Internationalization support for Next.js with static HTML export.
To install the library simply add the module.
You can use npm:
npm i next-locales
or i.e. Yarn if you prefer:
yarn add next-locales
Create a file in the root path of your Next.js project called: .i18nrc.json
.
This file stores the basic configuration needed for this library to run.
{
"localesDir": "./src/locales",
"locales": ["en", "pl"],
"defaultLocale": "en"
}
In the next step, edit your next.config.js
file, importing in it high order function withLocalesConfig
from this library.
Let it look something like this:
const { withLocalesConfig } = require('next-locales/server');
module.exports = withLocalesConfig({
// your custom Next.js config
});
Now we will go to the pages
directory. You may be using the src
directory, then the path might look like this: src/pages
. Here are all the pages on which Next.js works.
In this directory, edit the _app.jsx
or _app.tsx
file (if your project uses TypeScript). If such a file does not exist in your project, create it.
This is how it should look like in the simplest form:
import { AppProps as CustomAppProps } from 'next/app';
import { withLocales } from 'next-locales';
const CustomApp = ({ Component, pageProps }: CustomAppProps) => (
<Component {...pageProps} />
);
export default withLocales(CustomApp);
Now it's time to create a directory inside pages
or src/pages
.
Such directory must be named [locale]
.
Next, move all files and directories except for files such as: _app.jsx
, _document.jsx
, _error.jsx
, 404.jsx
or 500.jsx
(or .tsx
in the TypeScript case) that you previously had in the pages directory to this created directory.
The index.jsx
file (for the home page) should also be moved.
Since your home page has been moved to the new [locale]
directory, you should create a new file index.jsx
with the content as below:
import { createInitialIndexPage } from 'next-locales';
export default createInitialIndexPage();
This is needed to properly export the Next.js project with this library.
You translation files should be located at localesDir
set in the .i18nrc
file. This library supports two types of translations that you can use - JSON
and Yaml
.
Each language added to the locales
configuration array should have its file here with the same name. For example, pl.json
and en.json
(pl.yml
and en.yml
if you prefer Yaml).
en.yml
testing:
welcome: Hello {{ name }}!
userinfo:
age: Age
gender: Gender
pl.yml
testing:
welcome: Cześć {{ name }}!
userinfo:
age: Wiek
gender: Płeć
As you can see above - you can use placeholders.
This library implements Mustache
template system (https://github.com/janl/mustache.js) which enables this functionality.
For translations to work, you need to import high order functions - withLocalesStaticProps
and withLocalesStaticPaths
in each file where you want to use translation.
import {
withLocalesStaticProps,
withLocalesStaticPaths,
} from 'next-locales/server';
const ExamplePage = () => <div>This is an example page</div>;
export const getStaticProps = withLocalesStaticProps();
export const getStaticPaths = withLocalesStaticPaths();
export default ExamplePage;
If you need a custom getStaticProps
or getStaticPaths
function, just pass the function as the first HOC parameter. Like that:
export const getStaticProps = withLocalesStaticProps(async ({ params }) => {
const additionalProp = 'Hello World!';
return {
props: {
additionalProp,
},
};
});
export const getStaticPaths = withLocalesStaticPaths(() => ({
paths: ['/example', '/hello/world'],
fallback: false,
}));
If the implementation of getStaticProps
and getStaticPaths
is fine - you are ready to use your translations!
All you need at this point is to use the useTranslation
hook.
Full example:
import {
withLocalesStaticProps,
withLocalesStaticPaths,
} from 'next-locales/server';
const ExamplePage = () => {
const { t } = useTranslation();
return <div>{t('testing.welcome', { name: 'Guest' })}</div>;
};
export const getStaticProps = withLocalesStaticProps();
export const getStaticPaths = withLocalesStaticPaths();
export default ExamplePage;
The useTranslation hook returns the t
function. It takes a translation key as the first parameter, and an object for replacing placeholders as the second optional parameter.
This library provides a modified Link
component to be used for any links and redirects in the application. It provides support for locales.
import {
withLocalesStaticProps,
withLocalesStaticPaths,
} from 'next-locales/server';
import { Link } from 'next-locales';
const ExamplePage = () => <Link href="/example/page">Page</Link>;
export const getStaticProps = withLocalesStaticProps();
export const getStaticPaths = withLocalesStaticPaths();
export default ExamplePage;
To set the lang
attribute for the <html>
tag, create a custom document _document.jsx
file and use the getLangAttrValue
function:
import { Html, Head, Main, NextScript } from 'next/document';
import { getLangAttrValue } from 'next-locales/server';
const CustomDocument = ({ __NEXT_DATA__ }) => (
<Html lang={getLangAttrValue(__NEXT_DATA__)}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
export default CustomDocument;
To set the dir
attribute for the <html>
tag, you need to add a special __config
section in the translation file and provide a value for the dir
field:
en.yml
__config:
dir: rtl
The field value is validated. It currently takes the values ltr
, rtl
, and auto
. The default is ltr
.
The next step is to get the dir
value for the currently active locale.
You do this in a similar way as seen above, when setting the lang
attribute but here you are using a slightly different function with the name getDirAttrValue
:
import { Html, Head, Main, NextScript } from 'next/document';
import { getDirAttrValue } from 'next-locales/server';
const CustomDocument = ({ __NEXT_DATA__ }) => (
<Html dir={getDirAttrValue(__NEXT_DATA__)}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
export default CustomDocument;
This library also provides a util, with which you can get an object with the lang
and dir
fields with one function and insert it like this:
import { Html, Head, Main, NextScript } from 'next/document';
import { getHtmlLocaleAttributes } from 'next-locales/server';
const CustomDocument = ({ __NEXT_DATA__ }) => (
<Html {...getHtmlLocaleAttributes(__NEXT_DATA__)}>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
export default CustomDocument;
The use of this function may override the setting of the lang
and dir
attributes separately.
Thanks to Adriano Raiano (https://github.com/adrai) for sharing the library next-language-detector
(https://github.com/adrai/next-language-detector) which is used in this project.