How to Localize a React App: Step-by-Step Guide
Learn how to add localization to your React application with react-i18next. Complete step-by-step tutorial with code examples.
Quick Answer
To localize a React app:
npm install react-i18next i18nextuseTranslation hook in componentsPrerequisites
Step 1: Install Dependencies
npm install react-i18next i18next i18next-browser-languagedetector| Package | Purpose |
|---|---|
| react-i18next | React bindings for i18next |
| i18next | Core internationalization framework |
| i18next-browser-languagedetector | Auto-detect user's language |
| react-i18next | React bindings for i18next |
|---|---|
| i18next | Core internationalization framework |
| i18next-browser-languagedetector | Auto-detect user's language |
| react-i18next | React bindings for i18next |
|---|---|
| i18next | Core internationalization framework |
| i18next-browser-languagedetector | Auto-detect user's language |
| i18next | Core internationalization framework |
|---|---|
| i18next-browser-languagedetector | Auto-detect user's language |
| i18next-browser-languagedetector | Auto-detect user's language |
|---|
Step 2: Create Translation Files
Create a locales folder with JSON files for each language:
src/
locales/
en/
translation.json
es/
translation.json
fr/
translation.jsonsrc/locales/en/translation.json:
{
"welcome": {
"title": "Welcome to Our App",
"subtitle": "The best solution for your needs"
},
"nav": {
"home": "Home",
"about": "About",
"contact": "Contact"
},
"auth": {
"login": "Log In",
"signup": "Sign Up",
"logout": "Log Out"
}
}src/locales/es/translation.json:
{
"welcome": {
"title": "Bienvenido a Nuestra App",
"subtitle": "La mejor solucion para tus necesidades"
},
"nav": {
"home": "Inicio",
"about": "Acerca de",
"contact": "Contacto"
},
"auth": {
"login": "Iniciar Sesion",
"signup": "Registrarse",
"logout": "Cerrar Sesion"
}
}Step 3: Configure i18next
Create src/i18n.js:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import enTranslation from './locales/en/translation.json';
import esTranslation from './locales/es/translation.json';
import frTranslation from './locales/fr/translation.json';
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: { translation: enTranslation },
es: { translation: esTranslation },
fr: { translation: frTranslation },
},
fallbackLng: 'en',
interpolation: {
escapeValue: false, // React already escapes
},
});
export default i18n;Step 4: Import in App Entry
src/index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './i18n'; // Import i18n configuration
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);Step 5: Use Translations in Components
src/App.js:
import { useTranslation } from 'react-i18next';
function App() {
const { t } = useTranslation();
return (
<div>
<nav>
<a href="/">{t('nav.home')}</a>
<a href="/about">{t('nav.about')}</a>
<a href="/contact">{t('nav.contact')}</a>
</nav>
<main>
<h1>{t('welcome.title')}</h1>
<p>{t('welcome.subtitle')}</p>
</main>
<button>{t('auth.login')}</button>
</div>
);
}
export default App;Step 6: Add Language Switcher
import { useTranslation } from 'react-i18next';
function LanguageSwitcher() {
const { i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
return (
<div>
<button onClick={() => changeLanguage('en')}>English</button>
<button onClick={() => changeLanguage('es')}>Espanol</button>
<button onClick={() => changeLanguage('fr')}>Francais</button>
</div>
);
}
export default LanguageSwitcher;Advanced Features
Variables/Interpolation
Translation:
{
"greeting": "Hello, {{name}}!"
}Component:
t('greeting', { name: 'John' }) // "Hello, John!"Pluralization
Translation:
{
"items": "{{count}} item",
"items_plural": "{{count}} items"
}Component:
t('items', { count: 1 }) // "1 item"
t('items', { count: 5 }) // "5 items"Nested Keys
// Access nested keys with dot notation
t('welcome.title')
t('nav.home')Trans Component (JSX in translations)
Translation:
{
"terms": "I agree to the <link>Terms of Service</link>"
}Component:
import { Trans } from 'react-i18next';
<Trans i18nKey="terms">
I agree to the <a href="/terms">Terms of Service</a>
</Trans>Managing Translations at Scale
As your app grows, managing JSON files becomes difficult:
Solution: Use a Translation Management System
IntlPull automates React localization:
# Scan your code for hardcoded strings
npx intlpull scan
# Pull latest translations
npx intlpull pull --output ./src/locales
# Push new strings
npx intlpull pushBenefits:
Common Issues and Solutions
Issue: Translations not updating
Solution: Make sure you imported i18n before App:
import './i18n';
import App from './App';Issue: Blank content on first load
Solution: Add Suspense fallback:
import { Suspense } from 'react';
<Suspense fallback="Loading...">
<App />
</Suspense>Issue: TypeScript errors
Solution: Install types and configure:
npm install --save-dev @types/react-i18nextBest Practices
auth.login not button1)Frequently Asked Questions
How do I add a new language?
locales/de/translation.json)How do I handle RTL languages?
Add dir attribute based on language:
<html dir={i18n.language === 'ar' ? 'rtl' : 'ltr'}>How do I lazy-load translations?
Use i18next-http-backend:
import Backend from 'i18next-http-backend';
i18n.use(Backend).init({
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
});Summary
To localize a React app:
useTranslation hookReady to scale your localization? IntlPull automates React i18n with AI translation and seamless CLI integration.