Skip to main content

Kompletny przewodnik po internacjonalizacji Reacta

Od zera do wielu języków: skonfiguruj i18n w aplikacji React, a następnie zautomatyzuj tłumaczenia za pomocą AI.

1

Instalacja pakietów

Potrzebne są trzy pakiety: react-i18next (powiązania z Reactem), i18next (główna biblioteka) oraz opcjonalnie i18next-browser-languagedetector do automatycznego wykrywania języka.

react-i18next udostępnia hooki i komponenty Reacta. i18next jest głównym silnikiem obsługującym wczytywanie tłumaczeń, interpolację i liczbę mnogą. Wtyczka wykrywająca automatycznie odczytuje preferowany język przeglądarki.
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

Konfigurowanie instancji i18n

Utwórz plik konfiguracji i18n inicjalizujący i18next z językiem domyślnym, zasobami tłumaczeń i łańcuchem wtyczek. Zaimportuj go w punkcie wejścia aplikacji, zanim zostanie wyrenderowany pierwszy komponent.

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" — ten błąd oznacza, że pominięto i18n.use(initReactI18next) przed i18n.init(). Wywołanie .use() musi nastąpić przed .init().
3

Otaczanie aplikacji przez I18nextProvider

Zaimportuj plik konfiguracji i18n w katalogu głównym aplikacji i otocz drzewo komponentów przez I18nextProvider. Bez tego useTranslation() zwraca surowe klucze zamiast przetłumaczonego tekstu.

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>
);
Jeśli zamiast "Welcome to our app" widać surowe klucze takie jak "welcome", najczęściej brakuje I18nextProvider albo importu pliku konfiguracji i18n.
4

Tworzenie plików tłumaczeń

Utwórz po jednym pliku JSON dla każdego języka. Użyj zagnieżdżonych kluczy, aby grupować teksty według funkcji lub strony. Zachowaj język źródłowy, zwykle angielski, jako jedno źródło referencyjne.

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"
  }
}
Nazywaj klucze według znaczenia, a nie miejsca wyświetlania: "cart.itemCount" jest lepsze niż "homepageCartLabel". Klucze powinny przetrwać przeprojektowanie interfejsu.
5

Używanie tłumaczeń w komponentach

Wywołaj useTranslation() w dowolnym komponencie, aby uzyskać funkcję t(). Używaj jej dla prostych tekstów, interpolowanych zmiennych oraz tłumaczeń z JSX przez komponent 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" />
    }} />
  );
}
Dynamiczne klucze takie jak t(`error.$'{code}'`) działają podczas wykonywania, ale narzędzia takie jak i18next-scanner nie potrafią ich statycznie wyodrębnić. Jeśli używasz ekstrakcji, jawnie wymień klucze dynamiczne lub dodaj wskazówkę w komentarzu.
6

Obsługa liczby mnogiej i zmiennych

i18next obsługuje liczbę mnogą zgodnie z CLDR, a nie tylko podział na formę pojedynczą i mnogą. Arabski ma 6 form (zero, one, two, few, many, other), a japoński 1 (other). Zdefiniuj wszystkie wymagane formy, a i18next automatycznie wybierze właściwą.

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}}個のアイテム"
}
Nigdy nie koduj count === 1 na stałe jako testu liczby pojedynczej. Francuski traktuje 0 jak liczbę pojedynczą, a rosyjski, arabski i polski mają formy nieobecne w angielskim. Pozwól i18next stosować reguły liczby mnogiej.
7

Zmiana i wykrywanie języka

Utwórz selektor języka wywołujący i18n.changeLanguage(). Połącz go z wykrywaniem języka przeglądarki, aby przy pierwszej wizycie wybrać preferowany język użytkownika, a następnie zapisywać jego jawny wybór.

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>
  );
}
Przy SSR (Next.js, Remix) serwer może wykryć inny język niż klient, ponieważ nie zna preferencji przeglądarki. Powoduje to niezgodność hydratacji. Przekaż wykryte ustawienia z serwera do klienta jako prop lub cookie, aby oba renderowały ten sam język.
8

Automatyzacja tłumaczeń

Po skonfigurowaniu i18n przetłumacz pliki językowe za pomocą AI. Poproś asystenta w środowisku programistycznym o przetłumaczenie pliku źródłowego lub użyj CLI i18n Agent w pipeline 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
Tłumacz przyrostowo — po dodaniu nowych kluczy przetłumacz tylko różnicę zamiast ponownie generować wszystkie pliki. Pozwoli to zachować tłumaczenia sprawdzone przez człowieka.

Automatyczna kontrola jakości tłumaczeń

Wykryj brakujące klucze i uszkodzone symbole zastępcze przed wydaniem za pomocą i18n-validate. Przetestuj interfejs przy użyciu sztucznych tłumaczeń z i18n-pseudo, zanim pojawią się prawdziwe tłumaczenia.

Częste pułapki

Tłumaczenia wyświetlają surowe klucze

Przyczyny: brak I18nextProvider, brak importu konfiguracji i18n w katalogu głównym, niewczytana przestrzeń nazw lub asynchroniczne wczytywanie. Włącz debug: true i sprawdź wskazówki w konsoli przeglądarki.

Błąd Suspense bez fallbacku

"A component suspended while responding to synchronous input" — dodaj granicę '&lt;Suspense&gt;' wokół aplikacji albo ustaw useSuspense: false w konfiguracji init i18next.

Niezgodność hydratacji SSR

Serwer renderuje jeden język, a klient hydratuje inny. Upewnij się, że oba korzystają z tego samego źródła — przekaż język jako prop z serwera i nie polegaj wyłącznie na wykrywaniu przeglądarki.

Brak autouzupełniania kluczy tłumaczeń

Rozszerz moduł i18next o typ zasobów: declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'. Zapewni to bezpieczne pod względem typów wywołania t() z autouzupełnianiem.

Zalecana struktura plików

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

Wypróbuj i18n Agent

Upuść tutaj plik tłumaczenia

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

lub kliknij, aby go wybrać

Języki docelowe

Rejestracja nie jest wymaganaNatychmiastowa wycena

Częste pytania