Skip to main content

Vodič za react-intl: postavljanje internacionalizacije Reacta

Postavite FormatJS react-intl u svojoj React aplikaciji uz IntlProvider, FormattedMessage, useIntl, format poruka ICU i automatizirano prevođenje.

Umjesto toga koristite react-i18next? Pogledajte naš vodič za react-i18next

1

Instalirajte react-intl

react-intl dio je projekta FormatJS. Nudi React komponente i hookove za oblikovanje tekstova, brojeva, datuma i množine prema standardu ICU MessageFormat.

Osim Reacta, react-intl nema ovisnosti tijekom izvođenja. Za oblikovanje brojeva i datuma upotrebljava ugrađeni preglednikov API Intl, a isporučuje i vlastiti parser ICU MessageFormat za množinu, izraze select i obogaćeni tekst.
Terminal
npm install react-intl
2

Konfigurirajte IntlProvider

Komponentom IntlProvider obuhvatite korijen aplikacije. Proslijedite joj aktivnu lokalnu postavku i plosnati objekt messages. Svaka joj podređena komponenta tada može pristupiti prijevodima putem FormattedMessage ili 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 zahtijeva plosnati objekt messages s parovima ključ–vrijednost (npr. { "app.greeting": "Hello" }). Ugniježđeni JSON morate izravnati prije prosljeđivanja komponenti IntlProvider ili ga pretvoriti uslužnim alatom poput flat.

Datoteke poruka

Izradite po jednu JSON datoteku za svaku lokalnu postavku. react-intl izvorno upotrebljava sintaksu ICU MessageFormat — množina, izrazi select i varijable navode se izravno u nizovima poruka.

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"
}
Za organizaciju upotrebljavajte ID-ove razdvojene točkama, poput "nav.home". Za razliku od biblioteke react-i18next, react-intl očekuje plosnati objekt messages — izravnavate ključeve, a ne strukturu.
3

Upotrebljavajte prijevode u komponentama

react-intl nudi Vam dva glavna API-ja: komponentu FormattedMessage za iscrtavanje prevedenog JSX-a i hook useIntl za imperativni pristup (rezervirana mjesta, oznake aria i programsko oblikovanje).

Komponenta FormattedMessage

Upotrijebite FormattedMessage za deklarativne prijevode u JSX-u. Proslijedite ID poruke i sve interpolacijske vrijednosti. Komponenta izravno iscrtava prevedeni 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

Upotrijebite useIntl() kada prevedeni tekst trebate kao običnu vrijednost — za rezervirana mjesta polja za unos, oznake aria-label, document.title ili prosljeđivanje teksta API-jima izvan Reacta. Nudi i formatNumber, formatDate te 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>
  );
}

Obogaćeni tekst (HTML u prijevodima)

Ugradite JSX u prijevode s pomoću oznaka nalik XML-u u nizovima poruka. Putem svojstva values proslijedite obrađivače oznaka kako biste iscrtali poveznice, podebljani tekst ili bilo koju React komponentu unutar prevedene poruke.

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 prema zadanim postavkama iscrtava React Fragment. Ako trebate određeni omotni element, proslijedite svojstvo textComponent komponenti IntlProvider ili obuhvatite FormattedMessage vlastitim elementom.

Izdvajanje poruka pomoću @formatjs/cli

FormatJS nudi CLI za automatsko izdvajanje ID-ova poruka iz izvornog kôda u JSON datoteku. Tako datoteka poruka ostaje usklađena s komponentama bez ručnog vođenja evidencije.

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

Množine i ICU select

react-intl izvorno upotrebljava ICU MessageFormat. Množina, rodno uvjetovani izrazi select i ugniježđeno oblikovanje navode se izravno u nizovima poruka — nisu potrebne konvencije sufiksa ni zasebni ključevi.

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}個の商品があります"
}
Nikada nemojte izravno ugrađivati logiku množine u JavaScript. Arapski ima 6 oblika množine, francuski broj 0 smatra jedninom, a japanski ne razlikuje množinu. Pravila prepustite standardu ICU MessageFormat — samo proslijedite brojčanu vrijednost.

ICU select za rod i uloge

Upotrijebite sintaksu ICU select za prijevode ovisne o kontekstu, poput roda, korisničkih uloga ili vrijednosti stanja. Izraz select odabire odgovarajuću inačicu prema proslijeđenoj vrijednosti.

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

Automatizirajte provjeru kvalitete prijevoda

Alatom i18n-validate otkrijte ključeve koji nedostaju i neispravna rezervirana mjesta prije objave. Korisničko sučelje testirajte pseudoprijevodima uz i18n-pseudo prije nego što stignu stvarni prijevodi.

Uobičajene zamke

Pretjerano oslanjanje na defaultMessage

defaultMessage razvojna je zamjena, a ne strategija prevođenja. Ako defaultMessage upotrebljavate za sve tekstove, rezultat izdvajanja sadržavat će engleski tekst, ali prevoditelji mogu propustiti nove ključeve. Uvijek izdvojite i održavajte cjelovitu datoteku izvorne lokalne postavke.

Ugniježđeni objekti umjesto ravnih ključeva

IntlProvider za poruke očekuje plosnati Record&lt;string, string&gt;. Ako proslijedite ugniježđeni JSON poput { nav: { home: "Home" } }, react-intl neće pronaći ključ "nav.home". Izravnajte poruke prije prosljeđivanja ili upotrijebite biblioteku poput flat.

IntlProvider uzrokuje ponovna iscrtavanja

Ako objekt messages izradite izravno unutar funkcije render, IntlProvider pri svakom iscrtavanju prima novu referencu objekta, zbog čega se svi potrošači ponovno iscrtavaju. Memoizirajte poruke s pomoću useMemo ili ih definirajte izvan komponente.

IntlProvider nedostaje u testovima

Komponente koje upotrebljavaju FormattedMessage ili useIntl izbacit će pogrešku ako se iscrtaju bez nadređene komponente IntlProvider. U testovima komponentu obuhvatite komponentom IntlProvider s locale="en" te praznim ili minimalnim objektom messages.

Preporučena struktura datoteka

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

Isprobajte i18n Agent odmah

Povucite datoteku za prijevod ovdje

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

ili kliknite za odabir

Ciljni jezici

Registracija nije potrebnaProcjena odmah

Zamjenske lokalne postavke uz react-intl-locale-chain

Kada u regionalnoj lokalnoj postavci poput pt-BR nedostaje ključ prijevoda, react-intl odmah prelazi na zadanu postavku umjesto da prvo provjeri nadređenu postavku 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>

U našem vodiču za zamjenske lokalne postavke pogledajte cjelovit popis podržanih razvojnih okvira i 75 ugrađenih lanaca. Learn more →

Česta pitanja