From dc11f350cf152496404295ca77205addef94f0b8 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Fri, 19 Jul 2024 20:43:18 +0530 Subject: [PATCH 1/8] add next-i18next package --- next.config.mjs | 8 +++-- package-lock.json | 89 ++++++++++++++++++++++++++++++++++++++++++----- package.json | 7 ++-- pages/_app.tsx | 15 ++------ 4 files changed, 93 insertions(+), 26 deletions(-) diff --git a/next.config.mjs b/next.config.mjs index 6b3d6dabffa..b719ff09955 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -15,14 +15,18 @@ const nextConfig = { eslint: { ignoreDuringBuilds: true }, - output: 'export', +// output: 'export', webpack(config, { isServer }) { if (!isServer) { config.resolve.fallback.fs = false; } return config; - } + }, + i18n:{ + defaultLocale: 'en', + locales: ['en', 'de'], +} }; const mdxConfig = withMDX({ diff --git a/package-lock.json b/package-lock.json index 738534b90ee..88c5e6ef6dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "fuse.js": "^7.0.0", "googleapis": "^133.0.0", "gray-matter": "^4.0.3", - "i18next": "^23.8.2", + "i18next": "^23.12.2", "jgexml": "^0.4.4", "js-cookie": "^3.0.5", "json-schema": "^0.4.0", @@ -47,6 +47,7 @@ "mermaid": "9.3.0", "moment": "^2.30.1", "next": "14.1.1", + "next-i18next": "^15.3.0", "next-mdx-remote": "^4.4.1", "node-fetch": "^3.3.2", "node-fetch-2": "npm:node-fetch@^2.7.0", @@ -56,7 +57,7 @@ "react-dom": "^18", "react-ga": "^3.3.1", "react-gtm-module": "^2.0.11", - "react-i18next": "^14.0.5", + "react-i18next": "^14.1.3", "react-scrollspy": "^3.4.3", "react-syntax-highlighter": "^15.5.0", "react-text-truncate": "^0.19.0", @@ -8774,6 +8775,15 @@ "@types/unist": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -16907,6 +16917,19 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "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/hoist-non-react-statics/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==" + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -17081,9 +17104,9 @@ } }, "node_modules/i18next": { - "version": "23.11.5", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.5.tgz", - "integrity": "sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==", + "version": "23.12.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.12.2.tgz", + "integrity": "sha512-XIeh5V+bi8SJSWGL3jqbTEBW5oD6rbP5L+E7dVQh1MNTxxYef0x15rhJVcRb7oiuq4jLtgy2SD8eFlf6P2cmqg==", "funding": [ { "type": "individual", @@ -17102,6 +17125,11 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/i18next-fs-backend": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.3.1.tgz", + "integrity": "sha512-tvfXskmG/9o+TJ5Fxu54sSO5OkY6d+uMn+K6JiUGLJrwxAVfer+8V3nU8jq3ts9Pe5lXJv4b1N7foIjJ8Iy2Gg==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -22903,6 +22931,51 @@ } } }, + "node_modules/next-i18next": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-15.3.0.tgz", + "integrity": "sha512-bq7Cc9XJFcmGOCLnyEtHaeJ3+JJNsI/8Pkj9BaHAnhm4sZ9vNNC4ZsaqYnlRZ7VH5ypSo73fEqLK935jLsmCvQ==", + "funding": [ + { + "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" + }, + { + "type": "individual", + "url": "https://locize.com" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2", + "@types/hoist-non-react-statics": "^3.3.4", + "core-js": "^3", + "hoist-non-react-statics": "^3.3.2", + "i18next-fs-backend": "^2.3.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "i18next": ">= 23.7.13", + "next": ">= 12.0.0", + "react": ">= 17.0.2", + "react-i18next": ">= 13.5.0" + } + }, + "node_modules/next-i18next/node_modules/core-js": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/next-mdx-remote": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", @@ -26685,9 +26758,9 @@ "integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw==" }, "node_modules/react-i18next": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.2.tgz", - "integrity": "sha512-FSIcJy6oauJbGEXfhUgVeLzvWBhIBIS+/9c6Lj4niwKZyGaGb4V4vUbATXSlsHJDXXB+ociNxqFNiFuV1gmoqg==", + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", + "integrity": "sha512-wZnpfunU6UIAiJ+bxwOiTmBOAaB14ha97MjOEnLGac2RJ+h/maIYXZuTHlmyqQVX1UVHmU1YDTQ5vxLmwfXTjw==", "dependencies": { "@babel/runtime": "^7.23.9", "html-parse-stringify": "^3.0.1" diff --git a/package.json b/package.json index 4dbbc4d939d..552400b4a9f 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "fuse.js": "^7.0.0", "googleapis": "^133.0.0", "gray-matter": "^4.0.3", - "i18next": "^23.8.2", + "i18next": "^23.12.2", "jgexml": "^0.4.4", "js-cookie": "^3.0.5", "json-schema": "^0.4.0", @@ -81,6 +81,7 @@ "mermaid": "9.3.0", "moment": "^2.30.1", "next": "14.1.1", + "next-i18next": "^15.3.0", "next-mdx-remote": "^4.4.1", "node-fetch": "^3.3.2", "node-fetch-2": "npm:node-fetch@^2.7.0", @@ -90,7 +91,7 @@ "react-dom": "^18", "react-ga": "^3.3.1", "react-gtm-module": "^2.0.11", - "react-i18next": "^14.0.5", + "react-i18next": "^14.1.3", "react-scrollspy": "^3.4.3", "react-syntax-highlighter": "^15.5.0", "react-text-truncate": "^0.19.0", @@ -154,4 +155,4 @@ "remark-mdx": "^3.0.1", "storybook": "^8.1.5" } -} \ No newline at end of file +} diff --git a/pages/_app.tsx b/pages/_app.tsx index 2f39eeb319c..fbbdf6ef032 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,6 +2,7 @@ import '../styles/globals.css'; import type { AppProps } from 'next/app'; import Head from 'next/head'; +import { appWithTranslation } from 'next-i18next'; import React from 'react'; import AlgoliaSearch from '@/components/AlgoliaSearch'; @@ -13,23 +14,12 @@ import { MDXProvider } from '@/components/MDX/MDX'; import NavBar from '@/components/navigation/NavBar'; import StickyNavbar from '@/components/navigation/StickyNavbar'; import AppContext from '@/context/AppContext'; -import { defaultLanguage, defaultNamespace, I18nProvider, languages, namespaces } from '@/utils/i18n'; -import loadLocales from '@/utils/locales'; /** * @description The MyApp component is the root component for the application. */ function MyApp({ Component, pageProps, router }: AppProps) { - const i18n = { - languages, - defaultLanguage, - namespaces, - defaultNamespace, - locales: loadLocales() - }; - return ( - @@ -52,8 +42,7 @@ function MyApp({ Component, pageProps, router }: AppProps) { - ); } -export default MyApp; +export default appWithTranslation(MyApp); From 58301ae9780b552228c6ec096d44550c2ce40e01 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Sat, 20 Jul 2024 12:42:49 +0530 Subject: [PATCH 2/8] add more config --- next-i18next.config.js | 10 ++++++++ next.config.mjs | 1 + pages/[lang]/index.tsx | 23 +++++++++++++++---- pages/[lang]/tools/cli.tsx | 22 ++++++++++++++---- {locales => public/locales}/de/common.json | 0 .../locales}/de/landing-page.json | 0 {locales => public/locales}/de/tools.json | 0 {locales => public/locales}/en/common.json | 0 .../locales}/en/landing-page.json | 0 {locales => public/locales}/en/tools.json | 0 10 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 next-i18next.config.js rename {locales => public/locales}/de/common.json (100%) rename {locales => public/locales}/de/landing-page.json (100%) rename {locales => public/locales}/de/tools.json (100%) rename {locales => public/locales}/en/common.json (100%) rename {locales => public/locales}/en/landing-page.json (100%) rename {locales => public/locales}/en/tools.json (100%) diff --git a/next-i18next.config.js b/next-i18next.config.js new file mode 100644 index 00000000000..071f5aa5da5 --- /dev/null +++ b/next-i18next.config.js @@ -0,0 +1,10 @@ +module.exports = { + i18n: { + languages: ['en', 'de'], + defaultLocale : 'en', + namespaces: ['landing-page', 'common', 'tools'], + defaultNamespace: 'landing-page', + react: { useSuspense: false },// this line + }, + +}; diff --git a/next.config.mjs b/next.config.mjs index b719ff09955..cd1408e35a9 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -26,6 +26,7 @@ const nextConfig = { i18n:{ defaultLocale: 'en', locales: ['en', 'de'], + react: { useSuspense: false },// this line } }; diff --git a/pages/[lang]/index.tsx b/pages/[lang]/index.tsx index 20e7e90db7e..fef9a478ace 100644 --- a/pages/[lang]/index.tsx +++ b/pages/[lang]/index.tsx @@ -1,3 +1,5 @@ +import { useTranslation } from 'next-i18next'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import React from 'react'; import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; @@ -26,7 +28,7 @@ import Testimonial from '../../components/Testimonial'; import Heading from '../../components/typography/Heading'; import Paragraph from '../../components/typography/Paragraph'; import TextLink from '../../components/typography/TextLink'; -import { getAllLanguageSlugs, getLanguage, useTranslation } from '../../utils/i18n'; +import { getAllLanguageSlugs } from '../../utils/i18n'; /** * @description The HomePage is the landing page of the website. @@ -244,12 +246,25 @@ export async function getStaticPaths() { * @param {object} params The language parameter. * @returns {object} The language content for the landing page. */ -export async function getStaticProps({ params }: any) { - const language = getLanguage(params.lang); +// export async function getStaticProps({ params }: any) { +// const language = getLanguage(params.lang); +// return { +// props: { +// language +// } +// }; +// } + +export async function getStaticProps({ locale }) { return { props: { - language + ...(await serverSideTranslations(locale, [ + 'common', + 'tools', + 'landing-page' + ])) + // Will be passed to the page component as props } }; } diff --git a/pages/[lang]/tools/cli.tsx b/pages/[lang]/tools/cli.tsx index 8e3434b9fc6..9d1a96e0b30 100644 --- a/pages/[lang]/tools/cli.tsx +++ b/pages/[lang]/tools/cli.tsx @@ -1,5 +1,6 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { BadgeCheckIcon, CodeIcon, DocumentAddIcon, GlobeIcon } from '@heroicons/react/outline'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import React from 'react'; import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; @@ -11,7 +12,7 @@ import CodeBlock from '../../../components/editor/CodeBlock'; import GenericLayout from '../../../components/layout/GenericLayout'; import Heading from '../../../components/typography/Heading'; import Paragraph from '../../../components/typography/Paragraph'; -import { getAllLanguageSlugs, getLanguage, useTranslation } from '../../../utils/i18n'; +import { getAllLanguageSlugs, useTranslation } from '../../../utils/i18n'; interface Feature { name: string; @@ -254,12 +255,25 @@ export async function getStaticPaths() { * @param { params: { lang: string } } * @returns { props: { language: string } } */ -export async function getStaticProps({ params }: any) { - const language = getLanguage(params.lang); +// export async function getStaticProps({ params }: any) { +// const language = getLanguage(params.lang); +// return { +// props: { +// language +// } +// }; +// } + +export async function getStaticProps({ locale }) { return { props: { - language + ...(await serverSideTranslations(locale, [ + 'common', + 'tools', + 'landing-page' + ])) + // Will be passed to the page component as props } }; } diff --git a/locales/de/common.json b/public/locales/de/common.json similarity index 100% rename from locales/de/common.json rename to public/locales/de/common.json diff --git a/locales/de/landing-page.json b/public/locales/de/landing-page.json similarity index 100% rename from locales/de/landing-page.json rename to public/locales/de/landing-page.json diff --git a/locales/de/tools.json b/public/locales/de/tools.json similarity index 100% rename from locales/de/tools.json rename to public/locales/de/tools.json diff --git a/locales/en/common.json b/public/locales/en/common.json similarity index 100% rename from locales/en/common.json rename to public/locales/en/common.json diff --git a/locales/en/landing-page.json b/public/locales/en/landing-page.json similarity index 100% rename from locales/en/landing-page.json rename to public/locales/en/landing-page.json diff --git a/locales/en/tools.json b/public/locales/en/tools.json similarity index 100% rename from locales/en/tools.json rename to public/locales/en/tools.json From 8e206040983e756f7e1a9da8954155585a8497cd Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Sat, 20 Jul 2024 12:45:13 +0530 Subject: [PATCH 3/8] fix type error --- pages/[lang]/index.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pages/[lang]/index.tsx b/pages/[lang]/index.tsx index fef9a478ace..2a3081dcfa4 100644 --- a/pages/[lang]/index.tsx +++ b/pages/[lang]/index.tsx @@ -241,11 +241,6 @@ export async function getStaticPaths() { }; } -/** - * @description This function fetches the language content for the landing page. - * @param {object} params The language parameter. - * @returns {object} The language content for the landing page. - */ // export async function getStaticProps({ params }: any) { // const language = getLanguage(params.lang); @@ -255,14 +250,20 @@ export async function getStaticPaths() { // } // }; // } - -export async function getStaticProps({ locale }) { +/** + * @description This function fetches the language content for the landing page. + * @param {object} params The language parameter. + * @returns {object} The language content for the landing page. + */ +export async function getStaticProps({ locale }:{ + locale: string +}) { return { props: { ...(await serverSideTranslations(locale, [ 'common', 'tools', - 'landing-page' + 'landing-page' ])) // Will be passed to the page component as props } From 0480429d84171edbe3afb7455cbbcae910163c54 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Sat, 20 Jul 2024 14:06:42 +0530 Subject: [PATCH 4/8] use nextjs default mdx provider --- components/MDX/MDX.tsx | 2 +- mdx-components.tsx | 10 ++++++++++ pages/[lang]/tools/cli.tsx | 16 ++++------------ pages/_app.tsx | 6 +----- pages/index.tsx | 11 +++++++++-- 5 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 mdx-components.tsx diff --git a/components/MDX/MDX.tsx b/components/MDX/MDX.tsx index 36cddf7aa6a..4d3b8e1f230 100644 --- a/components/MDX/MDX.tsx +++ b/components/MDX/MDX.tsx @@ -330,7 +330,7 @@ export function getMDXComponents() { }; } -const mdxComponents = getMDXComponents(); +export const mdxComponents = getMDXComponents(); interface MDXProviderProps { children: React.ReactNode; diff --git a/mdx-components.tsx b/mdx-components.tsx new file mode 100644 index 00000000000..bf8be01bdbc --- /dev/null +++ b/mdx-components.tsx @@ -0,0 +1,10 @@ +import type { MDXComponents } from 'mdx/types'; + +import { mdxComponents } from '@/components/MDX/MDX'; + +export function useMDXComponents(components: MDXComponents): MDXComponents { + return { + ...components, + mdxComponents + }; +} diff --git a/pages/[lang]/tools/cli.tsx b/pages/[lang]/tools/cli.tsx index 9d1a96e0b30..e6dfecf72fb 100644 --- a/pages/[lang]/tools/cli.tsx +++ b/pages/[lang]/tools/cli.tsx @@ -255,23 +255,15 @@ export async function getStaticPaths() { * @param { params: { lang: string } } * @returns { props: { language: string } } */ -// export async function getStaticProps({ params }: any) { -// const language = getLanguage(params.lang); - -// return { -// props: { -// language -// } -// }; -// } - -export async function getStaticProps({ locale }) { +export async function getStaticProps({ locale }:{ + locale: string +}) { return { props: { ...(await serverSideTranslations(locale, [ 'common', 'tools', - 'landing-page' + 'landing-page' ])) // Will be passed to the page component as props } diff --git a/pages/_app.tsx b/pages/_app.tsx index fbbdf6ef032..50733d45310 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,7 +2,6 @@ import '../styles/globals.css'; import type { AppProps } from 'next/app'; import Head from 'next/head'; -import { appWithTranslation } from 'next-i18next'; import React from 'react'; import AlgoliaSearch from '@/components/AlgoliaSearch'; @@ -10,7 +9,6 @@ import ScrollButton from '@/components/buttons/ScrollButton'; import Banner from '@/components/campaigns/Banner'; import Footer from '@/components/footer/Footer'; import Layout from '@/components/layout/Layout'; -import { MDXProvider } from '@/components/MDX/MDX'; import NavBar from '@/components/navigation/NavBar'; import StickyNavbar from '@/components/navigation/StickyNavbar'; import AppContext from '@/context/AppContext'; @@ -24,7 +22,6 @@ function MyApp({ Component, pageProps, router }: AppProps) { -
@@ -40,9 +37,8 @@ function MyApp({ Component, pageProps, router }: AppProps) {
-
); } -export default appWithTranslation(MyApp); +export default MyApp; diff --git a/pages/index.tsx b/pages/index.tsx index 348311a7aa2..06e181a96e6 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,4 +1,6 @@ -import { languageDetection } from '@/utils/i18n'; + +import { useRouter } from 'next/navigation'; +import { useEffect } from 'react'; import Head from '../components/Head'; @@ -8,7 +10,12 @@ import Head from '../components/Head'; export default function HomePage() { const loader: string = 'img/loaders/loader.png'; // preloader image for the tools - languageDetection(); + const router = useRouter(); + + useEffect(() => { + console.log('object'); + router.push('/en'); + }, [router]); return ( <> From e10baf2d4d653089cc34399e1e24ef5aea4e4578 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Sat, 20 Jul 2024 16:21:47 +0530 Subject: [PATCH 5/8] removed all the older i18n files --- components/NewsletterSubscribe.tsx | 2 +- components/buttons/GithubButton.tsx | 3 +- components/link.tsx | 4 +- components/navigation/NavBar.tsx | 5 +- next.config.mjs | 1 + pages/[lang]/index.tsx | 8 +- pages/[lang]/tools/cli.tsx | 3 + pages/_app.tsx | 6 +- pages/index.tsx | 7 +- utils/i18n.ts | 17 +++ utils/i18n.tsx | 211 ---------------------------- utils/i18nPaths.ts | 16 --- utils/locales.ts | 21 --- 13 files changed, 43 insertions(+), 261 deletions(-) create mode 100644 utils/i18n.ts delete mode 100644 utils/i18n.tsx delete mode 100644 utils/i18nPaths.ts delete mode 100644 utils/locales.ts diff --git a/components/NewsletterSubscribe.tsx b/components/NewsletterSubscribe.tsx index 5b7c70aae7e..b6695c25bef 100644 --- a/components/NewsletterSubscribe.tsx +++ b/components/NewsletterSubscribe.tsx @@ -1,9 +1,9 @@ +import { useTranslation } from 'next-i18next'; import { useState } from 'react'; import { ButtonType } from '@/types/components/buttons/ButtonPropsType'; import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; -import { useTranslation } from '../utils/i18n'; import Button from './buttons/Button'; import Loader from './Loader'; import Heading from './typography/Heading'; diff --git a/components/buttons/GithubButton.tsx b/components/buttons/GithubButton.tsx index 571972d0869..a8986ae5b51 100644 --- a/components/buttons/GithubButton.tsx +++ b/components/buttons/GithubButton.tsx @@ -1,7 +1,8 @@ +import { useTranslation } from 'next-i18next'; + import { ButtonIconPosition, ButtonSize } from '@/types/components/buttons/ButtonPropsType'; import type { IButtonDefaultProps } from '../../types/components/buttons/types'; -import { useTranslation } from '../../utils/i18n'; import IconGithub from '../icons/Github'; import Button from './Button'; diff --git a/components/link.tsx b/components/link.tsx index d415f090ab2..0f6be66d2bf 100644 --- a/components/link.tsx +++ b/components/link.tsx @@ -1,8 +1,7 @@ import Link from 'next/link'; import { useRouter } from 'next/router'; -import { defaultLanguage, languages } from '../utils/i18n'; -import i18nPaths from '../utils/i18nPaths'; +import { defaultLanguage, i18nPaths, languages } from '@/utils/i18n'; interface LinkComponentProps { children: React.ReactNode; @@ -44,6 +43,7 @@ export default function LinkComponent({ // Detect current language based on the path or query parameter const slug = asPath.split('/')[1]; + const langSlug = languages.includes(slug) && slug; const language: string = query.lang && typeof query.lang === 'string' ? query.lang : langSlug || defaultLanguage; // Ensure language is always a string diff --git a/components/navigation/NavBar.tsx b/components/navigation/NavBar.tsx index 56cda97c5c0..1684c8da987 100644 --- a/components/navigation/NavBar.tsx +++ b/components/navigation/NavBar.tsx @@ -1,10 +1,11 @@ import Link from 'next/link'; import type { NextRouter } from 'next/router'; import { useRouter } from 'next/router'; +import { useTranslation } from 'next-i18next'; import { useEffect, useState } from 'react'; -import { defaultLanguage, languages, useTranslation } from '../../utils/i18n'; -import i18nPaths from '../../utils/i18nPaths'; +import { defaultLanguage, i18nPaths, languages } from '@/utils/i18n'; + import { SearchButton } from '../AlgoliaSearch'; import AsyncAPILogo from '../AsyncAPILogo'; import GithubButton from '../buttons/GithubButton'; diff --git a/next.config.mjs b/next.config.mjs index cd1408e35a9..e667c983c98 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -23,6 +23,7 @@ const nextConfig = { return config; }, + 'trailingSlash': true, i18n:{ defaultLocale: 'en', locales: ['en', 'de'], diff --git a/pages/[lang]/index.tsx b/pages/[lang]/index.tsx index 2a3081dcfa4..a1c68b37ea8 100644 --- a/pages/[lang]/index.tsx +++ b/pages/[lang]/index.tsx @@ -28,7 +28,7 @@ import Testimonial from '../../components/Testimonial'; import Heading from '../../components/typography/Heading'; import Paragraph from '../../components/typography/Paragraph'; import TextLink from '../../components/typography/TextLink'; -import { getAllLanguageSlugs } from '../../utils/i18n'; +import { languages } from '@/utils/i18n'; /** * @description The HomePage is the landing page of the website. @@ -233,7 +233,11 @@ export default function HomePage() { * @returns {object} The paths object containing all language slugs. */ export async function getStaticPaths() { - const paths = getAllLanguageSlugs(); + const paths = languages.map((lang) => ({ + params: { + lang + } + })); return { paths, diff --git a/pages/[lang]/tools/cli.tsx b/pages/[lang]/tools/cli.tsx index e6dfecf72fb..9df071bc5bd 100644 --- a/pages/[lang]/tools/cli.tsx +++ b/pages/[lang]/tools/cli.tsx @@ -71,6 +71,7 @@ const features: Feature[] = [ * @description The CLI tools page that displays the AsyncAPI CLI tool. */ export default function CliPage() { + console.log('obfject'); const { t } = useTranslation('tools'); /** @@ -258,6 +259,8 @@ export async function getStaticPaths() { export async function getStaticProps({ locale }:{ locale: string }) { + console.log(locale); + return { props: { ...(await serverSideTranslations(locale, [ diff --git a/pages/_app.tsx b/pages/_app.tsx index 50733d45310..375a285d5a8 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,6 +2,7 @@ import '../styles/globals.css'; import type { AppProps } from 'next/app'; import Head from 'next/head'; +import { appWithTranslation } from 'next-i18next'; import React from 'react'; import AlgoliaSearch from '@/components/AlgoliaSearch'; @@ -9,6 +10,7 @@ import ScrollButton from '@/components/buttons/ScrollButton'; import Banner from '@/components/campaigns/Banner'; import Footer from '@/components/footer/Footer'; import Layout from '@/components/layout/Layout'; +import { MDXProvider } from '@/components/MDX/MDX'; import NavBar from '@/components/navigation/NavBar'; import StickyNavbar from '@/components/navigation/StickyNavbar'; import AppContext from '@/context/AppContext'; @@ -19,6 +21,7 @@ import AppContext from '@/context/AppContext'; function MyApp({ Component, pageProps, router }: AppProps) { return ( + @@ -37,8 +40,9 @@ function MyApp({ Component, pageProps, router }: AppProps) { + ); } -export default MyApp; +export default appWithTranslation(MyApp); diff --git a/pages/index.tsx b/pages/index.tsx index 06e181a96e6..68412cfbfbd 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -12,10 +12,9 @@ export default function HomePage() { const router = useRouter(); - useEffect(() => { - console.log('object'); - router.push('/en'); - }, [router]); +// useEffect(() => { +// router.push('/en'); +// }, [router]); return ( <> diff --git a/utils/i18n.ts b/utils/i18n.ts new file mode 100644 index 00000000000..cecf5e2cd66 --- /dev/null +++ b/utils/i18n.ts @@ -0,0 +1,17 @@ +interface I18nPaths { + [key: string]: string[]; +} + +export const i18nPaths: I18nPaths = { + en: [ + '', // Homepage Route + '/tools/cli' + ], + de: [ + '', // Homepage Route + '/tools/cli' + ] +}; + +export const languages = ['en', 'de']; +export const defaultLanguage = 'en'; diff --git a/utils/i18n.tsx b/utils/i18n.tsx deleted file mode 100644 index 34f3c7900d4..00000000000 --- a/utils/i18n.tsx +++ /dev/null @@ -1,211 +0,0 @@ -import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; -import i18next, { i18n, Module } from 'i18next'; -import { - initReactI18next, - useTranslation, - withTranslation, - Translation, - Trans, -} from 'react-i18next'; -import nextI18nextStaticSiteConfig from '../next-i18next-static-site.config'; - -// Translation exports from react-i18next -export { useTranslation, withTranslation, Translation, Trans }; - -interface Config { - languages: string[]; - defaultLanguage: string; - namespaces: string[]; - defaultNamespace: string; - allowHydration: boolean; - cookieName: string; -} - -const defaultConfig = { - allowHydration: true, - languages: ['en'], - defaultLanguage: 'en', - namespaces: ['common'], - defaultNamespace: 'common', - cookieName: 'lang', - cookieOptions: { expires: 365, path: '/' }, -}; - -const config: Config = { - ...defaultConfig, - languages: nextI18nextStaticSiteConfig.i18n.languages, - defaultLanguage: nextI18nextStaticSiteConfig.i18n.defaultLanguage, - namespaces: nextI18nextStaticSiteConfig.i18n.namespaces, - defaultNamespace: nextI18nextStaticSiteConfig.i18n.defaultNamespace, -}; - -export const languages = config.languages; -export const defaultLanguage = config.defaultLanguage; -export const namespaces = config.namespaces; -export const defaultNamespace = config.defaultNamespace; -export const defaultNamespace2 = config.defaultNamespace; -export const cookieName = config.cookieName; - -/** - * Creates an i18next instance with the provided locales and language. - * @param {Object} locales - The locales object containing translations for different languages and namespaces. - * @param {string} language - The language code representing the desired language. - * @returns {Object} - The initialized i18next instance. - */ -const createI18nextInstance = (locales: any, language: string): i18n => { - // i18n plugins to load - const plugins = [ - // - initReactI18next, - ]; - - plugins.map((plugin: Module) => i18next.use(plugin)); - plugins.map((plugin: Module) => i18next.use(plugin)); // @fix: remove in future - https://github.com/vercel/next.js/issues/53688 - - i18next.init({ - resources: locales, - cleanCode: true, - lng: language, - supportedLngs: config.languages, - fallbackLng: language ? language : config.defaultLanguage, - ns: config.namespaces, // String or array of namespaces to load - defaultNS: config.defaultNamespace, // Default namespace used if not passed to translation function - interpolation: { - escapeValue: false, // Not needed for react as it escapes by default - }, - react: { - useSuspense: false, // Not compatible with SSR - }, - load: 'languageOnly', // Remove if you want to use localization (en-US, en-GB) - }); - - return i18next; -}; - -let globalI18nextInstance: any = null; - -/** - * Returns a singleton instance of the i18next object with the specified language and locales. - * If the instance doesn't exist, it creates a new one; otherwise, it changes the language of the existing instance. - * @param {string} language - The language code representing the desired language. - * @param {Object} locales - The locales object containing translations for different languages and namespaces. - * @returns {Object} - The i18next instance. - */ -export const i18nextInstance = (language: string, locales: object): i18n => { - if (!globalI18nextInstance) { - globalI18nextInstance = createI18nextInstance(locales, language); - - return globalI18nextInstance; - } else { - globalI18nextInstance.changeLanguage(language); - - return globalI18nextInstance; - } -}; - -// Prevent rerender -let loaded = false; - -/** - * A React component that provides i18n functionality to the child components. - * @param {Object} props - The props object containing the i18n options and child components. - * @returns {JSX.Element|null} - The child components wrapped in the i18n provider, or null if hydration is not allowed. - */ -export const I18nProvider = (props: any) => { - const [hydration, setHydration] = useState(false); - - const options: any = { ...config, ...props.i18n }; - - if (!props.i18n?.locales) { - throw new Error('locales object was not passed into I18nProvider'); - } - - const router = useRouter(); - const { asPath, query } = router; - - // Detect the current language - const slug = asPath.split('/')[1]; - const langSlug = config.languages.includes(slug) && slug; - const language = ( - query.lang || - langSlug || - config.defaultLanguage - ).toString(); - - // Load only once, otherwise there will be an re-render infinite loop - if (!loaded) { - i18nextInstance(language, props.i18n.locales); - } - - const { i18n } = useTranslation(); - - useEffect(() => { - // Overwrite the current store - i18n.services.resourceStore.data = props.i18n.locales; - - // Required to display the updated translations - i18n.changeLanguage(language); - }, [i18n, language, props.i18n.locales]); - - useEffect(() => { - loaded = true; - i18n.changeLanguage(language); - }, [i18n, language]); - - useEffect(() => { - const hasWindow = typeof window !== 'undefined'; - if (hasWindow && options.allowHydration) { - setHydration(true); - } - }, [options.allowHydration]); - - return hydration ? props.children : null; -}; - -/** - * Retrieves all language slugs for use in Next.js dynamic routing. - * @returns {Object[]} - An array of objects, each containing the "params" property with the "lang" parameter for each language. - */ -export function getAllLanguageSlugs() { - return config.languages.map((lang: string) => { - return { params: { lang: lang } }; - }); -} - -/** - * Retrieves the valid language code based on the provided language. - * If the provided language is not valid, returns the default language. - * @param {string} lang - The language code to check for validity. - * @returns {string} - The valid language code. - */ -export function getLanguage(lang: string) { - return config.languages.includes(lang) ? lang : config.defaultLanguage; -} - -/** - * Detects the user's preferred language based on cookies and browser settings. - * If a preferred language is found, redirects the user to the corresponding language page. - */ -export const languageDetection = () => { - const router = useRouter(); - - useEffect(() => { - let browserLocale: string | undefined = - (navigator.languages && navigator.languages.length - ? navigator.languages[0] - : navigator.language) || undefined; - - if (browserLocale) { - browserLocale = browserLocale.slice(0, 2); - } - - if (browserLocale && languages.includes(browserLocale)) { - router.push('/' + browserLocale); - } else { - router.push('/' + defaultLanguage); - } - }, [router, defaultLanguage]); - - return null; -}; diff --git a/utils/i18nPaths.ts b/utils/i18nPaths.ts deleted file mode 100644 index 7a0c937c049..00000000000 --- a/utils/i18nPaths.ts +++ /dev/null @@ -1,16 +0,0 @@ -interface I18nPaths { - [key: string]: string[]; -} - -const i18nPaths: I18nPaths = { - en: [ - "", // Homepage Route - "/tools/cli" - ], - de: [ - "", // Homepage Route - "/tools/cli" - ] -}; - -export default i18nPaths; \ No newline at end of file diff --git a/utils/locales.ts b/utils/locales.ts deleted file mode 100644 index 00a34a0e9df..00000000000 --- a/utils/locales.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { languages, namespaces } from './i18n'; - -/** - * Loads all locales. - * @returns {object} - Returns an object containing all locales. - */ -function loadLocales(): Record> { - // Load all locales, required for next-i18n-static-site - const locales: Record> = {}; - languages.map((language) => { - locales[language] = {}; - namespaces.map((namespace) => { - locales[language][ - namespace - ] = require(`./../locales/${language}/${namespace}.json`); - }); - }); - return locales; -} - -export default loadLocales; From 19328ea3b8b0ef6f1da0c4790e1e34f6e620d122 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Mon, 22 Jul 2024 14:31:37 +0530 Subject: [PATCH 6/8] works --- next-i18next.config.js | 2 +- next.config.mjs | 10 +++--- pages/[lang]/index.tsx | 73 ++++++++++++++++++++------------------- pages/_document.tsx | 6 +++- utils/getStatic.ts | 57 ++++++++++++++++++++++++++++++ utils/i18n.ts | 4 +++ utils/languageDetector.ts | 8 +++++ utils/redirect.ts | 33 ++++++++++++++++++ 8 files changed, 151 insertions(+), 42 deletions(-) create mode 100644 utils/getStatic.ts create mode 100644 utils/languageDetector.ts create mode 100644 utils/redirect.ts diff --git a/next-i18next.config.js b/next-i18next.config.js index 071f5aa5da5..17bd6e563f2 100644 --- a/next-i18next.config.js +++ b/next-i18next.config.js @@ -1,6 +1,6 @@ module.exports = { i18n: { - languages: ['en', 'de'], + locales: ['en', 'de'], defaultLocale : 'en', namespaces: ['landing-page', 'common', 'tools'], defaultNamespace: 'landing-page', diff --git a/next.config.mjs b/next.config.mjs index e667c983c98..d55f9efa5a0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -24,11 +24,11 @@ const nextConfig = { return config; }, 'trailingSlash': true, - i18n:{ - defaultLocale: 'en', - locales: ['en', 'de'], - react: { useSuspense: false },// this line -} +// i18n:{ +// defaultLocale: 'en', +// locales: ['en', 'de'], +// react: { useSuspense: false },// this line +// } }; const mdxConfig = withMDX({ diff --git a/pages/[lang]/index.tsx b/pages/[lang]/index.tsx index a1c68b37ea8..23fe23c20af 100644 --- a/pages/[lang]/index.tsx +++ b/pages/[lang]/index.tsx @@ -1,8 +1,8 @@ import { useTranslation } from 'next-i18next'; -import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import React from 'react'; import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; +import { getStaticPaths, makeStaticProps } from '@/utils/getStatic'; import Button from '../../components/buttons/Button'; import GoogleCalendarButton from '../../components/buttons/GoogleCalendarButton'; @@ -28,7 +28,10 @@ import Testimonial from '../../components/Testimonial'; import Heading from '../../components/typography/Heading'; import Paragraph from '../../components/typography/Paragraph'; import TextLink from '../../components/typography/TextLink'; -import { languages } from '@/utils/i18n'; + +const getStaticProps = makeStaticProps(['landing-page', 'footer']); + +export { getStaticPaths, getStaticProps }; /** * @description The HomePage is the landing page of the website. @@ -232,44 +235,44 @@ export default function HomePage() { * @description This function generates all language slugs for the landing page. * @returns {object} The paths object containing all language slugs. */ -export async function getStaticPaths() { - const paths = languages.map((lang) => ({ - params: { - lang - } - })); +// export async function getStaticPaths() { +// const paths = languages.map((lang) => ({ +// params: { +// lang +// } +// })); - return { - paths, - fallback: false - }; -} +// return { +// paths, +// fallback: false +// }; +// } -// export async function getStaticProps({ params }: any) { -// const language = getLanguage(params.lang); +// // export async function getStaticProps({ params }: any) { +// // const language = getLanguage(params.lang); +// // return { +// // props: { +// // language +// // } +// // }; +// // } +// /** +// * @description This function fetches the language content for the landing page. +// * @param {object} params The language parameter. +// * @returns {object} The language content for the landing page. +// */ +// export async function getStaticProps({ locale }:{ +// locale: string +// }) { // return { // props: { -// language +// ...(await serverSideTranslations(locale, [ +// 'common', +// 'tools', +// 'landing-page' +// ])) +// // Will be passed to the page component as props // } // }; // } -/** - * @description This function fetches the language content for the landing page. - * @param {object} params The language parameter. - * @returns {object} The language content for the landing page. - */ -export async function getStaticProps({ locale }:{ - locale: string -}) { - return { - props: { - ...(await serverSideTranslations(locale, [ - 'common', - 'tools', - 'landing-page' - ])) - // Will be passed to the page component as props - } - }; -} diff --git a/pages/_document.tsx b/pages/_document.tsx index 76bceeecc8e..83ec776e2f3 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,5 +1,7 @@ import Document, { Head, Html, Main, NextScript } from 'next/document'; +import i18nextConfig from '../next-i18next.config'; + class MyDocument extends Document { static async getInitialProps(ctx: any) { const initialProps = await Document.getInitialProps(ctx); @@ -8,8 +10,10 @@ class MyDocument extends Document { } render() { + const currentLocale = this.props.__NEXT_DATA__.query.locale || i18nextConfig.i18n.defaultLocale; + return ( - + {/* Load Work Sans font */} diff --git a/utils/getStatic.ts b/utils/getStatic.ts new file mode 100644 index 00000000000..73b1e257255 --- /dev/null +++ b/utils/getStatic.ts @@ -0,0 +1,57 @@ +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; + +import i18nextConfig from '../next-i18next.config'; + +console.log(i18nextConfig.i18n.locales); + +/** + * Retrieves the internationalization paths for the supported locales. + * @returns An array of paths for each supported locale. + */ +export const getI18nPaths = () => + i18nextConfig.i18n.locales.map((lng) => ({ + params: { + lang: lng + } + })); + +/** + * Retrieves the static paths for Next.js. + * @returns An object containing the fallback value and an array of paths. + */ +export const getStaticPaths = () => ({ + fallback: false, + paths: getI18nPaths() +}); + +/** + * Retrieves the internationalization props for a given context and namespaces. + * @param ctx - The context object containing the locale parameter. + * @param ns - An array of namespaces to be loaded. + * @returns An object containing the internationalization props. + */ +export async function getI18nProps(ctx, ns = ['common']) { + const locale = ctx?.params?.lang; + + console.log(locale, 'here'); + const props = { + ...(await serverSideTranslations(locale, ns)) + }; + + return props; +} + +/** + * Creates static props for Next.js based on the given namespaces. + * @param ns - An object containing the namespaces to be loaded. + * @returns A function that retrieves the static props. + */ +export function makeStaticProps(ns = {}) { + return async function getStaticProps(ctx) { + console.log(ctx, 'ctx'); + + return { + props: await getI18nProps(ctx, ns) + }; + }; +} diff --git a/utils/i18n.ts b/utils/i18n.ts index cecf5e2cd66..899fafde605 100644 --- a/utils/i18n.ts +++ b/utils/i18n.ts @@ -1,3 +1,5 @@ +import { useTranslation } from 'next-i18next'; + interface I18nPaths { [key: string]: string[]; } @@ -15,3 +17,5 @@ export const i18nPaths: I18nPaths = { export const languages = ['en', 'de']; export const defaultLanguage = 'en'; + +export { useTranslation }; diff --git a/utils/languageDetector.ts b/utils/languageDetector.ts new file mode 100644 index 00000000000..e3db95e0f17 --- /dev/null +++ b/utils/languageDetector.ts @@ -0,0 +1,8 @@ +import languageDetector from 'next-language-detector'; + +import i18nextConfig from '../next-i18next.config'; + +export default languageDetector({ + supportedLngs: i18nextConfig.i18n.locales, + fallbackLng: i18nextConfig.i18n.defaultLocale +}); diff --git a/utils/redirect.ts b/utils/redirect.ts new file mode 100644 index 00000000000..3e96df4046d --- /dev/null +++ b/utils/redirect.ts @@ -0,0 +1,33 @@ +import { useEffect } from 'react' +import { useRouter } from 'next/router' +import languageDetector from './languageDetector' + +export const useRedirect = (to) => { + const router = useRouter() + to = to || router.asPath + + // language detection + useEffect(() => { + const detectedLng = languageDetector.detect() + if (to.startsWith('/' + detectedLng) && router.route === '/404') { // prevent endless loop + router.replace('/' + detectedLng + router.route) + return + } + + languageDetector.cache(detectedLng) + router.replace('/' + detectedLng + to) + }) + + return <> +}; + +export const Redirect = () => { + useRedirect() + return <> +} + +// eslint-disable-next-line react/display-name +export const getRedirect = (to) => () => { + useRedirect(to) + return <> +} \ No newline at end of file From 038c7244019fe815b1c6e98d3a23c7af4dcbcbc8 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Mon, 22 Jul 2024 14:46:47 +0530 Subject: [PATCH 7/8] add redirect and browser language detection --- package-lock.json | 34 ++++++++++++++++++++ package.json | 1 + pages/index.tsx | 10 ++---- utils/redirect.ts | 79 +++++++++++++++++++++++++++++------------------ 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88c5e6ef6dd..b605ab8e9d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,6 +48,7 @@ "moment": "^2.30.1", "next": "14.1.1", "next-i18next": "^15.3.0", + "next-language-detector": "^1.1.0", "next-mdx-remote": "^4.4.1", "node-fetch": "^3.3.2", "node-fetch-2": "npm:node-fetch@^2.7.0", @@ -17125,6 +17126,14 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/i18next-browser-languagedetector": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.0.tgz", + "integrity": "sha512-U00DbDtFIYD3wkWsr2aVGfXGAj2TgnELzOX9qv8bT0aJtvPV9CRO77h+vgmHFBMe7LAxdwvT/7VkCWGya6L3tA==", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/i18next-fs-backend": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.3.1.tgz", @@ -22976,6 +22985,31 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/next-language-detector": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-language-detector/-/next-language-detector-1.1.0.tgz", + "integrity": "sha512-TLXMSqweKrrIID0a+PxotItN8MBwIurso3oyz9Odq1VPv3/sdrSpfam2V2eoF462+ibjtSW/P0Xs7gFmeA4Ktw==", + "dependencies": { + "@babel/runtime": "7.16.7", + "i18next-browser-languagedetector": "7.2.0" + } + }, + "node_modules/next-language-detector/node_modules/@babel/runtime": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz", + "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/next-language-detector/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, "node_modules/next-mdx-remote": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-4.4.1.tgz", diff --git a/package.json b/package.json index 552400b4a9f..6f8217b4d7f 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "moment": "^2.30.1", "next": "14.1.1", "next-i18next": "^15.3.0", + "next-language-detector": "^1.1.0", "next-mdx-remote": "^4.4.1", "node-fetch": "^3.3.2", "node-fetch-2": "npm:node-fetch@^2.7.0", diff --git a/pages/index.tsx b/pages/index.tsx index 68412cfbfbd..0d1abb2d691 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,8 +1,6 @@ -import { useRouter } from 'next/navigation'; -import { useEffect } from 'react'; - import Head from '../components/Head'; +import { Redirect } from '../utils/redirect'; /** * @description This is the home page which is the first page that loads when the user visits the website. @@ -10,11 +8,7 @@ import Head from '../components/Head'; export default function HomePage() { const loader: string = 'img/loaders/loader.png'; // preloader image for the tools - const router = useRouter(); - -// useEffect(() => { -// router.push('/en'); -// }, [router]); + Redirect(); return ( <> diff --git a/utils/redirect.ts b/utils/redirect.ts index 3e96df4046d..4004835d534 100644 --- a/utils/redirect.ts +++ b/utils/redirect.ts @@ -1,33 +1,52 @@ -import { useEffect } from 'react' -import { useRouter } from 'next/router' -import languageDetector from './languageDetector' - -export const useRedirect = (to) => { - const router = useRouter() - to = to || router.asPath - - // language detection - useEffect(() => { - const detectedLng = languageDetector.detect() - if (to.startsWith('/' + detectedLng) && router.route === '/404') { // prevent endless loop - router.replace('/' + detectedLng + router.route) - return - } - - languageDetector.cache(detectedLng) - router.replace('/' + detectedLng + to) - }) - - return <> +import { useRouter } from 'next/router'; +import { useEffect } from 'react'; + +import languageDetector from './languageDetector'; + +/** + * Custom hook that redirects the user to a specified URL or the current URL with a language prefix. + * @param to - The URL to redirect to. If not provided, the current URL will be used. + * @returns null + */ +export function useRedirect(to: string | undefined): any { + const router = useRouter(); + + const toUrl = to || router.asPath; + + // language detection + useEffect(() => { + const detectedLng = languageDetector.detect(); + + if (toUrl.startsWith(`/${detectedLng}`) && router.route === '/404') { // prevent endless loop + router.replace(`/${detectedLng}${router.route}`); + + return; + } + + languageDetector.cache(detectedLng); + router.replace(`/${detectedLng}${toUrl}`); + }); + + return null; }; +/** + * Component that redirects the user to the current URL with a language prefix. + * @returns null + */ export const Redirect = () => { - useRedirect() - return <> -} - -// eslint-disable-next-line react/display-name -export const getRedirect = (to) => () => { - useRedirect(to) - return <> -} \ No newline at end of file + useRedirect(undefined); + + return null; +}; + +/** + * Higher-order function that returns a component that redirects the user to a specified URL with a language prefix. + * @param to - The URL to redirect to. + * @returns A component that redirects the user to the specified URL. + */ +export const getRedirect = (to: string) => () => { + useRedirect(to); + + return null; +}; From 8c48d6fd244b626620d5ba42d675db8b40662fd2 Mon Sep 17 00:00:00 2001 From: JeelRajodiya Date: Mon, 22 Jul 2024 14:50:38 +0530 Subject: [PATCH 8/8] add new i18n config --- pages/[lang]/tools/cli.tsx | 70 ++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/pages/[lang]/tools/cli.tsx b/pages/[lang]/tools/cli.tsx index 9df071bc5bd..09f0d7157f6 100644 --- a/pages/[lang]/tools/cli.tsx +++ b/pages/[lang]/tools/cli.tsx @@ -1,10 +1,11 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { BadgeCheckIcon, CodeIcon, DocumentAddIcon, GlobeIcon } from '@heroicons/react/outline'; -import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import React from 'react'; import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; import { ParagraphTypeStyle } from '@/types/typography/Paragraph'; +import { getStaticPaths, makeStaticProps } from '@/utils/getStatic'; +import { useTranslation } from '@/utils/i18n'; import Button from '../../../components/buttons/Button'; import GithubButton from '../../../components/buttons/GithubButton'; @@ -12,7 +13,10 @@ import CodeBlock from '../../../components/editor/CodeBlock'; import GenericLayout from '../../../components/layout/GenericLayout'; import Heading from '../../../components/typography/Heading'; import Paragraph from '../../../components/typography/Paragraph'; -import { getAllLanguageSlugs, useTranslation } from '../../../utils/i18n'; + +const getStaticProps = makeStaticProps(['tools', 'footer']); + +export { getStaticPaths, getStaticProps }; interface Feature { name: string; @@ -238,37 +242,37 @@ export default function CliPage() { ); } -/** - * @description Get the language for the CLI page. - * @returns { paths: { params: { lang: string } }[]; fallback: boolean } - */ -export async function getStaticPaths() { - const paths = getAllLanguageSlugs(); +// /** +// * @description Get the language for the CLI page. +// * @returns { paths: { params: { lang: string } }[]; fallback: boolean } +// */ +// export async function getStaticPaths() { +// const paths = getAllLanguageSlugs(); - return { - paths, - fallback: false - }; -} +// return { +// paths, +// fallback: false +// }; +// } -/** - * @description Get the language for the CLI page. - * @param { params: { lang: string } } - * @returns { props: { language: string } } - */ -export async function getStaticProps({ locale }:{ - locale: string -}) { - console.log(locale); +// /** +// * @description Get the language for the CLI page. +// * @param { params: { lang: string } } +// * @returns { props: { language: string } } +// */ +// export async function getStaticProps({ locale }:{ +// locale: string +// }) { +// console.log(locale); - return { - props: { - ...(await serverSideTranslations(locale, [ - 'common', - 'tools', - 'landing-page' - ])) - // Will be passed to the page component as props - } - }; -} +// return { +// props: { +// ...(await serverSideTranslations(locale, [ +// 'common', +// 'tools', +// 'landing-page' +// ])) +// // Will be passed to the page component as props +// } +// }; +// }