Skip to main content

Průvodce react-intl: Nastavení internacionalizace React

Nastavte FormatJS react-intl ve Vaší React aplikaci pomocí IntlProvider, FormattedMessage, useIntl, ICU message format a automatizovaných překladů.

Používáte místo toho react-i18next? Podívejte se na našeho průvodce react-i18next

1

Nainstalovat react-intl

react-intl je součástí projektu FormatJS. Poskytuje React komponenty a hooky pro formátování řetězců, čísel, dat a plurálů podle standardu ICU MessageFormat.

react-intl nemá žádné runtime závislosti kromě Reactu. Pro formátování čísel a dat používá vestavěné Intl API v prohlížeči a dodává vlastní parser ICU MessageFormat pro plurály, select a rich text.
Terminal
npm install react-intl
2

Nakonfigurovat IntlProvider

V kořeni obalte svou aplikaci do IntlProvider. Předávejte aktivní locale a plochý objekt messages. Každá komponenta pod ním pak může k překladům přistupovat přes FormattedMessage nebo 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 vyžaduje plochý objekt messages typu klíč-hodnota (např. { "app.greeting": "Hello" }). Vnořený JSON musíte před předáním do IntlProvider zploštit, nebo použít utilitu jako flat pro převod vnořených struktur.

Soubory zpráv

Vytvořte jeden JSON soubor pro každou lokalizaci. react-intl nativně používá syntaxi ICU MessageFormat — plurály, select i proměnné se zapisují přímo do řetězců zpráv.

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"
}
Pro organizaci používejte tečkou oddělená ID, například "nav.home". Na rozdíl od react-i18next očekává react-intl plochý objekt messages — zplošťujete klíče, ne strukturu.
3

Použít překlady v komponentách

react-intl Vám dává dvě hlavní API: komponentu FormattedMessage pro vykreslení přeloženého JSX a hook useIntl pro imperativní přístup (placeholdery, aria popisky, programové formátování).

Komponenta FormattedMessage

Pro deklarativní překlady v JSX použijte FormattedMessage. Předejte ID zprávy a případné hodnoty pro interpolaci. Komponenta přímo vykreslí přeložený řetězec.

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

useIntl() použijte, když potřebujete přeložený řetězec jako obyčejnou hodnotu — pro placeholdery vstupů, aria-labely, document.title nebo při předávání řetězců do non-React API. Hook také poskytuje formatNumber, formatDate a 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>
  );
}

Rich text (HTML v překladech)

Vkládejte JSX do překladů pomocí tagů podobných XML v řetězcích zpráv. Handlery tagů předejte přes prop values, abyste v přeložené zprávě mohli vykreslit odkazy, tučný text nebo libovolnou React komponentu.

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 ve výchozím nastavení vykreslí React Fragment. Pokud potřebujete konkrétní obalovací prvek, předejte textComponent do IntlProvider nebo FormattedMessage obalte vlastním prvkem.

Extrakce zpráv s @formatjs/cli

FormatJS poskytuje CLI, které automaticky extrahuje ID zpráv ze zdrojového kódu do JSON souboru. Tím zajistíte, že soubor zpráv zůstane synchronizovaný s komponentami bez ruční správy.

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

Plurály a ICU Select

react-intl nativně používá ICU MessageFormat. Plurály, výběr podle rodu (select) i vnořené formátování se zapisují přímo do řetězců zpráv — nejsou potřeba konvence se sufixy ani samostatné klíče.

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}個の商品があります"
}
Nikdy nehardcodujte logiku plurálů v JavaScriptu. Jazyky jako arabština mají 6 tvarů množného čísla, francouzština považuje 0 za singulár a japonština nemá rozlišení množného čísla. Nechte pravidla vyřešit ICU MessageFormat — pouze předejte hodnotu count.

ICU Select pro rod a role

Použijte syntaxi ICU select pro kontextově závislé překlady, jako je rod, role uživatele nebo stavové hodnoty. Výraz select vybere správnou variantu podle předané hodnoty.

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 }}
/>

Automatizovat kvalitu překladu

Zachyťte chybějící klíče a rozbité placeholdery dříve, než se dostanou do produkce, pomocí i18n-validate. Než dorazí skutečné překlady, otestujte UI pomocí pseudo-překladů v i18n-pseudo.

Běžná úskalí

Přílišné spoléhání na defaultMessage

defaultMessage je vývojový fallback, ne překladová strategie. Pokud používáte defaultMessage pro všechny řetězce, výstup extrakce zpráv bude obsahovat anglický text, ale překladatelům mohou uniknout nové klíče. Vždy extrahujte a udržujte kompletní zdrojový soubor pro výchozí locale.

Vnořené objekty místo plochých klíčů

IntlProvider očekává pro messages plochý Record&lt;string, string&gt;. Pokud předáte vnořený JSON jako { nav: { home: "Home" } }, react-intl nenajde klíč „nav.home“. Před předáním zprávy zploštěte, nebo použijte knihovnu jako flat.

IntlProvider způsobuje zbytečné re-rendery

Pokud vytváříte objekt messages inline uvnitř render funkce, IntlProvider při každém renderu dostane novou referenci objektu, což způsobí re-render všech konzumentů. Memoizujte messages pomocí useMemo nebo je definujte mimo komponentu.

Chybějící IntlProvider v testech

Komponenty používající FormattedMessage nebo useIntl vyhodí chybu, pokud jsou vykresleny bez nadřazeného IntlProvider. V testech obalte komponentu do IntlProvider s locale="en" a prázdným nebo minimálním objektem messages.

Doporučená struktura souborů

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

Vyzkoušejte i18n Agent nyní

Sem přetáhněte svůj překladový soubor

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

nebo klikněte a vyberte soubor

Cílové jazyky

Bez registraceOkamžitý odhad

Fallback lokalizací s react-intl-locale-chain

Když v regionální lokalizaci, jako je pt-BR, chybí překladový klíč, react-intl skočí rovnou na výchozí lokalizaci místo toho, aby nejdřív zkontroloval nadřazené 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>

Podívejte se do našeho Průvodce fallbackem lokalizací, kde najdete kompletní seznam podporovaných frameworků a 75 vestavěných řetězců. Learn more →

Často kladené otázky