The localisation process

The first step will be to add our actual localised content. This example is very simple, but in reality you might end up writing your whole frontend in a single locale, and then having translators do bigger chunks of work when you get closer to release.

As a package, next-i18next borrows functionality from both react-i18next and NextJs. One such feature we take advantage of is the static dir provided by NextJs, which is automatically publicly available to our client via our Node server. We can simply pop our localised content in there, and don’t need to do anything else — it’s already available to our Node app via the filesystem, and to our client via a network request to my-app.com/static/my-asset.txt .

By default, next-i18next expects you to organise your localised content like this:

next-i18next-demo

└── static

└── locales

├── en

| └── common.json

└── de

└── common.json

In this example, we’ll have a default namespace of English, and a foreign namespace of German, both with a single key.

static/locales/en/common.json :

static/locales/de/common.json :

Now that our localisation content is in place, we can initialise our next-i18next class.

(We might rewrite the package in a more functional way in the future, but for now it’s class-based.)

Let’s add a top-level i18n.js file as per the next-i18next docs:

This file will be used by both our NextJs process and a custom Node/Express server, so if you’d like to use ESM syntax you’ll need to take care of transpilation yourself.

The NextI18NextInstance class provides us with almost everything we need to localise our app. We just need to do two more things:

Create an _app.js file and wrap it with the appWithTranslation HOC provided by our NextI18NextInstance — this is what enables the bulk of the SSR localisation magic Create a server.js file and use the nextI18NextMiddleware — this is what does language detection based on headers, creates locale subpaths, and so on.

Here’s our _app.js :

And here’s our server.js :

Notice we’re passing our NextI18NextInstance into nextI18NextMiddleware . Behind the scenes, this NextI18NextInstance will provide a cloned i18n instance for each Express req which is then serialised and sent down to the client via the existing NextJs pattern of pageProps / getInitialProps .

Note that we’ll need to change our NextJs scripts now, as our app’s entry point has changed to our custom server.js :

That’s it! We’re done. We can add the actual localised content via withNamespaces to our homepage, and add a button to change the locale:

Now if we run our, app, we’ll see: