To properly internationalize your Next.js project and make it multilingual, there are two biggest problems to solve:
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:
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.
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
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 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.
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. That 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.
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:
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.
Now, when your project is ready to be translated, you might have the following setup:
en.js
or en.json
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:
main
.staging
and start translating it so your content is already multilingual when you release it.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.
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:
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.
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.
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 MoreReleased on Sep 25, 2022
Updated on Aug 28, 2024
Published by Community
Identifier:nextjs-localization