DEV Community

Cover image for Multi Language Support in Your React & Next JS App
Syed Muhammad Ali Raza
Syed Muhammad Ali Raza

Posted on

Multi Language Support in Your React & Next JS App

How to Add Multi Language Support to Your React App Using react i18next

As a frontend developer there comes a time when your React app needs to speak than one language. Whether you are building for an audience or planning ahead internationalization is a must have.

In this guide I will walk you through setting up react i18next. The popular internationalization library for React with over 6.3 million weekly downloads.


What Is Internationalization. Why Do You Need It?

Internationalization means designing your app so it can support languages without rewriting code. Think of it as laying the foundation. Localization is what comes after. Actually translating the content.

With react i18next you can:

  • Move all user facing text into JSON translation files

  • Switch languages dynamically without page reloads

  • Handle plurals, variables and even HTML inside translations

  • Load the translations your user needs


Step 1: Installation

First install the core packages. You need both i18next. React i18next.


npm install react-i18next i18next --save

Enter fullscreen mode Exit fullscreen mode

You need both because i18next does the lifting. Managing languages, pluralization, formatting. React i18next gives you React tools like the useTranslation hook and Trans component.

For production apps you will likely want two packages:


npm install i18next-http-backend i18next-browser-languagedetector --save

Enter fullscreen mode Exit fullscreen mode
  • i18next-http-backend: Loads translation JSON files from your public folder

  • i18next-browser-languagedetector: Automatically detects the users preferred language from browser settings, cookies or localStorage


Step 2: Set Up the Configuration

Create a file called i18n.js in your src folder.


import i18n from 'i18next';

import { initReactI18next } from 'react-i18next';

import Backend from 'i18next-http-backend';

import LanguageDetector from 'i18next-browser-languagedetector';

i18n

.use(Backend)

.use(LanguageDetector)

.use(initReactI18next)

.init({

fallbackLng: 'en'

debug:

interpolation: {

escapeValue: false,

}

});

export default i18n;

Enter fullscreen mode Exit fullscreen mode

The escapeValue is set to false because React already handles XSS protection.


Step 3: Connect to Your React App

Import the i18n configuration in your entry file before rendering your app.


import React from 'react';

import { createRoot } from 'react-dom/client';

import './i18n';

import App from './App';

const root = createRoot(document.getElementById('root'));

root.render(<App />);

Enter fullscreen mode Exit fullscreen mode

Step 4: Create Your Translation Files

By default i18next looks for translation files in public/locales/[language]/translation.json.

Create this folder structure:


public/

locales/

en/

translation.json

fr/

translation.json

es/

translation.json

Enter fullscreen mode Exit fullscreen mode

translation file:


{

"welcome": "Welcome to my app"

"greeting": "Hello, {{name}}!"

"itemCount": "You have {{count}} item"

"itemCount_plural": "You have {{count}} items"

}

Enter fullscreen mode Exit fullscreen mode

translation file:


{

"welcome": "Bienvenue sur mon app"

"greeting": "Bonjour, {{name}} !"

"itemCount": "Vous avez {{count}} article"

"itemCount_plural": "Vous avez {{count}} articles"

}

Enter fullscreen mode Exit fullscreen mode

Keep your JSON keys consistent across all languages. Use. Group related strings into namespaces.


Step 5: Use Translations in Your Components

The useTranslation Hook

The way to translate in functional components:


import React from 'react';

import { useTranslation } from 'react-i18next';

function WelcomeMessage() {

const { t } = useTranslation();

return (

<div>

<h1>{t('welcome')}</h1>

<p>{t('greeting' { name: 'Alex' })}</p>

<p>{t('itemCount' { count: 5 })}</p>

</div>

);

}

export default WelcomeMessage;

Enter fullscreen mode Exit fullscreen mode

When the language changes, everything re-renders automatically. No page reload needed.

Handling Plurals

i18next follows CLDR rules so it handles complex pluralization across languages. Just define _ keys in your JSON:


{

"message": "{{count}} item"

"message_plural": "{{count}} items"

}

Enter fullscreen mode Exit fullscreen mode

const { t } = useTranslation();

t('message' { count: 0 });

t('message' { count: 1 });

t('message' { count: 3 });

Enter fullscreen mode Exit fullscreen mode

The Trans Component for HTML and JSX

When your translation includes links, bold text or React components use the Trans component instead of concatenating strings.


import { Trans } from 'react-i18next';

function Message() {

return (

<Trans>

Hello <strong>world</strong> check out our <a href="/docs">docs</a>.

</Trans>

);

}

Enter fullscreen mode Exit fullscreen mode

In your translation file use numbered tags to match the JSX structure:


{

"Hello <1>world</1> check out our <3>docs</3>.": "Bonjour <1>le monde</1>, consultez notre <3>documentation</3>."

}

Enter fullscreen mode Exit fullscreen mode

The Trans component maps <1> to the child element <2> to the second and so on.


Step 6: Add a Language Switcher

Let users change languages on the fly:


import React from 'react';

import { useTranslation } from 'react-i18next';

function LanguageSwitcher() {

const { i18n } = useTranslation();

const changeLanguage = (lang) => {

i18n.changeLanguage(lang);

};

return (

<div>

<button onClick={() => changeLanguage('en')}>English</button>

<button onClick={() => changeLanguage('fr')}>Français</button>

<button onClick={() => changeLanguage('es)}>Español</button>

</div>

);

}

export default LanguageSwitcher;

Enter fullscreen mode Exit fullscreen mode

When you call i18n.changeLanguage() i18next loads the translation file and triggers a re-render of all components using useTranslation.


Step 7: Organize with Namespaces

As your app grows putting everything in one translation.json becomes messy. Namespaces let you split translations by feature.

Folder structure:


/locales/en/

common.json

dashboard.json

profile.json

Enter fullscreen mode Exit fullscreen mode

// Load only what you need

const { t } = useTranslation('dashboard');

//. Load multiple

const { t } = useTranslation(['dashboard' 'common']);

Enter fullscreen mode Exit fullscreen mode

Using namespaces improves performance by loading only the translations needed for the current view.


Project Structure Recap

Here's what a organized internationalization setup looks like:


src/

├── i18n.js          # i18next configuration

├── index.js         # Import i18n.js here

├── components/

│   ├── Welcome.jsx

│   └── LanguageSwitcher.jsx

└── App.jsx

public/

└── locales/

├── en/

│   ├── translation.json

│   └── dashboard.json

└── fr/

├── translation.json

└── dashboard.json

Enter fullscreen mode Exit fullscreen mode

Top comments (0)