Skip to main content

react-intl-guide: Oppsett av React-internasjonalisering

Sett opp FormatJS react-intl i React-appen din med IntlProvider, FormattedMessage, useIntl, ICU-meldingsformat og automatiserte oversettelser.

Bruker du react-i18next i stedet? Se guiden vår for react-i18next

1

Installer react-intl

react-intl er en del av FormatJS-prosjektet. Det gir React-komponenter og hooks for å formatere strenger, tall, datoer og flertallsformer med ICU MessageFormat-standarden.

react-intl har ingen kjøretidsavhengigheter utover React. Det bruker nettleserens innebygde Intl-API for tall- og datoformatering, og leveres med sin egen ICU MessageFormat-parser for flertallsformer, select og rik tekst.
Terminal
npm install react-intl
2

Konfigurer IntlProvider

Pakk inn appen din med IntlProvider på rotnivå. Send med det aktive språket og et flatt meldingsobjekt. Alle komponenter under kan da få tilgang til oversettelser via FormattedMessage eller 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 krever et flatt nøkkel-verdi-meldingsobjekt (f.eks. { "app.greeting": "Hello" }). Nøstet JSON må flates ut før det sendes til IntlProvider, eller du kan bruke et verktøy som flat for å konvertere nøstede strukturer.

Meldingsfiler

Opprett én JSON-fil per språk. react-intl bruker ICU MessageFormat-syntaks direkte — flertallsformer, select og variabler uttrykkes alle direkte i meldingsstrengene.

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"
}
Bruk punktseparerte ID-er som "nav.home" for organisering. I motsetning til react-i18next forventer react-intl et flatt meldingsobjekt — du flater ut nøklene, ikke strukturen.
3

Bruk oversettelser i komponenter

react-intl gir deg to primære API-er: FormattedMessage-komponenten for å gjengi oversatt JSX, og useIntl-hooken for imperativ tilgang (plassholdere, aria-etiketter, programmatisk formatering).

FormattedMessage-komponenten

Bruk FormattedMessage for deklarative oversettelser i JSX. Send med meldings-ID-en og eventuelle interpolasjonsverdier. Den gjengir den oversatte strengen direkte.

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-hooken

Bruk useIntl() når du trenger den oversatte strengen som en ren verdi — for input-plassholdere, aria-labels, document.title, eller når du sender strenger til API-er utenfor React. Den gir også tilgang til formatNumber, formatDate og 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>
  );
}

Rik tekst (HTML i oversettelser)

Bygg inn JSX i oversettelser ved å bruke XML-lignende tagger i meldingsstrengene dine. Send med taggbehandlere via values-egenskapen for å gjengi lenker, uthevet tekst eller andre React-komponenter inne i en oversatt melding.

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 gjengir som standard et React Fragment. Hvis du trenger et bestemt omsluttende element, sender du textComponent-egenskapen til IntlProvider eller pakker inn FormattedMessage i ditt eget element.

Uttrekk av meldinger med @formatjs/cli

FormatJS tilbyr et CLI-verktøy som automatisk trekker ut meldings-ID-er fra kildekoden din til en JSON-fil. Dette sørger for at meldingsfilen din holdes synkronisert med komponentene dine uten manuell oppfølging.

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

Flertallsformer og ICU select

react-intl bruker ICU MessageFormat direkte. Flertallsformer, kjønnsbasert select og nøstet formatering uttrykkes alle direkte i meldingsstrenger — det er ikke behov for suffikskonvensjoner eller separate nøkler.

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}個の商品があります"
}
Hardkod aldri flertallslogikk i JavaScript. Språk som arabisk har 6 flertallsformer, fransk behandler 0 som entall, og japansk har ingen flertallsdistinksjon. La ICU MessageFormat håndtere reglene — send bare med tallverdien.

ICU select for kjønn og roller

Bruk ICU select-syntaks for kontekstavhengige oversettelser som kjønn, brukerroller eller statusverdier. Select-uttrykket velger riktig variant basert på den oppgitte verdien.

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

Automatiser oversettelseskvalitet

Fang opp manglende nøkler og ødelagte plassholdere før de sendes ut med i18n-validate. Test brukergrensesnittet med pseudo-oversettelser ved hjelp av i18n-pseudo før de virkelige oversettelsene er klare.

Vanlige fallgruver

Overdreven avhengighet av defaultMessage

defaultMessage er en utviklingsreserveløsning, ikke en oversettelsesstrategi. Hvis du bruker defaultMessage for alle strenger, vil resultatet av meldingsuttrekket inneholde den engelske teksten, men oversettere kan gå glipp av nye nøkler. Trekk alltid ut og vedlikehold en fullstendig kildespråkfil.

Nøstede objekter i stedet for flate nøkler

IntlProvider forventer en flat Record&lt;string, string&gt; for meldinger. Hvis du sender nøstet JSON som { nav: { home: "Home" } }, finner ikke react-intl nøkkelen "nav.home". Flat ut meldingene dine før du sender dem, eller bruk et bibliotek som flat.

IntlProvider forårsaker gjengivelser på nytt

Hvis du oppretter meldingsobjektet inline inne i gjengivelsesfunksjonen, mottar IntlProvider en ny objektreferanse ved hver gjengivelse, noe som fører til at alle forbrukere gjengis på nytt. Memoiser meldinger med useMemo eller definer dem utenfor komponenten.

Manglende IntlProvider i tester

Komponenter som bruker FormattedMessage eller useIntl vil kaste feil hvis de gjengis uten en IntlProvider-forelder. I tester pakker du inn komponenten din i IntlProvider med locale="en" og et tomt eller minimalt meldingsobjekt.

Anbefalt filstruktur

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

Prøv i18n Agent nå

Slipp oversettelsesfilen din her

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

eller klikk for å bla gjennom

Målspråk

Ingen registrering krevesUmiddelbart estimat

Språkfallback med react-intl-locale-chain

Når en oversettelsesnøkkel mangler i et regionalt språk som pt-BR, hopper react-intl rett til standardspråket i stedet for å sjekke foreldrespråket pt først.

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>

Se guiden vår for språkfallback for den fullstendige listen over støttede rammeverk og 75 innebygde kjeder. Learn more →

Ofte stilte spørsmål