Topic #45Core6 min read

Internationalization (i18n)

Translate UI with i18next/react-i18next, interpolate values, and handle RTL languages like Arabic.

#i18n#internationalization#i18next#rtl#localization

Internationalization (i18n) is structuring an app so its UI can be translated and localized without code changes. Instead of hard-coding strings, you reference translation keys (e.g. expense.title) that resolve to the active language's strings. The de-facto standard in React is i18next with the react-i18next bindings.

You configure i18next once with a resources object holding a translation map per language, a default language (lng), and a fallbackLng. Components call the useTranslation hook to get a t() function for looking up keys, plus the i18n instance for reading and changing the current language. t() supports interpolationt('expense.total', { amount: '₹1,200' }) fills the {{amount}} placeholder.

Beyond text, real i18n handles directionality. Right-to-left languages like Arabic require dir="rtl", which mirrors the layout. A common pattern is to set the dir attribute from the active language so the whole subtree flips automatically. Mature setups also handle pluralization, date/number/currency formatting (via the Intl API), and lazy-loading translation bundles per locale.

Backend Analogy

Translation keys are exactly Java's ResourceBundle / messages.properties files keyed by locale — t('expense.title') is MessageSource.getMessage('expense.title', locale). Interpolation with {{amount}} is MessageFormat placeholders. The fallbackLng is your default bundle when a locale-specific key is missing.

Key Insights
  • Never hard-code user-facing strings; reference translation keys resolved per active language.
  • react-i18next's useTranslation gives you t() for lookups and the i18n instance for changeLanguage.
  • Interpolation ({{amount}}) injects dynamic values into translated strings without string concatenation.
  • RTL support is more than translation: set dir="rtl" for languages like Arabic to mirror the layout.

Worked Code

Setup: i18next + react-i18next
TSX
// Setup: i18next + react-i18next
import i18n from 'i18next';
import { initReactI18next, useTranslation } from 'react-i18next';

i18n.use(initReactI18next).init({
  resources: {
    en: { translation: {
      'expense.title': 'My Expenses',
      'expense.add': 'Add Expense',
      'expense.amount': 'Amount',
      'expense.total': 'Total: {{amount}}',
    }},
    ar: { translation: {
      'expense.title': 'مصاريفي',
      'expense.add': 'إضافة مصروف',
      'expense.amount': 'المبلغ',
      'expense.total': 'المجموع: {{amount}}',
    }},
  },
  lng: 'en',
  fallbackLng: 'en',
});
Usage in components
TSX
// Usage in components
function Header() {
  const { t, i18n } = useTranslation();
  return (
    <header dir={i18n.language === 'ar' ? 'rtl' : 'ltr'}>
      <h1>{t('expense.title')}</h1>
      <p>{t('expense.total', { amount: '₹1,200' })}</p>
      <button onClick={() => i18n.changeLanguage('ar')}>
        العربية
      </button>
    </header>
  );
}

Interview-Ready Q&A

Adopt i18next with react-i18next. Extract all user-facing strings into per-language translation resource files keyed by stable identifiers (e.g. expense.title). Initialize i18next once with those resources, a default lng, and a fallbackLng. In components use the useTranslation hook's t() function to look up keys, and the i18n instance to switch languages. Add interpolation for dynamic values and the Intl API for date/number/currency formatting.

Things to Remember
  • 1Use translation keys, not hard-coded strings; i18next + react-i18next is the React standard.
  • 2useTranslation provides t() for lookups and i18n.changeLanguage to switch locale at runtime.
  • 3RTL = dir="rtl" plus logical CSS properties; interpolation handles dynamic values per language.

References & Further Reading