feat: add i18n internationalization (#560)

* chore: add next-i18next

* feat: add i8n-config

* feat: i18n config to next config

* feat: wrap app with the appWithTranslation

* feat: add initial dummy translation

* chore: pin version

* feat: add translation

Co-authored-by: Deepak Prabhakara <deepak@boxyhq.com>
This commit is contained in:
Nafees Nazik 2022-10-08 23:24:43 +05:30 committed by GitHub
parent 8ccdcdcb86
commit 05eeb7f491
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 226 additions and 10 deletions

3
locales/en/common.json Normal file
View File

@ -0,0 +1,3 @@
{
"back": "Back"
}

9
next-i18next.config.js Normal file
View File

@ -0,0 +1,9 @@
const path = require('path');
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
localePath: path.resolve('./locales'),
};

View File

@ -1,7 +1,10 @@
const { i18n } = require('./next-i18next.config');
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
i18n,
output: 'standalone',
webpack: (config, { webpack, isServer }) => {
if (isServer) {

204
package-lock.json generated
View File

@ -23,6 +23,7 @@
"micromatch": "4.0.5",
"next": "12.3.1",
"next-auth": "4.12.2",
"next-i18next": "12.0.1",
"next-mdx-remote": "4.1.0",
"nodemailer": "6.8.0",
"raw-body": "2.5.1",
@ -1350,6 +1351,15 @@
"@types/unist": "*"
}
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/js-yaml": {
"version": "4.0.5",
"license": "MIT"
@ -2710,6 +2720,16 @@
"node": ">= 0.6"
}
},
"node_modules/core-js": {
"version": "3.25.3",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.3.tgz",
"integrity": "sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/core-js-pure": {
"version": "3.24.1",
"dev": true,
@ -4268,6 +4288,22 @@
"node": "*"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"dependencies": {
"void-elements": "3.1.0"
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"license": "MIT",
@ -4304,6 +4340,33 @@
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/i18next": {
"version": "21.9.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz",
"integrity": "sha512-00fVrLQOwy45nm3OtC9l1WiLK3nJlIYSljgCt0qzTaAy65aciMdRy9GsuW+a2AtKtdg9/njUGfRH30LRupV7ZQ==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"dependencies": {
"@babel/runtime": "^7.17.2"
}
},
"node_modules/i18next-fs-backend": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.5.tgz",
"integrity": "sha512-raTel3EfshiUXxR0gvmIoqp75jhkj8+7R1LjB006VZKPTFBbXyx6TlUVhb8Z9+7ahgpFbcQg1QWVOdf/iNzI5A=="
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"license": "MIT",
@ -6060,6 +6123,41 @@
}
}
},
"node_modules/next-i18next": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-12.0.1.tgz",
"integrity": "sha512-i1yLpOvokldjqnnkP4KfZtnbp2+DILlUvavzJ9rvCSu1Yk5w45IRAYrJfu20/0WDeWxea/ktYDmXw+z/2roo3g==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"dependencies": {
"@babel/runtime": "^7.18.9",
"@types/hoist-non-react-statics": "^3.3.1",
"core-js": "^3",
"hoist-non-react-statics": "^3.3.2",
"i18next": "^21.9.1",
"i18next-fs-backend": "^1.1.5",
"react-i18next": "^11.18.4"
},
"engines": {
"node": ">=12"
},
"peerDependencies": {
"next": ">= 10.0.0",
"react": ">= 16.8.0"
}
},
"node_modules/next-mdx-remote": {
"version": "4.1.0",
"license": "MPL-2.0",
@ -6907,11 +7005,31 @@
"react-dom": ">=16"
}
},
"node_modules/react-i18next": {
"version": "11.18.6",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz",
"integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==",
"dependencies": {
"@babel/runtime": "^7.14.5",
"html-parse-stringify": "^3.0.1"
},
"peerDependencies": {
"i18next": ">= 19.0.0",
"react": ">= 16.8.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-syntax-highlighter": {
"version": "15.5.0",
@ -8700,6 +8818,14 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@ -15631,6 +15757,15 @@
"@types/unist": "*"
}
},
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/js-yaml": {
"version": "4.0.5"
},
@ -16454,6 +16589,11 @@
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
},
"core-js": {
"version": "3.25.3",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.3.tgz",
"integrity": "sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ=="
},
"core-js-pure": {
"version": "3.24.1",
"dev": true
@ -17442,6 +17582,22 @@
"highlight.js": {
"version": "10.7.3"
},
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
}
},
"html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"requires": {
"void-elements": "3.1.0"
}
},
"http-errors": {
"version": "2.0.0",
"requires": {
@ -17460,6 +17616,19 @@
"version": "8.0.1",
"dev": true
},
"i18next": {
"version": "21.9.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-21.9.2.tgz",
"integrity": "sha512-00fVrLQOwy45nm3OtC9l1WiLK3nJlIYSljgCt0qzTaAy65aciMdRy9GsuW+a2AtKtdg9/njUGfRH30LRupV7ZQ==",
"requires": {
"@babel/runtime": "^7.17.2"
}
},
"i18next-fs-backend": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.5.tgz",
"integrity": "sha512-raTel3EfshiUXxR0gvmIoqp75jhkj8+7R1LjB006VZKPTFBbXyx6TlUVhb8Z9+7ahgpFbcQg1QWVOdf/iNzI5A=="
},
"iconv-lite": {
"version": "0.4.24",
"requires": {
@ -18436,6 +18605,20 @@
"uuid": "^8.3.2"
}
},
"next-i18next": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-12.0.1.tgz",
"integrity": "sha512-i1yLpOvokldjqnnkP4KfZtnbp2+DILlUvavzJ9rvCSu1Yk5w45IRAYrJfu20/0WDeWxea/ktYDmXw+z/2roo3g==",
"requires": {
"@babel/runtime": "^7.18.9",
"@types/hoist-non-react-statics": "^3.3.1",
"core-js": "^3",
"hoist-non-react-statics": "^3.3.2",
"i18next": "^21.9.1",
"i18next-fs-backend": "^1.1.5",
"react-i18next": "^11.18.4"
}
},
"next-mdx-remote": {
"version": "4.1.0",
"requires": {
@ -18908,11 +19091,19 @@
"goober": "^2.1.10"
}
},
"react-i18next": {
"version": "11.18.6",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.6.tgz",
"integrity": "sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==",
"requires": {
"@babel/runtime": "^7.14.5",
"html-parse-stringify": "^3.0.1"
}
},
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-syntax-highlighter": {
"version": "15.5.0",
@ -19947,6 +20138,11 @@
"unist-util-stringify-position": "^3.0.0"
}
},
"void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="
},
"webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",

