The easiest way to translate your NextJs apps.
next-i18next is a plugin for Next.js projects that allows you to get translations up and running quickly and easily, while fully supporting SSR, multiple namespaces with codesplitting, etc.
While next-i18next uses i18next and react-i18next under the hood, users of next-i18next simply need to include their translation content as JSON files and don't have to worry about much else.
yarn add next-i18nextYou need to also have react and next installed.
By default, next-i18next expects your translations to be organised as such:
.
└── static
└── locales
├── en
| └── common.json
└── de
└── common.json
This structure can also be seen in the simple example.
If you want to structure your translations/namespaces in a custom way, you will need to pass modified localePath and localeStructure values into the initialisation config.
The default export of next-i18next is a class constructor, into which you pass your config options. The resulting class has all the methods you will need to translate your app:
import NextI18Next from 'next-i18next'
const NextI18NextInstance = new NextI18Next({
defaultLanguage: 'en',
otherLanguages: ['de']
})
export default NextI18NextInstance
/* Optionally, export class methods as named exports */
export const {
appWithTranslation,
withNamespaces,
} = NextI18NextInstanceA full list of options can be seen here.
It's recommended to export this NextI18Next instance from a single file in your project, where you can continually import it from to use the class methods as needed. You can see this approach in the examples/simple/i18n.js file.
After creating and exporting your NextI18Next instance, you need to take the following steps to get things working:
- Create an
_app.jsfile inside yourpagesdirectory, and wrap it with theNextI18Next.appWithTranslationhigher order component (HOC). You can see this approach in the examples/simple/pages/_app.js. - Create a
server.jsfile inside your root directory, initialise an express server, and use thenextI18NextMiddlewaremiddleware with yournextI18Nextinstance passed in. You can see this approach in the examples/simple/server.js. For more info, see the NextJs section on custom servers.
That's it! Your app is ready to go. You can now use the NextI18Next.withNamespaces HOC to make your components or pages translatable, based on namespaces:
import React from 'react'
// This is our initialised `NextI18Next` instance
import { withNamespaces } from '../i18n'
class Footer extends React.Component {
render() {
return (
<footer>{this.props.t('description')}</footer>
)
}
}
export default withNamespaces('footer')(Footer)The withNamespaces HOC is responsible for passing the t function to your component. It enables all the translation functionality provided by i18next. Further, it asserts your component gets re-rendered on language change or changes to the translation catalog itself (loaded translations). More info can be found here.
By default, next-i18next will send all your namespaces down to the client on each initial request. This can be an appropriate approach for smaller apps with less content, but a lot of apps will benefit from splitting namespaces based on route.
To do that, you need to return a namespacesRequired array via getInitialProps on your page-level component. You can see this approach in examples/simple/pages/index.js.
Note: withNamespaces provides namespaces to the component that it wraps. However, namespacesRequired provides the total available namespaces to the entire React tree and belongs on the page level. Both are required (although you can use Trans instead of withNamespaces if desired).
One of the main features of this package, besides translation itself, are locale subpaths. It's easiest to explain by example:
myapp.com ---> Homepage in default lang
myapp.com/de/ ---> Homepage in German
This functionality is not enabled by default, and must be passed as an option into the NextI18Next constructor:
new NextI18Next({ localeSubpaths: 'foreign' })Now, all your page routes will be duplicated across all your non-default language subpaths. If our static/locales folder included fr, de, and es translation directories, we will automatically get:
myapp.com
myapp.com/fr/
myapp.com/de/
myapp.com/es/
If you also want to enable locale subpaths for the default locale, set localeSubpaths to all:
new NextI18Next({ localeSubpaths: 'all' })We'll now get:
myapp.com/en/
myapp.com/fr/
myapp.com/de/
myapp.com/es/
The main "gotcha" with locale subpaths is routing. We want to be able to route to "naked" routes, and not have to worry about the locale subpath part of the route:
<Link href='/some-page'>With this link, we would expect someone whose language is set to French to automatically be directed to /fr/some-page.
To do that, we must import Link from your NextI18Next instance, not next/router:
import React from 'react'
// This is our initialised `NextI18Next` instance
import { Link } from '../i18n'
const SomeLink = () => (
<Link href='/some-page'>
This will magically prepend locale subpaths
</Link>
)We can also navigate imperatively with locale subpaths by importing Router from your NextI18Next instance.
The exported Router shares the same API as the native Next Router. The push, replace, and prefetch functions will automatically prepend locale subpaths.
import React from 'react'
// This is our initialised `NextI18Next` instance
import { Router } from '../i18n'
const SomeButton = () => (
<button
onClick={() => Router.push('/some-page')}
>
This will magically prepend locale subpaths
</button>
)Custom routing can be achieved via the app.render method:
/* First, use middleware */
server.use(nextI18NextMiddleware(nextI18next))
/* Second, declare custom routes */
server.get('/products/:id', (req, res) => {
const { query, params } = req
return app.render(req, res, '/product-page', { ...query, id: params.id })
})
/* Third, add catch-all GET for non-custom routes */
server.get('*', (req, res) => handle(req, res))| Key | Default value |
|---|---|
browserLanguageDetection |
true |
defaultNS |
'common' |
defaultLanguage |
'en' |
ignoreRoutes |
['/_next', '/static'] |
otherLanguages (required) |
[] |
localePath |
'static/locales' |
localeStructure |
'{{lng}}/{{ns}}' |
localeSubpaths |
'none' |
serverLanguageDetection |
true |
use (for plugins) |
[] |
customDetectors |
[] |
This table contains options which are specific to next-i18next. All other i18next options can be passed in as well.
next exportwill result in a client-side only React application.- We cannot support koa until a 1:1 replacement for
i18next-express-middlewareexists. - To add a
langattribute to your top-level html DOM node, you must create a_document.jsfile. - Localising
next/headrequires special consideration due to NextJs internals.
Thanks goes to these wonderful people (emoji key):
Rob Capellini 💻 | Alexander Kachkaev 📢 💬 🤔 💻 | Mathias Wøbbe 💻 🤔 | Lucas Feliciano 🤔 👀 | Ryan Leung 💻 |
This project follows the all-contributors specification. Contributions of any kind welcome!