Skip to main content

react-intl ceļvedis: React internacionalizācijas iestatīšana

Iestatiet FormatJS react-intl React lietotnē ar IntlProvider, FormattedMessage, useIntl, ICU ziņojumu formātu un automatizētu tulkošanu.

Vai tā vietā izmantojat react-i18next? Skatīt mūsu react-i18next ceļvedi

1

Instalēt react-intl

react-intl ir daļa no FormatJS projekta. Tā nodrošina React komponentus un āķus virkņu, skaitļu, datumu un daudzskaitļa formatēšanai ar ICU MessageFormat standartu.

Papildus React react-intl nav izpildlaika atkarību. Skaitļu un datumu formatēšanai tā izmanto pārlūka iebūvēto Intl API, bet daudzskaitlim, izvēlei un bagātinātam tekstam nodrošina savu ICU MessageFormat parsētāju.
Terminal
npm install react-intl
2

Konfigurēt IntlProvider

Ietveriet lietotni ar IntlProvider saknē. Nododiet aktīvo lokalizāciju un plakanu ziņojumu objektu. Tad katrs zemāk esošais komponents varēs piekļūt tulkojumiem ar FormattedMessage vai 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 vajadzīgs plakans ziņojumu atslēgu un vērtību objekts (piemēram, { "app.greeting": "Hello" }). Ligzdots JSON pirms nodošanas IntlProvider jāsaplacina vai ligzdotās struktūras jāpārveido ar tādu rīku kā flat.

Ziņojumu faili

Izveidojiet vienu JSON failu katrai lokalizācijai. react-intl tieši izmanto ICU MessageFormat sintaksi: daudzskaitlis, izvēle un mainīgie tiek izteikti ziņojumu virknēs.

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"
}
Sakārtošanai izmantojiet ar punktiem atdalītus ID, piemēram, „nav.home“. Atšķirībā no react-i18next react-intl sagaida plakanu ziņojumu objektu: saplacināt atslēgas, nevis struktūru.
3

Izmantot tulkojumus komponentos

react-intl nodrošina divas galvenās API: komponentu FormattedMessage tulkota JSX atveidei un āķi useIntl imperatīvai piekļuvei (vietturiem, aria etiķetēm, programmētiskai formatēšanai).

FormattedMessage komponents

Izmantojiet FormattedMessage deklaratīviem tulkojumiem JSX. Nododiet ziņojuma ID un visas interpolācijas vērtības. Tas tieši atveido tulkoto virkni.

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>
  );
}

useIntl āķis

Izmantojiet useIntl(), ja tulkotā virkne vajadzīga kā vienkārša vērtība: ievades lauku vietturiem, aria-label, document.title vai nododot virknes API ārpus React. Tas nodrošina arī formatNumber, formatDate un 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>
  );
}

Bagātināts teksts (HTML tulkojumos)

Ieguliet JSX tulkojumos, izmantojot XML līdzīgus tagus ziņojumu virknēs. Nododiet tagu apstrādātājus ar rekvizītu values, lai tulkotā ziņojumā atveidotu saites, treknrakstu vai jebkuru 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>,
      }}
    />
  );
}
Pēc noklusējuma FormattedMessage atveido React Fragment. Ja vajadzīgs konkrēts aptverošs elements, nododiet rekvizītu textComponent IntlProvider vai ietveriet FormattedMessage savā elementā.

Ziņojumu izvilkšana ar @formatjs/cli

FormatJS nodrošina CLI, kas automātiski izvelk ziņojumu ID no pirmkoda JSON failā. Tas uztur ziņojumu failu sinhronizētu ar komponentiem bez manuālas uzskaites.

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

Daudzskaitlis un ICU izvēle

react-intl tieši izmanto ICU MessageFormat. Daudzskaitlis, uz dzimti balstīta izvēle un ligzdots formatējums tiek izteikts ziņojumu virknēs — nav vajadzīgi sufiksu nosacījumi vai atsevišķas atslēgas.

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}個の商品があります"
}
Nekad tieši neierakstiet daudzskaitļa loģiku JavaScript. Arābu valodā ir 6 daudzskaitļa formas, franču valodā 0 uzskata par vienskaitli, bet japāņu valodā daudzskaitli vispār nenošķir. Ļaujiet ICU MessageFormat apstrādāt kārtulas — vienkārši nododiet skaita vērtību.

ICU izvēle dzimtei un lomām

Izmantojiet ICU izvēles sintaksi no konteksta atkarīgiem tulkojumiem, piemēram, dzimtei, lietotāju lomām vai stāvokļa vērtībām. Izvēles izteiksme atlasa pareizo variantu pēc norādītās vērtības.

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

Automatizēt tulkojumu kvalitāti

Ar i18n-validate pirms izlaišanas atrodiet trūkstošās atslēgas un bojātos vietturus. Kamēr īstie tulkojumi vēl nav gatavi, pārbaudiet UI ar i18n-pseudo pseidotulkojumiem.

Biežākās kļūdas

Pārmērīga paļaušanās uz defaultMessage

defaultMessage ir izstrādes atkāpšanās variants, nevis tulkošanas stratēģija. Ja defaultMessage izmantojat visām virknēm, ziņojumu izvilkšanas izvadē būs angļu teksts, taču tulkotāji var nepamanīt jaunas atslēgas. Vienmēr izvelciet un uzturiet pilnīgu avota lokalizācijas failu.

Ligzdoti objekti plakanu atslēgu vietā

IntlProvider sagaida plakanu Record&lt;string, string&gt; objektam messages. Ja nododat ligzdotu JSON, piemēram, { nav: { home: "Home" } }, react-intl neatradīs atslēgu „nav.home“. Pirms nodošanas saplaciniet ziņojumus vai izmantojiet tādu bibliotēku kā flat.

IntlProvider izraisa atkārtotu atveidi

Ja objektu messages izveidojat tieši atveides funkcijā, IntlProvider katrā atveidē saņem jaunu objekta atsauci, izraisot visu patērētāju atkārtotu atveidi. Iegaumējiet messages ar useMemo vai definējiet tos ārpus komponenta.

Testos trūkst IntlProvider

Komponenti, kas izmanto FormattedMessage vai useIntl, izmetīs kļūdu, ja tiks atveidoti bez IntlProvider priekšteča. Testos ietveriet komponentu ar IntlProvider, kam ir locale="en" un tukšs vai minimāls objekts messages.

Ieteicamā failu struktūra

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

Izmēģiniet i18n Agent tūlīt

Nometiet tulkošanas failu šeit

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

vai noklikšķiniet, lai izvēlētos

Mērķa valodas

Reģistrācija nav vajadzīgaTūlītēja tāme

Lokalizācijas atkāpšanās ar react-intl-locale-chain

Ja reģionālajā lokalizācijā, piemēram, pt-BR, trūkst tulkojuma atslēgas, react-intl uzreiz pāriet uz noklusējuma lokalizāciju, nevis vispirms pārbauda vecāklokalizāciju 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>

Pilnu atbalstīto sistēmu sarakstu un 75 iebūvētās ķēdes skatiet mūsu lokalizāciju atkāpšanās ceļvedī. Learn more →

Bieži uzdotie jautājumi