Exploring Internationalisation With Nextjs 10 and react-intl
Published: Nov 8, 2020
Last updated: Nov 8, 2020
In this post, we will be diving into one of Next.js 10's new advanced features in internationalised routing and how we can use this with react-intl.
Getting started
Create a new Next.js 10 project by running npx create-next-app i18n-example to create a new project name i18n-example.
We will run some other commands to set things up:
# Create new Next.js 10 project "i18n-example"
npx create-next-app i18n-example
cd i18n-example
# A place to pop some internationalisation content
mkdir -p content/locale
# A place for some languages
# French
touch content/locale/fr.js
# Spanish
touch content/locale/es.js
# English
touch content/locale/en.js
# A barrel file
touch content/locale/index.js
# Installing react-intl for i18n within components
npm i react-intl --legacy-peer-deps
# Required for updating config
touch next.config.js
For installing react-intl I've used --legacy-peer-deps as there was a peer dependency of react@^16.3.0 and I was running npm v7.
Now that we have some files going, let's get started with some basic content!
Setting up Next.js i18n
Follow on from the docs on getting started, we need to update next.config.js:
// next.config.js
module.exports = {
i18n: {
// These are all the locales you want to support in
// your application
locales: ["en", "fr", "es"],
// This is the default locale you want to be used when visiting
// a non-locale prefixed path e.g. `/hello`
defaultLocale: "en",
},
};
Here we are going with sub-path routing, so the tl;dr is that our-website.com will be the default locale (English), whereas our-website.com/fr and our-website.com/es will direct us to the French and Spanish websites respectively.
Now that we have that out of the way, let's update the pages/index.js page!
Internationalising our home page
We can use the Next router to grab which locale we are on.
With this, we are ready to start our app and see the results.
Run npm run dev to start the server and head to the localhost port-specific (likely http://localhost:3000).
Once you are there, you will see the current locale of English as well as what locales are configured!
Base page
Given what we mentioned previously about the sub-routing, we can now go to /fr and /es and expect the current locale to change. The below image will be just for the /fr route to show our sub-routing works.
French locale
Amazing! Now that we are done here, we can get to using this with react-intl.
Switching copy with react-intl
We will run a simple example here with react-intl, but what we need to do first is prep some content that we wish to swap out!
Inside of content/locale/en.js, let's through in some basic JSON to replace our "Hello, world!" and welcome message:
export const en = {
"/": {
hello: "Hello, world!",
welcomeMessage: "Welcome to your internationalised page!",
},
"/alt": {
hello: "Yo",
},
};
The structure of these files is up to you, but I am going with a top-level key of the page name for now and identifiers in the string. Places I have worked previous keep this as JSON to upload to places such as Smartling, so you may want to go down an avenue that transforms JSON to the above ES6 format I am using.
Let's copy-paste that across to our Spanish and French files and use some possibly inaccurate Google translations to help us out.
On this page, I am importing the useIntl hook, destructuring formatMessage from that hook, making a helper function f that abstract the need to always pass an object with the id and replace the appropriate code with our key name for the page in the locale content.
Let's fire up the app with npm run dev and see what happens!
If we check /, /fr and /es we get the following respectively:
English home
French home
Spanish home
Success!
As an added bonus to show how the other locale pages would work with the /alt route key we put in the locale files, we can create a new file pages/alt.js and add something similar:
import { useIntl } from "react-intl";
export default function IndexPage(props) {
const { formatMessage } = useIntl();
const f = (id) => formatMessage({ id });
return (
<div>
<h1>{f("hello")}</h1>
</div>
);
}
Going to /fr/alt and /es/alt respectively give us the following:
Alt image - French
Alt image - Spanish
Notice that we have re-used the hello key for this page too but we are not getting that clash thanks to how we set up the locales and pages/_app.js page? Very handy. I am unsure if that is the best way to lay it out (there may be issues I am yet to run into at scale) but for this demo, it works rather nicely.
Note: if you are having an error pop up in the terminal about missing Polyfills, refer to the formatjs documentation. The tl;dr is that you need Node v13+ or you can install a package.
Summary
In conclusion, we have explored Next.js internationalisation and used the react-intl package to help make our locales come to life!
See the final project (although lacking aesthetics) here and the final code here.