Translate Nextjs apps using next-translate
Tags: nextjs, i18n, translation, tutorial
Published: 2023-04-29 19:30:23

Since there have been some changes in the versions of Nextjs (v 13.3.1 at the time of writing this post), this doc can be used as a reference to internationalize your application using the next-translate (v2.0.5) library.


##1. Create an next app

```sh
npx create-next-app translation-app
```

Install the next-translate library

```sh
npm install next-translate
```


Add the plugin next-translate-plugin

```sh
npm install next-translate-plugin -D
```



##2. Internationalization configuration file

Create a file named `i18n.js` in the root path of the directory. This file will specify the configuration of the supported translations. You can read more about the configuration on the [documentation page](https://github.com/aralroca/next-translate).

In this case the locales array will handle English (en) and Spanish (es) languages:

_i18n.js file_
```js
module.exports = {
 locales: ['en', 'es'],
 defaultLocale: 'es',
 localeDetection: false,
 pages: {
   '*': ['common'],
 },
}
```
You can use namespaces to define sections for the whole app, useful if handling large translations.
For this exercise the regex expression ( * ) just will share the ‘common’ namespace with all the pages.


##3. Configure the next.config.js file

Add the next code to this file:

```typescript
const nextTranslate = require('next-translate-plugin')

module.exports = nextTranslate({
 webpack: (config, { isServer, webpack }) => {
   return config;
 }
})
```

You will end up with something like this:

_next.config.js_
```typescript
/** @type {import('next').NextConfig} */
const nextConfig = {
 reactStrictMode: true,
}
module.exports = nextConfig

const nextTranslate = require('next-translate-plugin')
module.exports = nextTranslate({
 webpack: (config, { isServer, webpack }) => {
   return config;
 }
})
```

##4. Create the translation files

Translations files are json files that help to manage the diferent languages for the app.

In the root directory create a folder called `locales`.
Then create a folder for each language: `en`  `es`

For each of those folders you will need to create json files named as the namespace specified before. In this case it is `common`. You will end up with an structure like this:


```
.
├── i18n.js
├── locales
│   ├── en
│   │   └── common.json
│   └── es
│       └── common.json
├── next.config.js
├── next-env.d.ts
├── package.json
├── package-lock.json
├── postcss.config.js
├── public
│   ├── favicon.ico
│   ├── next.svg
│   └── vercel.svg
├── README.md
├── src
│   ├── pages
│   │   ├── api
│   │   │   └── hello.ts
│   │   ├── _app.tsx
│   │   ├── _document.tsx
│   │   └── index.tsx
│   └── styles
│       └── globals.css
├── tailwind.config.js
└── tsconfig.json
```




Add to each json file the key-label data needed to translate the app.


_locales/common/en.json_
```json
{
   "hero-title" : "Translating Nextjs apps",
   "hero-description" : "Internationalization libraries are useful"
}
```



_locales/common/es.json_
```json
{
    "hero-title" : "Traduciendo apps en Nextjs",
    "hero-description" : "Las librerías de internacionalización son útiles"
}
```


## 5. Display your translations.

Update your components as shown next.
Import the useTranslation function:
`import useTranslation from 'next-translate/useTranslation'`

Inside the components functions, call the `t` function:
`const { t } = useTranslation('common')`

For each text that you want to translate, call the t function and pass the key for your label:
`{ t('hero-title') }`

This is the entire component file:

```typescript
// Home.tsx
import Image from 'next/image'
import { Inter } from 'next/font/google'

// useTranslation function from next-translate
import useTranslation from 'next-translate/useTranslation'

const inter = Inter({ subsets: ['latin'] })

export default function Home() {

  // t function from useTranslation, using the common namespace
  const { t } = useTranslation('common')

  return (
    <div className='h-screen flex flex-col justify-center items-center'>
       <h1 className='text-xl font-bold'>{ t('hero-title') }</h1>
       <p>{ t('hero-description') }</p>
   </div>
 )
}

```

## 6. Run your app

Run `npm run dev` and got to the this different urls:

**English**
`http://localhost:3000/en`

![App translated in english](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5zuw6l5eey9sntnkby3.png)



**Spanish**
`http://localhost:3000/es`

![App translated in spanish](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ya8nzzela41f8xb7lsot.png)



If you want to change between languages using buttons, check the suggested [methodology in the documentation](https://github.com/aralroca/next-translate#10-how-to-change-the-language)

Here is an example of a component that will display all the languages options based on the `locales` file.

_ChangeLanguage.tsx_
```typescript
import { locales } from '../../i18n'
import useTranslation from 'next-translate/useTranslation'
import setLanguage from 'next-translate/setLanguage'

export default function ChangeLanguage() {
    
    const { t, lang } = useTranslation()

    console.log( locales )

    let langs = []

    for(let l of locales){
        if( l !== lang ){
            langs.push(<button  key={l} onClick={async () => await setLanguage(l)}> { l.toUpperCase() } </button>)
        }
    }

    return (
        <div>
            { langs }
        </div>
    );
  }
```




At end, you can use sites like [i18next](https://translate.i18next.com/) to translate json files keeping the keys untouched, so translations can be easier.

Happy translations!