Skip to main content

Przewodnik po react-intl: konfiguracja internacjonalizacji Reacta

Skonfiguruj FormatJS react-intl w aplikacji React za pomocą IntlProvider, FormattedMessage, useIntl, formatu wiadomości ICU i automatycznych tłumaczeń.

Korzystasz zamiast tego z react-i18next? Zobacz nasz przewodnik po react-i18next

1

Zainstaluj react-intl

react-intl jest częścią projektu FormatJS. Udostępnia komponenty i hooki Reacta do formatowania tekstów, liczb, dat oraz liczby mnogiej zgodnie ze standardem ICU MessageFormat.

Poza Reactem react-intl nie ma żadnych zależności wymaganych podczas działania. Do formatowania liczb i dat używa wbudowanego w przeglądarkę API Intl, a własny parser ICU MessageFormat obsługuje liczbę mnogą, select i tekst sformatowany.
Terminal
npm install react-intl
2

Skonfiguruj IntlProvider

Otocz aplikację komponentem IntlProvider w jej głównym punkcie. Przekaż aktywny język oraz płaski obiekt messages. Każdy komponent poniżej uzyska wtedy dostęp do tłumaczeń przez FormattedMessage lub useIntl.

src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { IntlProvider } from 'react-intl';
import App from './App';
import enMessages from './messages/en.json';
import deMessages from './messages/de.json';

const messages: Record<string, Record<string, string>> = {
  en: enMessages,
  de: deMessages,
};

// Detect locale from browser or your routing layer
const locale = navigator.language.split('-')[0] || 'en';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <IntlProvider locale={locale} messages={messages[locale] || messages.en}>
      <App />
    </IntlProvider>
  </React.StrictMode>
);
IntlProvider wymaga płaskiego obiektu wiadomości z parami klucz–wartość (np. { "app.greeting": "Hello" }). Zagnieżdżony JSON trzeba spłaszczyć przed przekazaniem do IntlProvider albo przekształcić za pomocą narzędzia takiego jak flat.

Pliki wiadomości

Utwórz po jednym pliku JSON dla każdego języka. react-intl natywnie używa składni ICU MessageFormat — liczba mnoga, select i zmienne są zapisywane bezpośrednio w tekstach wiadomości.

messages/en.json & messages/de.json
// messages/en.json
{
  "app.greeting": "Hello, {name}!",
  "nav.home": "Home",
  "nav.about": "About",
  "nav.settings": "Settings",
  "cart.itemCount": "{count, plural, one {# item} other {# items}} in your cart"
}

// messages/de.json
{
  "app.greeting": "Hallo, {name}!",
  "nav.home": "Startseite",
  "nav.about": "Über uns",
  "nav.settings": "Einstellungen",
  "cart.itemCount": "{count, plural, one {# Artikel} other {# Artikel}} in Ihrem Warenkorb"
}
Do organizacji używaj identyfikatorów rozdzielonych kropkami, takich jak „nav.home”. W przeciwieństwie do react-i18next react-intl oczekuje płaskiego obiektu messages — spłaszczasz klucze, a nie strukturę.
3

Używaj tłumaczeń w komponentach

react-intl udostępnia dwa główne API: komponent FormattedMessage do renderowania przetłumaczonego JSX oraz hook useIntl do dostępu imperatywnego (symbole zastępcze, etykiety aria i formatowanie programistyczne).

Komponent FormattedMessage

Używaj FormattedMessage do deklaratywnych tłumaczeń w JSX. Przekaż identyfikator wiadomości i wartości interpolacji. Komponent bezpośrednio renderuje przetłumaczony tekst.

Greeting.tsx
import { FormattedMessage } from 'react-intl';

function Greeting({ userName }: { userName: string }) {
  return (
    <div>
      <h1>
        <FormattedMessage
          id="app.greeting"
          values={{ name: userName }}
        />
      </h1>
      <nav>
        <a href="/"><FormattedMessage id="nav.home" /></a>
        <a href="/about"><FormattedMessage id="nav.about" /></a>
      </nav>
    </div>
  );
}

