TL;DR: This npm module provides a simple, reactive client-side javascript solution for project internationalization (i18n) using next export
/config: export
for Next.js' app router
.
Version 3 of the module supports the app
router exclusively.
Because next-export-i18n
works with actual static exported pages, it operates exclusively on the client side. Therefore, you can only use it in client components
. You must add the "use client"
directive on top of the file.
Install it on your command line by running npm install --save-dev next-export-i18n
.
If you're migrating from the pages
directory to the app
router, look at the `migration guide.
To use next-export-i18n
with Next.js' traditional pages
directory, use the latest version of the major version 2
. We'll update this branch with new features. To install it, use the semver range ^2
.
The complete npm command would be: npm install --save-dev next-export-i18n@^2
To add the next-export-i18n
, follow a few basic steps.
- Run
yarn add next-export-i18n
ornpm install next-export-i18n
. - Create a top-level-folder
i18n
and Add yourJSON translation files
similar to the listings below
{
"headline": "City: Paris",
"link": {
"text": "Top 10 Bistros in Paris ",
"href": "/paris-bistros"
}
}
File: ./i18n/translations.en.json
{
"headline": "Stadt: Paris",
"link": {
"text": "Die 10 besten Bistros in Paris ",
"href": "/paris-bistros"
}
}
File: ./i18n/translations.de.json
- Create the
i18n/index.js
, and userequire
to add yourtranslation files
. Use the configuration object to customizenext-export-i18n
to your liking.
var en = require("./translations.en.json");
var de = require("./translations.de.json");
const i18n = {
translations: {
en,
de,
},
defaultLang: "en",
useBrowserDefault: true,
// optional property will default to "query" if not set
languageDataStore: "query" || "localStorage",
};
module.exports = i18n;
File: ./i18n/index.js
- Add the translation hook
useTranslation
and theLanguageSwitcher
component to your code. Then, add the reactive translations using thet()
function.Next-export-i18n
updates them automatically immediately when you change the language through theLanguageSwitcher
component.
If you choose the query
param (the default method) to store your language selection, remember that every internal link requires the search parameter lang
on the href' attribute. By adding this, we tell the destination which language to render. The linked page would fall back to the default language without the search parameter. To simplify this, you can use the
LinkWithLocalecomponent which automatically adds the
lang-parameter to each link while preserving all search parameters you've added to the URL (see
?share=social` in the example listing).
Look at the listing below for an example implementation.
"use client"
import {
useTranslation,
LanguageSwitcher,
LinkWithLocale
} from "next-export-i18n";
export default function Component({}) {
const { t } = useTranslation();
return (
<div>
<header>
<nav>
<LanguageSwitcher lang="de">Deutsch</LanguageSwitcher>
<LanguageSwitcher lang="en">English</LanguageSwitcher>
</nav>
</header>
<main>
<h1>t('headline')</h1>
<LinkWithLocale href={t("link.href")}>
{t("link.text")}
</LinkWithLocale>
</main>
</div>
);
File: ./component.js
Since v10.0.0 Next.js already has support for internationalized (i18n) routing out-of-the-box. You can provide a list of locales, a default and domain-specific locales, and Next.js automatically handles the routing. It streamlines the touring and locale parsing for nearly all existing l18n library solutions available for Next.js such as react-intl
, react-i18next
, lingui
, rosetta
, next-intl
.
Unfortunately, Next.js
i18n-routing does not supports next export
.
Note that Internationalized Routing does not integrate with
next export
as next export does not leverage the Next.js routing layer. Hybrid Next.js applications that do not use next export are fully supported.
This means that none of the i18n-libraries (utilizing the built-in i18n-routing) can support fully static sites generated with next export
.
Wait, what is happening here? They explicitly mention support for server-side rendering!
react-i18next is optimally suited for server-side rendering
To complement this, next-i18next provides the remaining functionality – management of translation content and components/hooks to translate your React components – while fully supporting SSG/SSR, multiple namespaces, code-splitting, etc.
https://github.com/isaachinman/next-i18next
They all support pre-rendered sites which are served with Next.js
- whereas next export
creates a truly static page which can be served with any webserver (e.g. nginx, apache, etc.).
For the different types of pre-rendering in Next.js
, take a look at my article The two and a half + one flavours of Next.js
's pre-rendering
, which explains and summarizes the different options.
With next-export-i18n
, you can add true reactive client-side internationalization to your static-generated projects.
You can configure next-export-i18n
to match the needs of your project.
The interface for the i18n-content is similar to react-i18next/next-i18next
; identical to them, we add the translated content through the t(key.to.translation)
function that we receive from the useTranslation
-hook.
Let's look at a simple example:
"use client"
import {useTranslation} from "next-export-i18n";
export default function Component({}) {
const { t } = useTranslation();
const translatedHeadline = t('headline');
return (
<h1>{translatedHeadline}</h1>
);
}
File: component.js
You must provide a JSON
file in the ./i18n
subfolder for each language.
Below is an example listing of how they could look like.
{
"headline": "City: Paris",
"link": {
"text": "Top 10 Bistros in Paris ",
"href": "/paris-bistros"
}
}
_File: ./i18n/translations.en.json
If you prefer a more readable format, you can use yaml
files and convert them to the required JSON
format during the build step. A common library for that would be yamljs.
Please remember not to use dots in your JSON
property names. The module uses the dots to determine link keys; for example: t("link.headline")
refers to the translated content string "City: Paris"
The module renders the key back to the site in case the key is not part of the language files to indicate and remind you of missing translations.
Let's look at an example configuration file i18n/index.js
.
// First, we load all translation files.
var en = require("./translations.en.json");
var de = require("./translations.de.json");
// Then we need to set up our configuration;
// Here, we add the translations under the particular
// language key and then configuring the module.
const i18n = {
translations: {
en: en.i18n,
de: de.i18n,
},
defaultLang: "de",
languageDataStore: "localStorage",
useBrowserDefault: true,
};
File: ./i18n/index.js
Next-export-i18n
has only a few important configuration options. Let's look at them in detail.
A string, for Example: "en"
We use the defaultLang
property to set the default language. Remember, this language key needs to be available in your translation configuration.
Either "localStorage"
or "query"
With the configuration property languageDataStore
, you tell next-export-i18n
to either add a query
parameter (default) lang
to your URLs or store the selected language in the browser's localStorage
.
Either true
or false
If you use true
, we use the browser's language instead of the configuration's defaultLang
to determine the default language setting. Remember that next-export-i18n
considers only the primary subtag, e.g., en-US
from the will be read as en
and will use the translations you added under ènin the
i18n/index.js`file.
When you use the query
param (default) to store your language selection, every internal link requires the search parameter lang
on the `href' attribute. Otherwise, the destination will not show the content in the selected language; instead, the application will fall back to the default language.
You can use the LinkWithLocale
component to automatically add the lang
-parameter to each link while preserving all search parameters you've added to the URL (see ?share=social
in the example listing). Look at the listing below for an example implementation.
"use client"
import {LinkWithLocale} from 'next-export-i18n';
export default function Component({ }) {
return (
<LinkWithLocale href="/paris-sights?share=social">
Link to /paris-sights
</LinkWithLocale>
);
}
File: component.js
Next-export-i18n
provides a convenient out-of-the-box to switch between the available languages. It preserves an existing search parameter on the current URL, and you can use the [data-language-switcher]
and [data-is-current="true"]
to style the component.
Look at the listing below for an example implementation.
"use client"
import {LanguageSwitcher} from 'next-export-i18n';
export default function Component({ }) {
return (
<nav>
<LanguageSwitcher lang="de">Deutsch</LanguageSwitcher>
<LanguageSwitcher lang="en">English</LanguageSwitcher>
</nav>
);
}
File: component.js
Let's say we want to display a username or set the number of top locations depending on the number of locations we receive from an API. For those kinds of dynamic text, you can add a moustache template in the translation.json
strings and update them dynamically.
Let's look at an example implementation where we replace the fixed number 10
in the string Top 10 Bistros in Paris
with a dynamic number.
{
"headline": "City: Paris",
"link": {
"text": "Top {{count}} Bistros in Paris ",
"href": "/paris-bistros"
}
}
File: translation.json
"use client"
import {useTranslation} from "next-export-i18n";
export default function Component({}) {
const { t } = useTranslation();
const numberOfItems = 10;
const translatedContent = t('link.text', { count: numberOfItems }))
// translatedContent will be "Top 10 Bistros in Paris"
return (
<h1>{translatedContent}</h1>
);
}
File: component.js
We have an example implementation at next-export-i18n-example.vercel.app and its source code at github: https://github.com/martinkr/next-export-i18n-example
to showcase next-export-i18n
and to give you an example of how to use the module.
Next.js v14.0.0 replaces the next export
command with the configuration setting "output": "export"
.
Add this to the next.config.js
in your application's root directory. The listing below shows a stripped down minimal example.
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export'
}
File: ./next.config.js Run the export command below:
npm run build
# or
yarn build
Then, you can use npx serve ./out
to see your exported project in your web browser or deploy the ./out
directory to your existing web server.
- next.js: >= 13.0.0
- react.js: >=18.0.0
- jest: ^27.5.1
- typescript: ^4.9.5
It is licensed under the MIT license. MIT - http://www.opensource.org/licenses/mit-license.php