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
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
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;
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 />);
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
translation file:
{
"welcome": "Welcome to my app"
"greeting": "Hello, {{name}}!"
"itemCount": "You have {{count}} item"
"itemCount_plural": "You have {{count}} items"
}
translation file:
{
"welcome": "Bienvenue sur mon app"
"greeting": "Bonjour, {{name}} !"
"itemCount": "Vous avez {{count}} article"
"itemCount_plural": "Vous avez {{count}} articles"
}
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;
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"
}
const { t } = useTranslation();
t('message' { count: 0 });
t('message' { count: 1 });
t('message' { count: 3 });
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>
);
}
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>."
}
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;
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
// Load only what you need
const { t } = useTranslation('dashboard');
//. Load multiple
const { t } = useTranslation(['dashboard' 'common']);
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
Top comments (0)