6

I would like my Next.js app to remember which language the user prefers, therefore I want to store it in a cookie on client side. I have 2 language options: EN & FR.

By default the language is set up for English (no cookie, myapp.com/), but once the user clicks on EN preference, the URL changes to myapp.com/en and this selected language should be stored. The same applies for French.

const [language, setLanguage] = useState(false);

        <Link
            href={`/${router.locale === 'en' ? 'fr' : 'en'}`}
            locale={false}
        >
            <a
                onClick={() => {
                    setLanguage((language) => !language);
                    // setCookie({});
                }}
            >
                {` ${language ? 'en' : 'fr'}`}
            </a>

Where and how can I use the cookie or session storage so the backend can see it?

juliomalves
  • 42,130
  • 20
  • 150
  • 146
  • 1
    Might be worth having a read through [Leveraging the NEXT_LOCALE cookie](https://nextjs.org/docs/advanced-features/i18n-routing#leveraging-the-next_locale-cookie). – juliomalves Mar 13 '21 at 22:09
  • `const setCookie = (locale) => { document.cookie = NEXT_LOCALE=${locale}; window.location.reload();}` This was my set up with calling the setCookie in my onClick function, but no luck with that. –  Mar 13 '21 at 22:36
  • What have you tried so far? Did you get any errors? – Camilo Mar 14 '21 at 00:59
  • @Camilo I tried what I mentioned in my previous comment. Using Next_Locale stored in hook, which I called in my onClick function, which would work, but I don’t really know what to call inside the function -onClick setCookie() –  Mar 14 '21 at 01:37

1 Answers1

11

You can leverage the NEXT_LOCALE cookie to persist the user's language preference. This will override the accept-language header that is usually used by Next.js built-in i18n.

This function sets a cookie with an expiry date of one year from now, at the root path of the domain.

const setCookie = (locale) => {
    document.cookie = `NEXT_LOCALE=${locale}; max-age=31536000; path=/`
}

Recommendation: Unrelated to the issue you raised, I would also recommend you use a button rather than an anchor to handle the language switching, as it's doing more than just simple navigation at this point.

<button
    onClick={() => {
        const locale = router.locale === 'en' ? 'fr' : 'en'
        setCookie(locale)
        router.push(router.asPath, undefined, { locale })
    }}
>
    {router.locale === 'en' ? 'fr' : 'en'}
</button>
Davey
  • 2,355
  • 1
  • 17
  • 18
juliomalves
  • 42,130
  • 20
  • 150
  • 146
  • 1
    your recommendation is bad (or poorly coded at least), as if it's a language selector inside another route, with your suggestion the route would completely change and go to the root page instead of the page where the user is – Soldeplata Saketos Nov 15 '21 at 07:26
  • 2
    @SoldeplataSaketos The example is a direct conversion of OP's code to use `router.push`. It wasn't meant as a generic language switch that could be used anywhere. That being said I might as well update it to fit that purpose. – juliomalves Nov 15 '21 at 08:41