Hook useIntl

Użyj useIntl(), gdy potrzebujesz przetłumaczonego tekstu jako zwykłej wartości — dla symboli zastępczych pól, aria-label, document.title lub podczas przekazywania tekstów do API niezwiązanych z Reactem. Udostępnia też formatNumber, formatDate i formatRelativeTime.

SearchBar.tsx
import { useIntl } from 'react-intl';

function SearchBar() {
  const intl = useIntl();

  return (
    <input
      type="search"
      placeholder={intl.formatMessage({ id: 'search.placeholder' })}
      aria-label={intl.formatMessage({ id: 'search.ariaLabel' })}
    />
  );
}

// useIntl also gives you formatNumber, formatDate, formatRelativeTime:
function PriceTag({ amount, currency }: { amount: number; currency: string }) {
  const intl = useIntl();
  return (
    <span>{intl.formatNumber(amount, { style: 'currency', currency })}</span>
  );
}

Tekst sformatowany (HTML w tłumaczeniach)

Osadzaj JSX w tłumaczeniach za pomocą znaczników podobnych do XML w tekstach wiadomości. Przekaż procedury obsługi znaczników przez właściwość values, aby renderować odnośniki, pogrubienie lub dowolny komponent Reacta wewnątrz przetłumaczonej wiadomości.

SignUp.tsx
import { FormattedMessage } from 'react-intl';

// Message: "By signing up, you agree to our <link>Terms</link>."
// Key: "signup.terms"
// Value: "By signing up, you agree to our <link>Terms</link>."

function SignUp() {
  return (
    <FormattedMessage
      id="signup.terms"
      values={{
        link: (chunks) => <a href="/terms" className="underline">{chunks}</a>,
      }}
    />
  );
}
FormattedMessage domyślnie renderuje React Fragment. Jeśli potrzebujesz określonego elementu opakowującego, przekaż właściwość textComponent do IntlProvider albo otocz FormattedMessage własnym elementem.

Wyodrębnianie wiadomości za pomocą @formatjs/cli

FormatJS udostępnia CLI, które automatycznie wyodrębnia identyfikatory wiadomości z kodu źródłowego do pliku JSON. Dzięki temu plik wiadomości pozostaje zsynchronizowany z komponentami bez ręcznego prowadzenia ewidencji.

Terminal
# Install the CLI
npm install -g @formatjs/cli

# Extract messages from source code into a JSON file
formatjs extract 'src/**/*.tsx' --out-file messages/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'

# Or use explicit IDs (recommended):
formatjs extract 'src/**/*.tsx' --out-file messages/en.json

# Compile messages for production (optional, improves perf)
formatjs compile messages/en.json --out-file compiled/en.json
formatjs compile messages/de.json --out-file compiled/de.json
4

Liczba mnoga i select ICU

react-intl natywnie używa ICU MessageFormat. Liczba mnoga, select zależny od rodzaju oraz formatowanie zagnieżdżone są zapisywane bezpośrednio w tekstach wiadomości — bez konwencji przyrostków ani osobnych kluczy.

ICU plural syntax by language
// ICU MessageFormat syntax — react-intl uses this natively
// English
{
  "cart.itemCount": "{count, plural, one {# item} other {# items}} in your cart",
  "inbox.unread": "You have {count, plural, =0 {no unread messages} one {# unread message} other {# unread messages}}"
}

// Arabic — 6 plural forms
{
  "cart.itemCount": "{count, plural, zero {لا عناصر} one {عنصر واحد} two {عنصران} few {# عناصر} many {# عنصرًا} other {# عنصر}} في سلتك"
}

// Japanese — 1 form (other)
{
  "cart.itemCount": "カートに{count}個の商品があります"
}
Nigdy nie zapisuj logiki liczby mnogiej na stałe w JavaScript. Języki takie jak arabski mają 6 form liczby mnogiej, francuski traktuje 0 jak liczbę pojedynczą, a japoński nie rozróżnia liczby. Pozwól ICU MessageFormat obsłużyć reguły — wystarczy przekazać wartość count.

