Next.js Localization Free

i18n & l10n in Next.js projects (Pages Router)

Try Crowdin

Next.js localization

Copy link

To properly internationalize your Next.js project and make it multilingual, there are two biggest problems to solve:

  1. Project Internationalization
  2. Content Localization

Next.js Internationalization

Copy link

Internationalization (i18n) is a process of making a project ready to be multilingual. For effective Next.js internationalization, consider the following aspects in your projects:

Next.js multilingual routing

Copy link

Multilingual routing is a built-in feature starting from Next.js version v10 and a huge helper. Localized routing is here for several reasons. You want to preserve a preferred locale while the user browses around or shares an URL and give search bots a better idea about how your multilingual website is structured.

Next.js would allow you to store locale in a domain name (sub-domains like fr.crowdin.com and TLD crowdin.ee) or as a Sub-path of the URL, i.e., https://crowdin.com/ee/, https://crowdin.com/fr.

To add Next.js multilanguage to your project, you want to add the respective config to your next.config.js file.

Sample for Sub-path Routing Config

Copy link
module.exports = {
  i18n: {
    locales: ['en-US', 'ee', 'fr'],
    defaultLocale: 'en-US',
  },
}

If your project is already in production, all your existing pages will open as usual, but you will get new URLs available:

  • /ee/page
  • /fr/page

Sample Domain Routing

Copy link

Storing a locale in a domain name is another way to keep your Next.js project aware of which language the current visitor prefers. While this approach is usually more tricky and expensive (you should own proper TLDs), it is believed to bring some SEO benefits and has a better brand impact. This method improves Next.js localization and can streamline Next.js translation efforts for a better user experience.

Below is your next.config.js config template.

module.exports = {
  i18n: {
    locales: ['en-US', 'fr', 'ee'],
    defaultLocale: 'en-US',
    domains: [{
        domain: 'crowdin.com',
        defaultLocale: 'en-US',
      }, {
        domain: 'crowdin.ee',
        defaultLocale: 'fr',
      }, {
        domain: 'fr.crowdin.com',
        defaultLocale: 'fr-FR',
        locales: ['fr-BE'],
      }],
  },
}

Note: All domains crowdin.com, crowdin.ee, fr.crowdin.com, fr-be.crowdin.com should be pointed to your server.

You might have noticed that the configuration for the French locale has additional locales property. If you use a locale with a region format (like fr-FR), you can list all the language dialects that should lead to this locale.

Next.js Internationalization (i18n)

Copy link

Next.js i18n does not have a recommended approach for content localization. So you can choose a toolset depending on content type and needs. The content you publish can also be in a variety of formats. UI elements usually reside in the resource files (in key-value files), and articles might come from your headless CMS or Markdown files.

Using plain JSON files to store Next.js localization keys

Copy link

A regular JSON file might be everything you need if you work on a simple project like a Blog.

{
  "blog.header": "Sample Next.js",
  "blog.date": "Posted by {{author}}",
}

Avoid concatenating strings that will be localized. Use placeholders like {{author}} instead of giving translators more context. Placeholders usually help get better-quality translations.

Translators might still need more information about how your keys are used in the UI. Usually, you can provide more contextual information for your keys in your TMS.

If you go with this hand-made localization approach, keep your JSON files in a separate directory and name with a ${locale-code}.json.

When the multilingual routing is done, you can find a locale property in the useRouter() hook. Th​at​ is a visitor's preferred locale. Require a proper locale and use values from localized JSONs as myLocale.stringKey everywhere you need a text label in the UI.

Choosing an Next.js i18n library

Copy link

If you work on anything more complex than a Blog or a small, static website, you might want to consider having a specialized i18n library for your UI text management.

Here's a quick questionary that might help you decide:

  • Will you need plurals management? (UI labels like: "One file added" or "5 files added" depending on the quantity)
  • Will you have gender-dependent labels? (like: "Sebastian invited Victoria to his sandbox" or "Victoria invited Sebastian to her sandbox," depending on the gender of an actor)
  • Will you need complex formatting for currencies, dates, and numbers?

