First, let's create a new Next.js project with the
npx create-next-app nextjs-i18n-example
As we mentioned earlier, the Next.js works well with existing i18n libraries (react-intl
.
cd nextjs-i18n-example
npm i react-intl
Translations and routing are two main pillars of internationalization. The previously added react-intl
library is going to handle translations and formatting. When it comes to routing, Next.js has next.config.js
file with the i18n
config.
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
i18n: {
// The locales you want to support in your app
locales: ["en", "fr"],
// The default locale you want to be used when visiting a non-locale prefixed path e.g. `/hello`
defaultLocale: "en",
},
};
module.exports = nextConfig;
The internationalized routing is available since
The next important thing is to add localization files. For that purpose, let's create a lang
directory. Within it, add two JSON files: en.json
and fr.json
. These files are going to hold translations for English and French, respectively. Below, you can see the project structure after adding the mentioned files.
nextjs-i18n-example
|-- lang
| |-- en.json
| |-- fr.json
|-- pages
| |-- api
| |-- _app.js
| |-- index.js
| |-- ...
|-- public
|-- ...
|-- package.json
|-- package-lock.json
Afterward, fill in localization files with messages that we will use later.
The en.json
file:
{
"page.home.head.title": "Next.js i18n example",
"page.home.head.meta.description": "Next.js i18n example - English",
"page.home.title": "Welcome to <b>Next.js i18n tutorial</b>",
"page.home.description": "You are currently viewing the homepage in English 🚀"
}
The fr.json
file:
{
"page.home.head.title": "Next.js i18n exemple",
"page.home.head.meta.description": "Next.js i18n exemple - Français",
"page.home.title": "Bienvenue à <b>Next.js i18n didacticiel</b>",
"page.home.description": "Vous consultez actuellement la page d'accueil en Français 🚀"
}
Internationalized routing and localization files are just the first part of the task. The second part is setting up the react-intl
library. Below, you can see what changes have been made in the _app.js
file.
import { useRouter } from "next/router";
import { IntlProvider } from "react-intl";
import en from "../lang/en.json";
import fr from "../lang/fr.json";
import "../styles/globals.css";
const messages = {
en,
fr,
};
function MyApp({ Component, pageProps }) {
const { locale } = useRouter();
return (
<IntlProvider locale={locale} messages={messages[locale]}>
<Component {...pageProps} />
</IntlProvider>
);
}
export default MyApp;
We did most of the work. The last step is to put all this together. Therefore, we are going to update the index.js
file under the pages directory. Below, you can find two approaches for accessing the localization messages, imperative and declarative. We've already covered
The index.js
file:
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import { FormattedMessage, useIntl } from "react-intl";
import styles from "../styles/Home.module.css";
export default function Home(props) {
const { locales } = useRouter();
const intl = useIntl();
const title = intl.formatMessage({ id: "page.home.head.title" });
const description = intl.formatMessage({ id: "page.home.head.meta.description" });
return (
<div className={styles.container}>
<Head>
<title>{title}</title>
<meta name="description" content={description} />
<link rel="icon" href="/favicon.ico" />
{/* Add hreflang links */}
<link rel="alternate" href="http://example.com" hrefLang="x-default" />
<link rel="alternate" href="http://example.com" hrefLang="en" />
<link rel="alternate" href="http://example.com/fr" hrefLang="fr" />
</Head>
<header>
<div className={styles.languages}>
{[...locales].sort().map((locale) => (
<Link key={locale} href="/" locale={locale}>
{locale}
</Link>
))}
</div>
</header>
<main className={styles.main}>
<h1 className={styles.title}>
<FormattedMessage id="page.home.title" values={{ b: (chunks) => <b>{chunks}</b> }} />
</h1>
<p className={styles.description}>
<FormattedMessage id="page.home.description" />
</p>
</main>
</div>
);
}
Congratulations! 🎉
You have successfully set up internationalization in your Next.js project.
More details and examples you can find in the
All code samples used in this article are available on the
I hope you found this guide useful.
Feel free to give me feedback in the comments.
Also Published Here