View File

@ -57,13 +57,14 @@
"micromatch": "4.0.5",
"next": "12.3.1",
"next-auth": "4.12.2",
"next-i18next": "12.0.1",
"next-mdx-remote": "4.1.0",
"nodemailer": "6.8.0",
"raw-body": "2.5.1",
"react-hot-toast": "2.4.0",
"react-syntax-highlighter": "15.5.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hot-toast": "2.4.0",
"react-syntax-highlighter": "15.5.0",
"sharp": "0.31.1",
"swr": "1.3.0"
},

View File

@ -3,7 +3,7 @@ import type { Session } from 'next-auth';
import { SessionProvider } from 'next-auth/react';
import { useRouter } from 'next/router';
import { Toaster } from 'react-hot-toast';
import { appWithTranslation } from 'next-i18next';
import { AccountLayout } from '@components/layouts';
import '../styles/globals.css';
@ -30,4 +30,4 @@ function MyApp({
);
}
export default MyApp;
export default appWithTranslation<never>(MyApp);

View File

@ -5,10 +5,13 @@ import toast from 'react-hot-toast';
import Link from 'next/link';
import { ArrowLeftIcon } from '@heroicons/react/24/outline';
import classNames from 'classnames';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import jackson from '@lib/jackson';
import { useTranslation } from 'next-i18next';
const New: NextPage<{ providers: any }> = ({ providers }) => {
const { t } = useTranslation('common');
const router = useRouter();
const [loading, setLoading] = React.useState(false);
const [directory, setDirectory] = React.useState({
@ -62,7 +65,7 @@ const New: NextPage<{ providers: any }> = ({ providers }) => {
<Link href='/admin/directory-sync'>
<a className='btn btn-outline items-center space-x-2'>
<ArrowLeftIcon aria-hidden className='h-4 w-4' />
<span>Back</span>
<span>{t('back')}</span>
</a>
</Link>
<h2 className='mb-5 mt-5 font-bold text-gray-700 md:text-xl'>New Directory</h2>
@ -153,12 +156,13 @@ const New: NextPage<{ providers: any }> = ({ providers }) => {
);
};
export const getServerSideProps: GetServerSideProps = async () => {
export const getServerSideProps: GetServerSideProps = async ({ locale }) => {
const { directorySyncController } = await jackson();
return {
props: {
providers: directorySyncController.providers(),
...(await serverSideTranslations(locale ?? '', ['common'])),
},
};
};