A lot of people, like me, are trying to get jobs outside their own country so to be able to do that we need to learn and master other languages. In the programming world (and to be honest, in almost all areas that involve technology in some degree), the universal language is the english.
With that, beyond mastering communicating (which I mean, talking and listening) in those languages, we need to write our CV, blog posts and copies in this universal language. So, today I'll be writing about how to manage a multi-language website using Next.js.
Setting up the Project
Let's set up our Next.js project using the create-next-app lib, which give us a pretty good template (you can follow up to see options in here)
npx create-next-app@latest
# or
yarn create next-app
# or
pnpm create next-app
Altought Next.js providers internationalised routing, it doesn't handle management of translation content, so to be able to achieve that we're going to install next-i18next dependency for our project:
yarn add next-i18next react-i18next i18next
# or
npm install --save next-i18next react-i18next i18next
Configuring Next.js with I18n
Following the next-i18next documentation, we need set up the project for it:
- First, create a
next-i18next.config.jsfile in the root of your project.
- Inside it we need to add the locales configuration, based on your locale languages, which in my case is:
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'pt-BR'],
},
}
- Next, we're going to modify the
next.config.jsfile, by passing the i18n config that we previously set up on ournext-i18next.config.jsfile.
const { i18n } = require('./next-i18next.config')
module.exports = {
{...}
i18n,
}
- Now we need to create a
localesfolder insidepublicand create our different languages folder with acommon.jsonfile each. It's important to say that thecommon.jsonit's basically a set of texts that will be used for all components, but you can create others for specific components)
└── public
└── locales
├── en
| └── common.json
└── pt-BR
└── common.json- Mostly important and the last step of the configuration, we need to connect the I18n with our app. Open the
pages/_app.jsdirectory and wrap the default export withappWithTranslationfromnext-i18next, following as below:
import '../styles/globals.css'
import { appWithTranslation } from 'next-i18next'
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default appWithTranslation(MyApp)
That's all! Now we have all configuration set up and we can start using it.
Implementing different languages in components using SSR
It's important to know that next-i18next added support for using SSR, which basically can be done by using the getStaticProps or getServerSideProps from Next.js. But let's continue:
- Let's define some example text in all our different locale folders, I will be creating a title field:
// locale/en/common.json
{
"title": "Building a multi-language website with Next.js"
}
// locale/pt-BR/common.json
{
"title": "Construindo um website com suporte a diversas linguagens, utilizando Next.js"
}
- As mentioned above, to have Next.js support, we need to use
getStaticPropsorgetServerSideProps(you can check usage details of each here). With the decision in place, we're going to importserverSideTranslationsfromnext-i18nextand add to our choosen method.
getStaticProps
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
export const getStaticProps = async ({ locale }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common'])),
}
}
}
getServerSideProps
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
export const getServerSideProps = async ({ locale }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common'])),
}
}
}
Another really important thing to remember is that we can have specific translations (as I mentioned prior) for each component. Let's say I created a new file in our locales named example.json, and we want to add the translation to the same component. We would do:
export const getStaticProps = async ({ locale }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common',
'example']))
}
}
}
- Last, the display!! Let's add the translation itself to our Component. Let's import
useTranslationsfromreact-i18nextdependency and destructure it to get propertyt(which will be then used for translating):
import { useTranslation } from 'react-i18next'
export default function Home() {
const { t } = useTranslation('common')
return (
<div>
<main>
<h1>
{t('title')}
</h1>
</main>
</div>
)
}
export const getStaticProps = async ({ locale }) => {
return {
props: {
...(await serverSideTranslations(locale, ['common']))
}
}
}
Seeing the Results
Accessing your YOUR_URL/$LANGUAGE, which in my case is http://localhost:3000/${CURRENT_LANGUAGE}.
English - http://localhost:3000/en

Portuguese - http://localhost:3000/pt-BR

Conclusion
There we have it! I hope the post it's clear and you guys were able to follow. Feel free to tag me into any doubts and providing any feedbacks. In part 2, we're going to understand on how to build a simple toggle for changing languages! Stay tuned
To check all the work done here, you can go to the GitHub Repository