React i18n Setup & Configuration
Set up internationalization in your React application with popular libraries
Internationalization (i18n) enables your React app to support multiple languages and locales. Learn to configure i18n libraries and structure your app for global audiences.
Implementation
1// Setting up react-i18next2// 1. Install dependencies: npm install react-i18next i18next i18next-browser-languagedetector34// i18n.ts - Configuration file5import i18n from 'i18next';6import { initReactI18next } from 'react-i18next';7import LanguageDetector from 'i18next-browser-languagedetector';89// Translation resources10const resources = {11 en: {12 translation: {13 welcome: {14 title: 'Welcome to {{appName}}',15 subtitle: 'Build amazing React applications',16 description: 'Start your journey with React today'17 },18 navigation: {19 home: 'Home',20 about: 'About',21 products: 'Products',22 contact: 'Contact',23 language: 'Language'24 },25 common: {26 loading: 'Loading...',27 error: 'Something went wrong',28 retry: 'Try again',29 save: 'Save',30 cancel: 'Cancel',31 delete: 'Delete',32 edit: 'Edit',33 search: 'Search',34 noResults: 'No results found'35 },36 forms: {37 email: 'Email',38 password: 'Password',39 confirmPassword: 'Confirm Password',40 required: 'This field is required',41 invalidEmail: 'Please enter a valid email',42 passwordMismatch: 'Passwords do not match',43 minLength: 'Must be at least {{count}} characters',44 maxLength: 'Must be no more than {{count}} characters'45 },46 messages: {47 success: 'Operation completed successfully',48 error: 'An error occurred: {{error}}',49 saved: 'Your changes have been saved',50 deleted: 'Item deleted successfully',51 confirmDelete: 'Are you sure you want to delete this item?'52 }53 }54 },55 ja: {56 translation: {57 welcome: {58 title: '{{appName}}へようこそ',59 subtitle: '素晴らしいReactアプリケーションを構築',60 description: '今日からReactの旅を始めましょう'61 },62 navigation: {63 home: 'ホーム',64 about: '概要',65 products: '製品',66 contact: 'お問い合わせ',67 language: '言語'68 },69 common: {70 loading: '読み込み中...',71 error: 'エラーが発生しました',72 retry: '再試行',73 save: '保存',74 cancel: 'キャンセル',75 delete: '削除',76 edit: '編集',77 search: '検索',78 noResults: '結果が見つかりません'79 },80 forms: {81 email: 'メールアドレス',82 password: 'パスワード',83 confirmPassword: 'パスワード確認',84 required: 'この項目は必須です',85 invalidEmail: '有効なメールアドレスを入力してください',86 passwordMismatch: 'パスワードが一致しません',87 minLength: '{{count}}文字以上で入力してください',88 maxLength: '{{count}}文字以下で入力してください'89 },90 messages: {91 success: '操作が正常に完了しました',92 error: 'エラーが発生しました: {{error}}',93 saved: '変更が保存されました',94 deleted: 'アイテムが削除されました',95 confirmDelete: 'このアイテムを削除してもよろしいですか?'96 }97 }98 },99 es: {100 translation: {101 welcome: {102 title: 'Bienvenido a {{appName}}',103 subtitle: 'Construye aplicaciones React increíbles',104 description: 'Comienza tu viaje con React hoy'105 },106 navigation: {107 home: 'Inicio',108 about: 'Acerca de',109 products: 'Productos',110 contact: 'Contacto',111 language: 'Idioma'112 },113 common: {114 loading: 'Cargando...',115 error: 'Algo salió mal',116 retry: 'Intentar de nuevo',117 save: 'Guardar',118 cancel: 'Cancelar',119 delete: 'Eliminar',120 edit: 'Editar',121 search: 'Buscar',122 noResults: 'No se encontraron resultados'123 }124 // ... more translations125 }126 }127};128129// Initialize i18next130i18n131 .use(LanguageDetector) // Detects user language132 .use(initReactI18next) // Passes i18n instance to react-i18next133 .init({134 resources,135 fallbackLng: 'en',136 debug: process.env.NODE_ENV === 'development',137138 interpolation: {139 escapeValue: false // React already escapes values140 },141142 detection: {143 order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'],144 caches: ['localStorage', 'cookie']145 }146 });147148export default i18n;149150// App.tsx - Wrap your app with I18nextProvider151import React from 'react';152import { I18nextProvider } from 'react-i18next';153import i18n from './i18n';154155function App() {156 return (157 <I18nextProvider i18n={i18n}>158 <YourApp />159 </I18nextProvider>160 );161}162163// Using translations in components164import { useTranslation } from 'react-i18next';165166function WelcomeComponent() {167 const { t } = useTranslation();168169 return (170 <div>171 <h1>{t('welcome.title', { appName: 'React Learning' })}</h1>172 <p>{t('welcome.subtitle')}</p>173 <p>{t('welcome.description')}</p>174 </div>175 );176}
Advanced Implementation
1// Advanced i18n configuration with namespaces and lazy loading2// i18n-advanced.ts3import i18n from 'i18next';4import { initReactI18next } from 'react-i18next';5import HttpApi from 'i18next-http-backend';6import LanguageDetector from 'i18next-browser-languagedetector';78// Namespace configuration9const namespaces = ['common', 'home', 'products', 'forms', 'errors'];1011i18n12 .use(HttpApi) // Load translations from backend13 .use(LanguageDetector)14 .use(initReactI18next)15 .init({16 backend: {17 loadPath: '/locales/{{lng}}/{{ns}}.json',18 addPath: '/locales/add/{{lng}}/{{ns}}'19 },2021 ns: namespaces,22 defaultNS: 'common',2324 fallbackLng: {25 'en-US': ['en'],26 'es-ES': ['es'],27 'ja-JP': ['ja'],28 default: ['en']29 },3031 debug: false,3233 interpolation: {34 escapeValue: false,35 format: function(value, format, lng) {36 // Custom formatting37 if (format === 'uppercase') return value.toUpperCase();38 if (format === 'currency') {39 return new Intl.NumberFormat(lng, {40 style: 'currency',41 currency: format.split(':')[1] || 'USD'42 }).format(value);43 }44 if (format === 'date') {45 return new Intl.DateTimeFormat(lng).format(value);46 }47 return value;48 }49 },5051 react: {52 useSuspense: true,53 bindI18n: 'languageChanged loaded',54 bindI18nStore: 'added removed',55 transEmptyNodeValue: '',56 transSupportBasicHtmlNodes: true,57 transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p']58 },5960 saveMissing: true,61 saveMissingTo: 'current',6263 keySeparator: '.',64 nsSeparator: ':',6566 pluralSeparator: '_',67 contextSeparator: '_',6869 // Cache options70 load: 'languageOnly',71 preload: ['en'],7273 // Performance optimizations74 cleanCode: true,75 nonExplicitSupportedLngs: true76 });7778export default i18n;7980// Lazy loading translations for specific routes81import { useEffect } from 'react';82import { useTranslation } from 'react-i18next';8384function ProductsPage() {85 const { t, i18n } = useTranslation(['products', 'common']);8687 useEffect(() => {88 // Load namespace if not already loaded89 i18n.loadNamespaces('products');90 }, [i18n]);9192 return (93 <div>94 <h1>{t('products:title')}</h1>95 <button>{t('common:save')}</button>96 </div>97 );98}