ICU select dla rodzaju i ról

Użyj składni ICU select do tłumaczeń zależnych od kontekstu, takich jak rodzaj, role użytkowników lub wartości stanu. Wyrażenie select wybiera właściwy wariant na podstawie przekazanej wartości.

ICU select syntax
// Gender-dependent messages using ICU select
{
  "user.greeting": "{gender, select, male {He} female {She} other {They}} liked your post.",
  "user.invitation": "{role, select, admin {You can manage all settings.} editor {You can edit content.} other {You can view content.}}"
}

// Usage:
<FormattedMessage
  id="user.greeting"
  values={{ gender: user.gender }}
/>

Zautomatyzuj kontrolę jakości tłumaczeń

Wykrywaj brakujące klucze i uszkodzone symbole zastępcze przed wydaniem za pomocą i18n-validate. Testuj interfejs z pseudotłumaczeniami przy użyciu i18n-pseudo, zanim pojawią się prawdziwe tłumaczenia.

Typowe pułapki

Nadmierne poleganie na defaultMessage

defaultMessage to wartość rezerwowa do programowania, a nie strategia tłumaczeniowa. Jeśli używasz defaultMessage dla wszystkich tekstów, wynik wyodrębniania wiadomości będzie zawierał angielski tekst, ale tłumacze mogą przeoczyć nowe klucze. Zawsze wyodrębniaj i utrzymuj kompletny plik języka źródłowego.

Obiekty zagnieżdżone zamiast płaskich kluczy

IntlProvider oczekuje płaskiego Record&lt;string, string&gt; dla messages. Jeśli przekażesz zagnieżdżony JSON taki jak { nav: { home: "Home" } }, react-intl nie znajdzie klucza „nav.home”. Spłaszcz wiadomości przed ich przekazaniem albo użyj biblioteki takiej jak flat.

IntlProvider powoduje ponowne renderowanie

Jeśli utworzysz obiekt messages bezpośrednio w funkcji renderującej, IntlProvider przy każdym renderowaniu otrzyma nową referencję do obiektu, co spowoduje ponowne renderowanie wszystkich konsumentów. Zapamiętaj messages za pomocą useMemo albo zdefiniuj je poza komponentem.

Brak IntlProvider w testach

Komponenty używające FormattedMessage lub useIntl zgłoszą wyjątek, jeśli zostaną wyrenderowane bez nadrzędnego IntlProvider. W testach umieść komponent wewnątrz IntlProvider z locale="en" oraz pustym lub minimalnym obiektem messages.

Zalecana struktura plików

Project Structure
my-react-app/
├── messages/
│   ├── en.json              # Source of truth (English)
│   ├── de.json              # German
│   ├── ja.json              # Japanese
│   └── es.json              # Spanish
├── compiled/                # Optional: compiled messages for prod
│   ├── en.json
│   └── ...
├── src/
│   ├── main.tsx             # App entry with IntlProvider
│   ├── App.tsx
│   └── components/
│       ├── Greeting.tsx      # Uses FormattedMessage
│       └── SearchBar.tsx     # Uses useIntl
└── 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

Rezerwowe ustawienia regionalne z react-intl-locale-chain

Gdy brakuje klucza tłumaczenia w regionalnym wariancie języka, takim jak pt-BR, react-intl przechodzi bezpośrednio do języka domyślnego, zamiast najpierw sprawdzić język nadrzędny pt.

Terminal
npm install react-intl-locale-chain
Configuration
<LocaleChainProvider
  fallbacks={{
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  }}
  defaultLocale="en"
>
  <App />
</LocaleChainProvider>

Zobacz nasz przewodnik po rezerwowych ustawieniach regionalnych, aby poznać pełną listę obsługiwanych frameworków i 75 wbudowanych łańcuchów. Learn more →

Najczęściej zadawane pytania