I am using next-i18next to translate my pages in my Next.JS app. I followed the basic tutorial and this works great for translating a page.
In the page login.tsx this code handles the translation:
const { i18n } = useTranslation();
const { language: currentLanguage } = i18n;
const locales = router.locales ?? [currentLanguage];
const languageNames = useMemo(() => {
return new Intl.DisplayNames([currentLanguage], {
type: 'language',
});
}, [currentLanguage]);
const onToggleLanguageClick = (newLocale: string) => {
const { pathname, asPath, query } = router
router.push({ pathname, query }, asPath, { locale: newLocale })
}
Note that Intl.DisplayNames here is just to translate my locale such as "en" into the language name "English".
This is rendered as such:
<div className="flex w-56 justify-between">
{locales.map( (locale) => {
return <button key={locale} onClick={(e) => onToggleLanguageClick(locale)}>{capitalize(languageNames.of(locale) ?? locale)}</button>
})}
</div>
Until here all is great, but I now want to move this logic out of the page and into a Component "Navbar", so that the user can select their language from there. The "Navbar" Component can then be re-used across the website.
This is the Navbar, and it is included directly in the Login page as a Component. For some reason the page takes forever to load when I do this. There is clearly some underlying error but I am too new with Next.JS and React to understand what the issue is. If someone could help me would be fantastic!
import {useState} from "react";
import { useTranslation } from 'next-i18next'
import {useRouter} from "next/router";
import {useCallback, useMemo} from "react";
export default function Navbar() {
const { i18n } = useTranslation();
const { language: currentLanguage } = i18n;
const router = useRouter();
const locales = router.locales ?? [currentLanguage];
const languageNames = useMemo(() => {
return new Intl.DisplayNames([currentLanguage], {
type: 'language',
});
}, [currentLanguage]);
const onToggleLanguageClick = useCallback((newLocale: string) => {
return ((e: any) => {
const { pathname, asPath, query } = router
router.push({ pathname, query }, asPath, { locale: newLocale })
})
}, [router]);
return (
<>
{locales.map( (locale) => {
return <li key={locale}>
<div onClick={onToggleLanguageClick(locale)}
className="flex items-center space-x-2 px-4 py-2 hover:bg-gray-100 hover:cursor-pointer dark:hover:bg-gray-600 dark:hover:text-white"><span>{capitalize(languageNames.of(locale) ?? locale)}</span></div>
</li>
})}
</>
)
}
const capitalize = (lang: string) => {
return lang.slice(0, 1).toUpperCase() + lang.slice(1);
};