8

For the SEO purposes I need to set up English as default language -> mynextapp.com/ when user enters the website, he/she can choose between ENGLISH or FRENCH, if English is selected the url will change to mynextapp.com/en, if the French will be chosen -> mynextapp.com/fr

Currently I am using the build in option in Next - i18n:

i18n: {
    locales: ['en', 'fr'],
    defaultLocale: 'en',
},

But this allows me to have English only as a default path = mynextapp.com/

Language Switcher:

    <Link
        href="/"
        locale={router.locale === 'en' ? 'fr' : 'en'}
    >
        <a>Switch</a>
    </Link>

Is there a way how to handle the same language under different urls? So that when you click on "en" in language switcher, the url path should be myapp.com/en.

juliomalves
  • 42,130
  • 20
  • 150
  • 146
  • I'm not sure I understand what the issue is? Your default language, english in this case, will be available under `/` and `/en` routes. – juliomalves Mar 13 '21 at 17:25
  • @juliomalves yes, it is available when you manually add it to url, but when you click on Link, where I want to switch between Languages (en/fr) I get the new url path only for french language myapp.com/fr, but when I click on English the url is just myapp.com/ –  Mar 13 '21 at 17:36
  • Ah, so you want to force the english (default) locale to have `/en` in the URL when clicking that link. – juliomalves Mar 13 '21 at 17:48
  • Exactly. When you enter the website url should be myapp.com/ and it should be in English (as it is now) by default. But when you click on "en" in language switcher, the url path should be myapp.com/en (still in English) –  Mar 13 '21 at 17:51

2 Answers2

4

To force the default language to add the locale to the URL you could pass it to the href directly, and opt-out of automatically handling the locale prefixing by setting locale to false.

<Link href={`/${router.locale === 'en' ? 'fr' : 'en'}`} locale={false}>
    <a>Switch</a>
</Link>

If you want all your Links to behave this way, and also force the default locale on the URL, the same logic would need to be applied.

Assuming you have a link to the /about page, it would look like the following.

<Link href={`/${router.locale}/about`} locale={false}>
    <a>About Page</a>
</Link>

If using next/router to do the routing, the same logic can also be applied.

router.push(`/${router.locale}/about`, undefined, { locale: false });
juliomalves
  • 42,130
  • 20
  • 150
  • 146
  • Thank you for post, this could be correct, although when I click on English Flag and yes, it does set up url to myapp.com/en, but when I click on other link - let's say about us page, the url does not stay with /en, as it should. When I am on /fr path, the path is staying the same even when I click on other pages links. –  Mar 13 '21 at 17:57
  • You'll need to apply this to all the `Link`'s you have, so they all follow this same logic. You can create a wrapper around `Link` for reusability. – juliomalves Mar 13 '21 at 17:58
  • But that would just keep switching languages on every link, or am I missing something ? –  Mar 13 '21 at 18:02
  • I got it now! Makes perfect sense. Thanks! –  Mar 13 '21 at 18:06
  • If I could ask one more question, I am using Prismic as my "backend" CMS so I am fetching the links in my navbar from there based on it's id, so I can not specify each link as explained above (can be done only on buttons on pages". Do you have any experience with that ? –  Mar 13 '21 at 18:13
  • 1
    That may require some clarifications from you, so I would suggest you create a new question for it here on StackOverflow with the detailed issue you're having. – juliomalves Mar 13 '21 at 18:18
0

For future reference, I managed to get my code working by routing to the other language (2 locales, one of them default) and have the default prefix always in the URL by using the following redirecting logic in my language switcher:

i18n.changeLanguage(i18n.language === Locales.EN ? Locales.NL : Locales.EN);
router.push(
  `/${i18n.language}${router.pathname}`,
  `/${i18n.language}${router.asPath}`,
  {
    locale: false
  }
);