Internationalization in Next.js
Make Your Product Compete with Local Businesses

A full stack web developer, studied in Savitribai Phule Pune University!
Computer Engineer | Spiritual | Business - Pune, Maharashtra
What is Next.js?
The React framework for production!
Next.js gives you the best developer experience with all the features you need for production:
- Hybrid, Static & Server Side Rendering
- Typescript Support
- Smart Bundling
- Route Pre-Fetching
- Internationalization and many more...
However, today we will take a look at Internationalization.
What is Internationalization?
It can be refered to as a process to make website more effective at reaching potential customers and business partners in other countries.
In other words, internationalization simple means to provide multilingual support for websites. It makes viewers feel local. It makes viewers feel connected as they can see websites in their own local language.
Setting up Internationalization in Next.js
To use this feature (i18n) in Next.js we need to do some quick setup! (I hope you have created next-app and ready to work along with this guide.)
Just a quick note: To create a next-app use following command. This guide is typescript specific but you can follow it if you are using javascript only too!
# yarn
yarn create next-app your-app-name
# npm - npx
npx create-next-app your-app-name
Add Locales in next.config.js

In your project root folder you will find a file named next.config.js, open the file in your favorite text editor. (We will be using VS Code for this tutorial)
Open the file and modify as below. This (or similar to this) will be default.
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
swcMinify: true,
}
Add the i18n key as shown in below image.
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
swcMinify: true,
i18n: {
locales: [ 'en', 'mr' ],
defaultLocale: 'en'
}
}
Here as you can see, we have added two keys in the i18n object, They are defaultLocale and locales.
The locales is an array mentioning locales (or simple languages) the website is supportive to. So, mentioning mr and en simply means that the website is supporting English and Marathi.
Browsers when making requests to the servers send a lot of data alongside the request which sometimes is part of the request. One of such value is locale. Next.js picks up locale value from the request object and provides it in the router object (we will see this few steps below). According to locale value in router object wbsite can be shown in respective language.
The next key we have in the i18n object is the defaultLocale key, this ensures when there is no option to choose from locales Next.js defaults to the defaultLocale value. In our case as we only have English en and Marathi mr; requests (with locale value) received by the server other that the locales defined in the locales array will load content in default locale defined with defaultLocale.
Create Data for Locales
Setting up locales in config is not the only step we have to do when it comes to adding multilingual support to our website, there's a lot to do ahead!
First, we should have data stored somewhere to fetch and deliver it to the frontend whenever required. This step includes creating multilingual translations; which we are going to do right now. So, later we can fetch and show based on the requested locale.
In this guide, we are not going to setup entire database but what we will do is to create a local json file and use that data instead. But, in your production softwares you should have a better storage option like a database or an API.
Now open your project directory in VS Code (or any code editor you prefer). Create an utils directory in the project root folder.

Here as you can see, i18-next is the root directory where all the files and sub directories live. We have created an utils directory in the root directory of our project.
Next up, we will add two files in the utils directory. They are en.json and mr.json.

