Last active
February 1, 2023 06:56
-
-
Save kachar/ee23a13dffa493179e835f3482f3b470 to your computer and use it in GitHub Desktop.
i18next + next.js 10 + Material UI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect } from 'react' | |
import Head from 'next/head' | |
import { AppProps } from 'next/app' | |
import { ThemeProvider } from '@material-ui/core/styles' | |
import CssBaseline from '@material-ui/core/CssBaseline' | |
import theme from 'common/theme' | |
import useNextLocale from 'common/useNextLocale' | |
export default function CustomApp(props: AppProps) { | |
const { Component, pageProps } = props | |
useNextLocale({ i18nResources: pageProps.i18nResources }) | |
useEffect(() => { | |
// Remove the server-side injected CSS. | |
const jssStyles = document.querySelector('#jss-server-side') | |
if (jssStyles && jssStyles.parentElement) { | |
jssStyles.parentElement.removeChild(jssStyles) | |
} | |
}, []) | |
return ( | |
<React.Fragment> | |
<Head> | |
<title>i18next + next.js</title> | |
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" /> | |
</Head> | |
<ThemeProvider theme={theme}> | |
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} | |
<CssBaseline /> | |
<Component {...pageProps} /> | |
</ThemeProvider> | |
</React.Fragment> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback } from 'react' | |
import { useRouter } from 'next/router' | |
import { useTranslation } from 'react-i18next' | |
import { Box, Button, ButtonGroup } from '@material-ui/core' | |
export default function LocaleSwitcher() { | |
const { t } = useTranslation() | |
const router = useRouter() | |
const changeLang = useCallback( | |
// Same route different language | |
(locale: string) => () => router.push(router.route, undefined, { locale }), | |
[], | |
) | |
return ( | |
<Box textAlign="center"> | |
<ButtonGroup | |
disableRipple | |
variant="outlined" | |
color="primary" | |
aria-label="text primary button group"> | |
<Button onClick={changeLang('bg')}>{t('BG')}</Button> | |
<Button onClick={changeLang('en')}>{t('EN')}</Button> | |
</ButtonGroup> | |
</Box> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import i18next from 'i18next' | |
import { useEffect } from 'react' | |
import { useRouter } from 'next/router' | |
import { initReactI18next } from 'react-i18next' | |
interface Translation { | |
[key: string]: string | |
} | |
interface Translations { | |
[namespace: string]: Translation | |
} | |
interface I18nResources { | |
translations: Translations | |
namespaces: string[] | |
} | |
type LocaleSetupProps = { | |
i18nResources: I18nResources | |
fallback?: string | |
} | |
export default function useNextLocale({ | |
i18nResources = { translations: {}, namespaces: ['common'] }, | |
}: LocaleSetupProps) { | |
const router = useRouter() | |
const { translations, namespaces } = i18nResources | |
const locale = router.locale || router.defaultLocale | |
if (!i18next.isInitialized) { | |
i18next.use(initReactI18next).init({ | |
lng: locale, | |
preload: locale ? [locale] : [], | |
ns: namespaces, | |
supportedLngs: router.locales, | |
fallbackLng: router.defaultLocale, | |
react: { useSuspense: false }, | |
}) | |
} | |
i18next.setDefaultNamespace(namespaces[0]) | |
if (locale) { | |
// Initialize language | |
if (!i18next.language) { | |
i18next.changeLanguage(locale) | |
} | |
for (const ns of namespaces) { | |
if (!i18next.hasResourceBundle(locale, ns)) { | |
i18next.addResourceBundle(locale, ns, translations[ns]) | |
} | |
} | |
} | |
useEffect(() => { | |
// if (!i18next?.language) return | |
if (!router.locale) return | |
// Handle router locale updates | |
if (i18next.language !== router.locale) { | |
i18next.changeLanguage(router.locale) | |
} | |
}, [i18next, router.locale]) | |
return { locale } | |
} | |
export async function getTranslations(locale: string | undefined, namespaces: string[]) { | |
const translations: Translations = {} | |
for (const ns of namespaces) { | |
const { default: data = {} }: { default: Translation } = await import( | |
`../../public/locales/${locale}/${ns}.json` // Adjust the correct path to public | |
) | |
translations[ns] = data | |
} | |
return { translations, namespaces } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment