Skip to main content

Ghidul complet pentru internaționalizarea în React

De la zero la o aplicație multilingvă: configurați i18n în aplicația React, apoi automatizați traducerile cu IA.

1

Instalați pachetele

Aveți nevoie de trei pachete: react-i18next (legăturile pentru React), i18next (biblioteca de bază) și, opțional, i18next-browser-languagedetector pentru detectarea automată a setărilor regionale.

react-i18next oferă hook-uri și componente React. i18next este motorul de bază care gestionează încărcarea traducerilor, interpolarea și formele de plural. Pluginul de detectare a limbii citește automat preferința lingvistică a browserului.
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

Configurați instanța i18n

Creați un fișier de configurare i18n care inițializează i18next cu limba implicită, resursele de traducere și lanțul de pluginuri. Acest fișier trebuie importat în punctul de intrare al aplicației înainte de afișarea oricărei componente.

src/i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)  // Must come before .init()
  .init({
    fallbackLng: 'en',
    debug: process.env.NODE_ENV === 'development',
    interpolation: {
      escapeValue: false,  // React already escapes
    },
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json',
    },
  });

export default i18n;
„You will need to pass in an i18next instance by using initReactI18next” — această eroare înseamnă că ați omis să apelați i18n.use(initReactI18next) înainte de i18n.init(). Apelul .use() trebuie să fie plasat înainte de .init().
3

Încadrați aplicația cu I18nextProvider

Importați fișierul de configurare i18n la rădăcina aplicației și încadrați arborele de componente cu I18nextProvider. Fără acesta, useTranslation() returnează cheile brute în locul textului tradus.

src/main.tsx
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n';  // Import your config
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Suspense fallback={<div>Loading...</div>}>
      <I18nextProvider i18n={i18n}>
        <App />
      </I18nextProvider>
    </Suspense>
  </React.StrictMode>
);
Dacă traducerile afișează chei brute precum „welcome” în loc de „Bun venit în aplicația noastră”, cauza cea mai frecventă este absența I18nextProvider sau neimportarea fișierului de configurare i18n.
4

Creați fișierele de traducere

Creați câte un fișier JSON pentru fiecare limbă. Folosiți chei imbricate pentru a organiza textele după funcționalitate sau pagină. Păstrați limba-sursă (de obicei engleza) drept unica sursă de referință.

public/locales/en/translation.json
// public/locales/en/translation.json
{
  "nav": {
    "home": "Home",
    "about": "About",
    "settings": "Settings"
  },
  "greeting": "Hello, {{name}}!",
  "cart": {
    "itemCount_one": "{{count}} item",
    "itemCount_other": "{{count}} items"
  }
}

// public/locales/de/translation.json
{
  "nav": {
    "home": "Startseite",
    "about": "Über uns",
    "settings": "Einstellungen"
  },
  "greeting": "Hallo, {{name}}!",
  "cart": {
    "itemCount_one": "{{count}} Artikel",
    "itemCount_other": "{{count}} Artikel"
  }
}
Denumiți cheile după ceea ce descriu, nu după locul în care apar: "cart.itemCount" este mai potrivit decât "homepageCartLabel". Cheile trebuie să rămână valabile după reproiectarea interfeței.
5

Folosiți traducerile în componente

Apelați useTranslation() în orice componentă pentru a obține funcția t(). Folosiți-o pentru texte simple, variabile interpolate și traduceri care includ JSX, cu ajutorul componentei Trans.

Greeting.tsx
import { useTranslation } from 'react-i18next';

function Greeting({ userName }: { userName: string }) {
  const { t } = useTranslation();

  return (
    <div>
      <h1>{t('greeting', { name: userName })}</h1>
      <nav>
        <a href="/">{t('nav.home')}</a>
        <a href="/about">{t('nav.about')}</a>
      </nav>
    </div>
  );
}
Trans component for JSX
import { Trans, useTranslation } from 'react-i18next';

// For JSX inside translations:
// "terms": "By signing up, you agree to our <link>Terms</link>."

function SignUp() {
  const { t } = useTranslation();
  return (
    <Trans i18nKey="terms" components={{
      link: <a href="/terms" className="underline" />
    }} />
  );
}
Cheile dinamice precum t(`error.$'{code}'`) funcționează în timpul execuției, dar nu pot fi extrase static de instrumente precum i18next-scanner. Dacă folosiți instrumente de extragere, enumerați explicit cheile dinamice sau folosiți un comentariu ajutător.
6

Gestionați formele de plural și variabilele

i18next gestionează formele de plural pe baza regulilor CLDR, nu doar singularul și pluralul. Araba are 6 forme (zero, one, two, few, many, other). Japoneza are una singură (other). Definiți toate formele necesare în fișierele de traducere, iar i18next o va selecta automat pe cea corectă.

Plural forms by language
// English: 2 forms (one, other)
{
  "itemCount_one": "{{count}} item",
  "itemCount_other": "{{count}} items"
}

// Arabic: 6 forms (zero, one, two, few, many, other)
{
  "itemCount_zero": "لا عناصر",
  "itemCount_one": "عنصر واحد",
  "itemCount_two": "عنصران",
  "itemCount_few": "{{count}} عناصر",
  "itemCount_many": "{{count}} عنصرًا",
  "itemCount_other": "{{count}} عنصر"
}

// Japanese: 1 form (other)
{
  "itemCount_other": "{{count}}個のアイテム"
}
Nu codificați niciodată direct count === 1 pentru detectarea singularului. Limbi precum franceza tratează 0 drept singular. Rusa, araba și poloneza au forme inexistente în engleză. Lăsați i18next să gestioneze regulile de plural.
7

Adăugați schimbarea și detectarea limbii

Creați un selector de limbă care apelează i18n.changeLanguage(). Combinați-l cu detectorul de limbă al browserului pentru a identifica automat limba preferată a utilizatorului la prima vizită, apoi păstrați alegerea explicită a acestuia.

LanguageSwitcher.tsx
import { useTranslation } from 'react-i18next';

const LANGUAGES = [
  { code: 'en', label: 'English' },
  { code: 'de', label: 'Deutsch' },
  { code: 'ja', label: '日本語' },
  { code: 'es', label: 'Español' },
];

function LanguageSwitcher() {
  const { i18n } = useTranslation();

  return (
    <select
      value={i18n.language}
      onChange={(e) => i18n.changeLanguage(e.target.value)}
    >
      {LANGUAGES.map(({ code, label }) => (
        <option key={code} value={code}>{label}</option>
      ))}
    </select>
  );
}
Dacă folosiți SSR (Next.js, Remix), serverul poate detecta o altă limbă decât clientul (serverul nu are acces la preferințele browserului). Aceasta provoacă o neconcordanță la hidratare. Soluție: transmiteți setările regionale detectate de la server către client ca proprietate sau cookie, astfel încât ambele să afișeze aceeași limbă.
8

Automatizați traducerile

După finalizarea configurării i18n, traduceți fișierele cu setări regionale folosind IA. În IDE, solicitați-i asistentului IA să traducă fișierul-sursă sau folosiți i18n Agent CLI în fluxul CI/CD.

Terminal
# In your IDE, ask your AI assistant:
> Translate public/locales/en/translation.json to German, Japanese, and Spanish

✓ de/translation.json created (1.2s)
✓ ja/translation.json created (1.5s)
✓ es/translation.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate public/locales/en/translation.json --lang de,ja,es
Traduceți incremental — când adăugați chei noi în fișierul-sursă, traduceți doar diferențele, în loc să regenerați toate fișierele. Astfel păstrați traducerile verificate de oameni.

Automatizați controlul calității traducerilor

Detectați cheile lipsă și substituenții nevalizi înainte de lansare cu i18n-validate. Testați interfața cu traduceri fictive folosind i18n-pseudo înainte de sosirea traducerilor reale.

Probleme frecvente

Traducerile afișează cheile brute

Cauze: lipsește I18nextProvider, configurația i18n nu este importată la rădăcina aplicației, spațiul de nume nu este încărcat sau traducerile încă se încarcă asincron. Verificați consola browserului cu debug: true pentru indicii.

Eroare Suspense fără conținut alternativ

„A component suspended while responding to synchronous input” — adăugați o delimitare '&lt;Suspense&gt;' în jurul aplicației sau setați useSuspense: false în configurația de inițializare i18next.

Neconcordanță la hidratarea SSR

Serverul afișează conținutul într-o anumită limbă, iar clientul îl hidratează în alta. Asigurați-vă că ambele folosesc aceeași sursă pentru setările regionale — transmiteți-le ca proprietate de la server și nu vă bazați exclusiv pe detectarea din browser.

Lipsește completarea automată pentru cheile de traducere

Extindeți modulul i18next cu tipul resurselor dumneavoastră: declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'. Astfel beneficiați de apeluri t() cu siguranță de tip și completare automată.

Structura recomandată a fișierelor

Project Structure
my-react-app/
├── public/
│   └── locales/
│       ├── en/
│       │   ├── translation.json    # Default namespace
│       │   ├── common.json         # Shared strings
│       │   └── dashboard.json      # Feature namespace
│       ├── de/
│       │   ├── translation.json
│       │   ├── common.json
│       │   └── dashboard.json
│       └── ja/
│           └── ...
├── src/
│   ├── i18n.ts                     # i18n configuration
│   ├── main.tsx                    # App entry with Provider
│   ├── App.tsx
│   └── components/
│       └── LanguageSwitcher.tsx
└── package.json

Încercați acum i18n Agent

Plasați aici fișierul de traducere

JSON, YAML, PO, XML, CSV, Markdown, Properties

sau faceți clic pentru a-l selecta

Limbi țintă

Nu este necesară înregistrareaEstimare instantanee

Întrebări frecvente