This two files will refer to the data we will need to fetch for two locales we have defined in our config file. Here en.json refers to the English and mr.json refers to the Marathi language.
Content in each of one is as listed below.
Content in en.json
{
"title": "i18-nextjs",
"heading": "Viewing English",
"buttonText": "Switch to"
}
Content in mr.json
{
"title": "आय 18 नॆक्स्ट",
"heading": "मराठी पाहत आहॊत.",
"buttonText": "बदल करा"
}
We have title, heading and buttonText properties. We will display content based on this properties.
Display Content Based on Locale
First of all, remove everything from the index.tsx or index.jsx file available in pages directory right under the root folder and add following lines in it.
import type { NextPage } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { useMemo } from 'react'
import en from '../utils/en.json'
import mr from '../utils/mr.json'
Here the first line is not required if your project haven't bootstrapped with typescript; You can omit it in such cases, for typescript it is required.
Now we will create a function named Home below our imports.
const Home: NextPage = () => {
return ()
}
The : NextPage part is not required in javascript project, but as mentioned earlier this is a typescript project we use it so compiler can understand that this is a NextPage.
Next.js provides us the useRouter hook to access router data at any given time. We will use this hook and extract out locale, locales and push function which is used to add route to the browser routing stack which manages on which page we will be. Based on the locale value we will use either data from en.json or mr.json.
Add following lines in the Home function block above the return keyword.
const { locale, locales, push } = useRouter()
const pageLocale = useMemo(() => (locale === 'en' ? en : mr), [locale])
useMemo is the react hook which can be used to cache data and only refetch or redeclare when there is change in some value. The value we will monitor is locale; So if locale value changes the useMemo will call the function provided and save data returned in the pageLocal identifier. Function provided is just checking the value of locale and returning data from either en.json or mr.json.
So up till now your Home component code should look like code below.
import type { NextPage } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { useMemo } from 'react'
import en from '../utils/en.json'
import mr from '../utils/mr.json'
const Home: NextPage = () => {
const { locale, locales, push } = useRouter()
const pageLocale = useMemo(() => (locale === 'en' ? en : mr), [locale])
return ()
}
Our component is ready to return tsx to render as now we have access to the data to render based on locale. We have stored our data in whichever the locale it will be in pageLocal identifier.
Let's have some html to render our data. Write below code in (...) which is next to return in Home component.
<div>
<Head>
<title>{pageLocale.title}</title>
<link rel='icon' href='/favicon.ico' />
</Head>
<!-- ... -->
</div>
You might have figured it out that the title in above code will be in the locale which was requested. Let's quickly finish building the component and see output.
Let's add a heading and a button to change our locale in our code.
Paste the below code in place of <!-- ... -->.
<main className='p-2 space-y-2'>
<h1 className='text-xl font-medium'>{pageLocale.heading}</h1>
<div className='space-x-2'>
{locales?.map((locale_) => locale_ === locale ? (
''
) : (
<button key={locale_}
className='bg-slate-200 py-2 px-4 rounded-md'
onClick={() => push('/', `/`, { locale: locale_ })}>
{pageLocale.buttonText} {locale_}
</button>
)
)}
</div>
</main>
In the h1 tag we have used heading property from our locale data in pageLocale identifier. In the next div what we have done is we want to render buttons to change to specific language. locales property provides us all the available locales. It is the same array as we have initially declared in config part.
So, using map function we are looping over the array of locales and checking if the current locale and the locale we are at in array, if they match we return '' empty string. Which means don't do anything! If they don't match it means we have different locale that the current one so creating a button for that specific locale to change page languagle.
The onClick attribute on buttons will use push function provided by the useRouter hook and redirect our user to the same page but in this case we pass locale oject as second argument. It will create a button with the specific locale in the array and on clicking that button it will redirect to the same page but with different locale.
Finally, your component should look like this,
import type { NextPage } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { useMemo } from 'react'
import en from '../utils/en.json'
import mr from '../utils/mr.json'
const Home: NextPage = () => {
const { locale, locales, push } = useRouter()
const pageLocale = useMemo(() => (locale === 'en' ? en : mr), [locale])
return (
<div>
<Head>
<title>{pageLocale.title}</title>
<link rel='icon' href='/favicon.ico' />
</Head>
<main className='p-2 space-y-2'>
<h1 className='text-xl font-medium'>{pageLocale.heading}</h1>
<div className='space-x-2'>
{locales?.map((locale_) => locale_ === locale ? (
''
) : (
<button key={locale_}
className='bg-slate-200 py-2 px-4 rounded-md'
onClick={() => push('/', `/`, { locale: locale_ })}>
{pageLocale.buttonText} {locale_}
</button>
)
)}
</div>
</main>
</div>
)
}
export default Home
Let's check our output!
Open the terminal and navigate to the project directory and type following command based on your package manager to run the app.
# yarn
yarn dev
# npm
npm run dev
Output - Default

As you can see that we are at the index route of the application which is /. In our case htpps://localhost:3000/ and the default language for my browser is English the page is loaded in English.
Let's check what will be the output when I press the button.
Output - Marathi

Boommm!!! Our route is changed to /mr and our content is also loaded in Marathi. Don't mind if you don't know Marathi just see how our app has ran successfully!
Try yourself and try to add more locales and experiment with them; you will have deeper understanding of the concepts.
Quick Recap
So, what we have learned so far is,
- Created new Next.js project.
- Added locales in the configuration file.
- Created directory called
utilsto store our data. - Added data to our files (
en.json,mr.json). - Then we went to developing frontend.
- Created
Homecomponent.
Resources
Hope you have liked this mini introduction to Internationalization in Next.js and could have understood what I wanted to convey, Thank You!