Discover how to add translations to your Next.js application using "next-translate". From scratch to your first translations.
Next.js is a famous React framework used by a lot of companies. It brings a lot of features out of the box and allows to build optimized websites at the speed of light.
In one of their recent version, they realized a new feature called the "Internationalized Routing". To give you a heads up, it's built-in support to internationalize your website routes.
It means that by using this framework and an additional NextJS i18n library, you'll be able to share your website with as many countries as you want!
This step-by-step guide will teach you:
- How to initialize your Next.js application with "next-translate" (the i18n library that we will use)
- How to create translations and start localizing your website
- How to use the main translation feature (useTranslation hook)
Are you ready to deep dive? π
Why do we choose Next-Translate?
Before going further, you may wonder why we're using the next-translate library over the numerous translation libraries in NextJS.
Even if most of the i18n library solutions like "react-i18next", "next-i18next", "next-zero-intl", etc. share the same functionalities, "next-translate" is easy to use and configure with NextJS.
It was built for this framework, and the library maintainer tries to keep the package lightweight.
"π γ» Works well with automatic page optimization.
π¦ γ» Easy to use and configure.
π γ» Basic i18n support: interpolation, plurals, useTranslation hook, Trans componentβ¦
ποΈ γ» It loads only the necessary translations (for page and for locale).
π¦ γ» Tiny (~1kb) and tree shakable. No dependencies."β-βFrom the "next-translate" NPM package homepage
1. Create a new NextJS application
Note: You can skip to the next step if you already have an existing application.
Once you're ready, you can open your terminal and move it into your project folder. The first thing you need to do is initialize a new NextJS application.
Following their documentation, you will have to type the command below:
$ npx create-next-app@latest
If you don't have Next JS installed yet, it will prompt you to download it. You should accept this step.
The tool is ready a few moments later and will ask you to name your project. You can choose the name of your choice, but for the purposes of this guide, we will use "next-translate-app".
Now, you can move inside the newly created folder "next-translate-app" using the cd your-project-name command
(cd next-translate-app
).
Your folder tree should look like below:
.
βββ README.md
βββ next.config.js
βββ package-lock.json
βββ package.json
βββ pages
β βββ _app.js
β βββ api
β β βββ hello.js
β βββ index.js
βββ public
β βββ favicon.ico
β βββ vercel.svg
βββ styles
βββ Home.module.css
βββ globals.css
4 directories, 11 files
Note: I will share the folder tree with you whenever we create new folders and files in this tutorial. It will help you to see what you've done.
If you want the same output in your terminal, you can use thetree -I node_modules
command.
2. Install Next-Translate in your Next.jsΒ project
The next step of this tutorial is to install the NextJS i18n library that we will use.
Let's return to your terminal and type the command below to install the NPM package.
$ npm install next-translate
3. Setup Next-Translate in the Next JS configuration file
Each Next.js projects have a next.config.js file at the root repository. You will need to modify it to initialize the translations inside your project.
At the first file opening, you should have something this content:
module.exports = {
reactStrictMode: true,
};
You should import "next-translate" and export it as a module like below.
const nextTranslate = require('next-translate');
module.exports = nextTranslate({
reactStrictMode: true,
});
Note: As you mention, the old configuration object is passed as a parameter of our nextTranslate variable. If you want to pass more settings, you can do it inside this object.
4. Create an i18n configuration for Next-Translate
As the official documentation requires, you will need to create an i18n.js
file at the root repository to configure the library.
This step-by-step guide will stick to the main functionalities without going in-depth. I highly recommend you look at the documentation if you want to move further at the end.
Create a i18n.js
file at your root repository and insert:
module.exports = {
locales: ['en', 'fr'], // Array with the languages that you want to use
defaultLocale: 'en', // Default language of your website
pages: {
'*': ['common'], // Namespaces that you want to import per page (we stick to one namespace for all the application in this tutorial)
},
};
Now, your tree should look like below.
.
βββ README.md
βββ i18n.js
βββ next.config.js
βββ package-lock.json
βββ package.json
βββ pages
β βββ _app.js
β βββ api
β β βββ hello.js
β βββ index.js
βββ public
β βββ favicon.ico
β βββ vercel.svg
βββ styles
βββ Home.module.css
βββ globals.css
4 directories, 12 files
Note: If you want to understand better how translations are loaded, you can discover it in the Next-Translate documentation.
5. Create the NextJS translation files
You're almost ready to display your translated texts on your website, but there is one last step before diving into the code.
You'll need to create some translation files for your Next.js application. To do so, you must create a "translations" folder at your root repository. Inside it, you will have one folder per locale defined in the i18n.js
file (locales variable).
In our case, you'll have to create these folders: locales/en/
and locales/fr/
.
Then, inside these folders, you should create the files matching the namespaces you created in the i18n.js
file. In our case, we only have the "common" namespace, so you should create a common.json
file in each of these repositories.
Here how the tree should look like afterward:
.
βββ README.md
βββ i18n.js
βββ locales
β βββ en
β β βββ common.json
β βββ fr
β βββ common.json
βββ next.config.js
βββ package-lock.json
βββ package.json
βββ pages
β βββ _app.js
β βββ api
β β βββ hello.js
β βββ index.js
βββ public
β βββ favicon.ico
β βββ vercel.svg
βββ styles
βββ Home.module.css
βββ globals.css
7 directories, 14 files
Note: As an initial value, you can set an empty object in your translations files (
{}
).
6. Display your first internationalized text
Let's run our code and see the NextJS default page! You can do it by typing:
$ npm run dev
This step-by-step guide will keep the CSS style of the default index.js
page to focus on the translations. As a start, I invite you to replace the index.js
content with the code below.
import Head from 'next/head';
import styles from '../styles/Home.module.css';
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Next.js Localization with Next-Translate</title>
</Head>
<main className={styles.main}>
<h1 className={styles.title}>Welcome to my i18n NextJS application!</h1>
<p className={styles.description}>
I'm using the Next-Translate library to translate this page.
</p>
</main>
</div>
);
}
After saving, you should have this page.
Perfect! Our goal here will be to replace these static texts with dynamic ones. Thanks to the "next-translate" library, they will update depending on the selected language on the website and the translations you will define.
To do so, you can use the useTranslation
hook provided by "next-translate". This hook takes as a parameter the namespace that you want to load. In our case, it's "common" (refs: i18n.js
and the locales/
folder).
You can extract a t
function from the hook that takes a translation key (string
) as a parameter. This key corresponds to your translation name.
For this tutorial purpose, we will define the translations to see what happens when a translation for a key is missing.
import useTranslation from 'next-translate/useTranslation';
import Head from 'next/head';
import styles from '../styles/Home.module.css';
export default function Home() {
const { t } = useTranslation('common');
return (
<div className={styles.container}>
<Head>
<title>{t('metaTitle')}</title>
</Head>
<main className={styles.main}>
<h1 className={styles.title}>{t('title')}</h1>
<p className={styles.description}>{t('description')}</p>
</main>
</div>
);
}
After saving, you should see the following:
As you can see common
is the name of our namespace (ref: locales/[locale]/common.js
), and after the ":" you know the translation key.
That's what you see when the library can't find a translation for the namespace and key you provided.
Now, let's add a translation for each key. First, we need to list what are the keys we have:
- metaTitle
- title
- description
You can open the common.js
files for each language and start filling the translations for each of these keys. As an example:
-
locales/en/common.json
{
"metaTitle": "Next.js Localization with Next-Translate",
"title": "Welcome to my i18n NextJS application!",
"description": "I'm using the Next-Translate library to translate this page."
}
- locales/fr/common.json
{
"metaTitle": "Localisation de Next.js avec Next-Translate",
"title": "Bienvenue dans mon application NextJS i18n !",
"description": "J'utilise la bibliothèque Next-Translate pour traduire cette page."
}
Once your files are saved, you can refresh, and you should see all your missing translated replaced with your English text. Congrats! π
7. How to change from one language to theΒ other?
You're probably wondering: "Perfect, I see the English page⦠but, how can I see the French one?". Don't worry, it's pretty straightforward!
You can use the Next Link component with a locale parameter.
When you will click on it, you will be redirected to the page of your choice with the corresponding locale.
import useTranslation from 'next-translate/useTranslation';
import Head from 'next/head';
import Link from 'next/link';
import styles from '../styles/Home.module.css';
export default function Home() {
const { t } = useTranslation('common');
return (
<div className={styles.container}>
<Head>
<title>{t('metaTitle')}</title>
</Head>
<main className={styles.main}>
<h1 className={styles.title}>{t('title')}</h1>
<p className={styles.description}>{t('description')}</p>
<Link href="/" locale="en">
<h2>Anglais</h2>
</Link>
<Link href="/" locale="fr">
<h2>Français</h2>
</Link>
</main>
</div>
);
}
Tadamβ¦ π₯ You just finalized your first internationalized website!
Your website should look like below! If not, don't worry! All the Next JS localization example is available at the end of this step-by-step guide.
Bonus: How to manage translations 5X faster thanks to FlyCodeΒ π
As a developer, you have probably already had to modify texts on your website, maybe even several times the same translation.
These tasks are time-consuming, and sometimes the result is not exactly what was expected by your product team.
Now imagine software designed for your contributors that simplifies all this workflow by allowing them to interact with your application as if they were developers. It would free up your time and enable you to focus more on building features.
That's precisely why FlyCode was created!
But, as we say, a quick demonstration is always better than a lengthy introduction!
Convinced? π Here are a few articles that you can read and share with your team in addition to the Flycode website:
- How Product Managers can work like software engineers? π©βπ»
- How to edit your product like a π€
Code is available onΒ GitHub
If you want to retrieve the complete code and execute it, everything is available on the FlyCode GitHub.
GitHub => Next JS i18n Example with Next-Translate
I hope you liked this step-by-step guide! Follow FlyCode on Twitter to be notified when new content is available!
Top comments (2)
Great article!
One suggestion: A file structure presents locales/common.json but it should be locales/fr/common.json, WDYT?
Thanks, @maciejtatol!
Great suggestion! That's a mistake, and I just corrected it.
Here is further information about the folder structure: most libraries are configured this way to create one folder per language. When your website loads, it uses the corresponding folder for your selected locale.
It's a better project architecture; you can create many files (namespaces) for each locale. As an example, most of the time, you will have one namespace per page:
locales/fr/common.js
(common translations)locales/fr/home.js
(home page translations)locales/fr/contact.js
(contact page translations) and so on!