An i18n library would typically bring even more value than mentioned above, things like fallback management of untranslated keys, advanced context management, which is highly valuable and help to produce higher quality translations, and more. But integrating the i18n library might require a little more effort, especially if it's your first experience.

Some of the most frequently used i18n libs in Next.js projects are i18next, React Intl. And a more advanced like FBT and Project Fluent. FBT and FTL were developed and used by Facebook and Mozilla, respectively. They would guide you while creating your UI texts and guarantee the localization will be as good as possible for many languages.

Next.js Content Localization

Copy link

Now, when your project is ready to be translated, you might have the following setup:

One of the main objectives you want when building your workflow is that you don't want to speak to translators every time you change something in your source content. This is why a TMS is so important.

The workflow you are looking for might work like the following:

  • whenever you have a new branch in your GitHub with UI texts changed, those texts should be translated before you merge to main.
  • very likely, your headless CMS has a concept of branching or content stages. You want your translators to be aware of new content in staging and start translating it so your content is already multilingual when you release it.
  • most importantly, if it's not necessarily a new release but just a tiny text change, your TMS should detect the change and notify translators, so you don't have to.

That is what's called agile localization. And this is what Crowdin does for you. Crowdin would connect to your content repositories like GitHub and Headless CMS or would accept your files like PDFs, docx, Youtube subtitles and will make sure you are multilingual while staying agile.

Next.js translation quality management strategies

Copy link

Here at Crowdin, we believe that there are no terrible translators. Any bilingual person can deliver decent-quality translations. We had seen that many times when the community was doing a fantastic job translating games, knowledge bases, and open-source software.

What is killing translations' quality is a lack of context. Traditional translation tools would present translators with a list of texts. While not sure about the context, translators will make assumptions. Where assumptions are, errors are guaranteed.

Crowdin has a whole bunch of quality features, Glossaries for consistent terminology, and Collaboration features where the translator would ask a content creation if not sure about the meaning or text usage, and more.

But some things still are on developers. What you can do to increase high UI texts translations quality is this:

  • Provide textual information for every key in your resource files (this is where the i18n library is useful again, there's no easy way to add contextual information if you store your keys in plain JS object)
  • Provide screenshots, ideally setup an automated screenshots upload to Crowdin during your build process
  • Set up a Crowdin In-Context so translators can preview or even do translations on the live application. Crowdin In-Context can also be a source of the screenshots for your keys.

React Intl Sample Resource File

{
   "app.name":{
      "defaultMessage":"Umbrella Editor",
      "description":"an app name. Umbrella should not be translated"
   },
   "app.menu.save_as_label":{
      "defaultMessage":"Save as...",
      "description":"Used in main menu"
   }
}

When translating Markdown files or Rich Text content from your headless CMS, Crowdin will try to preserve as much context as possible by rendering a WYSIWYG view to translators.

Crowdin Markdown WYSIWYG

More Next.js localization features

Copy link

Automatic locale detection

That is surprisingly cool that Next.js will automatically check the Accept-Language header and redirect a visitor to the proper locale. Because visitors usually configure their operating system to the language they prefer, with this feature, they will see content in their locale even if they visit a default route. It is recommended to list all the dialects your visitors might have in their settings to give them an even better experience while browsing your website.

This feature is configured by the localeDetection property in your i18n config object. It is set as true by default.

It is recommended, though, to store the user-selected locale in a NEXT_LOCALE cookie. That is how Next.js will not do an auto-detect of the locale if a user prefers the en locale while having the fr locale configured in a browser.

Wrapping up

Copy link

Next.js is a modern framework made with localization in mind. Localization is not just internationalization or the actual translator's work, but it is always an investment as well as new development workflows. Book a demo with a Crowdin expert to find out what workflow will work best for your business.

Check out our complete code of a minimalistic Next.js app on Github or play with it on a CodeSandbox.

Crowdin is a platform that helps you manage and translate content into different languages. Integrate Crowdin with your repo, CMS, or other systems. Source content is always up to date for your translators, and translated content is returned automatically.

Learn More
Categories
Development
Works with
  • Crowdin Enterprise
  • crowdin.com
Details

Released on Sep 25, 2022

Updated on Aug 28, 2024

Published by Community

Identifier:nextjs-localization