Skip to main content

Guia de react-intl: configuració de la internacionalització de React

Configuri FormatJS react-intl a la seva aplicació React amb IntlProvider, FormattedMessage, useIntl, el format de missatges d’ICU i traduccions automatitzades.

Utilitza react-i18next? Consultar la nostra guia de react-i18next

1

Instal·lar react-intl

react-intl forma part del projecte FormatJS. Proporciona components i hooks de React per formatar cadenes, nombres, dates i plurals mitjançant l’estàndard ICU MessageFormat.

react-intl no té cap dependència en temps d’execució més enllà de React. Utilitza l’API Intl integrada al navegador per formatar nombres i dates i inclou el seu propi analitzador d’ICU MessageFormat per als plurals, select i el text enriquit.
Terminal
npm install react-intl
2

Configurar IntlProvider

Embolcalli l’aplicació amb IntlProvider a l’arrel. Passi-hi la configuració regional activa i un objecte pla de missatges. A continuació, tots els components descendents podran accedir a les traduccions mitjançant FormattedMessage o 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 requereix un objecte pla de missatges amb parells clau-valor (p. ex., { "app.greeting": "Hello" }). Cal aplanar el JSON imbricat abans de passar-lo a IntlProvider o utilitzar una utilitat com flat per convertir les estructures imbricades.

Fitxers de missatges

Creï un fitxer JSON per a cada configuració regional. react-intl utilitza de manera nativa la sintaxi ICU MessageFormat: els plurals, select i les variables s’expressen en línia dins de les cadenes de missatge.

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"
}
Utilitzi ID separats per punts, com ara "nav.home", per organitzar-los. A diferència de react-i18next, react-intl espera un objecte pla de missatges: cal aplanar les claus, no l’estructura.
3

Utilitzar traduccions als components

react-intl proporciona dues API principals: el component FormattedMessage per renderitzar JSX traduït i el hook useIntl per a l’accés imperatiu (marcadors de posició, atributs aria-label i formatació programàtica).

Component FormattedMessage

Utilitzi FormattedMessage per a traduccions declaratives en JSX. Passi-hi l’ID del missatge i els valors d’interpolació necessaris. El component renderitza directament la cadena traduïda.

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

Utilitzi useIntl() quan necessiti la cadena traduïda com a valor simple: per als marcadors de posició dels camps d’entrada, els atributs aria-label, document.title o per passar cadenes a API que no siguin de React. També proporciona 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>
  );
}

Text enriquit (HTML a les traduccions)

Incrusti JSX dins de les traduccions mitjançant etiquetes semblants a les d’XML a les cadenes de missatge. Passi els gestors d’etiquetes mitjançant la propietat values per renderitzar enllaços, text en negreta o qualsevol component React dins d’un missatge traduït.

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 renderitza un React Fragment de manera predeterminada. Si necessita un element contenidor concret, passi la propietat textComponent a IntlProvider o embolcalli FormattedMessage amb el seu propi element.

Extracció de missatges amb @formatjs/cli

FormatJS proporciona una CLI per extreure automàticament els ID de missatge del codi font i desar-los en un fitxer JSON. Això garanteix que el fitxer de missatges es mantingui sincronitzat amb els components sense haver-ne de fer un seguiment manual.

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

Plurals i select d’ICU

react-intl utilitza ICU MessageFormat de manera nativa. Els plurals, select segons el gènere i la formatació imbricada s’expressen directament dins de les cadenes de missatge, sense convencions de sufixos ni claus separades.

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}個の商品があります"
}
No codifiqui mai la lògica dels plurals directament en JavaScript. Llengües com l’àrab tenen 6 formes plurals, el francès tracta el 0 com a singular i el japonès no distingeix el plural. Deixi que ICU MessageFormat gestioni les regles i limiti’s a passar-hi el valor del recompte.

select d’ICU per a gèneres i rols

Utilitzi la sintaxi select d’ICU per a traduccions que depenen del context, com ara el gènere, els rols d’usuari o els valors d’estat. L’expressió select tria la variant correcta segons el valor proporcionat.

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

Automatitzar la qualitat de les traduccions

Detecti amb i18n-validate les claus que falten i els marcadors de posició malmesos abans que arribin a producció. Provi la interfície amb pseudotraduccions mitjançant i18n-pseudo abans que arribin les traduccions reals.

Errors habituals

Dependència excessiva de defaultMessage

defaultMessage és un recurs de reserva per al desenvolupament, no una estratègia de traducció. Si utilitza defaultMessage per a totes les cadenes, la sortida de l’extracció de missatges contindrà el text en anglès, però els traductors podrien no detectar les claus noves. Extregui i mantingui sempre un fitxer complet de la configuració regional d’origen.

Objectes imbricats en lloc de claus planes

IntlProvider espera un Record&lt;string, string&gt; pla per als missatges. Si hi passa JSON imbricat, com ara { nav: { home: "Home" } }, react-intl no trobarà la clau "nav.home". Aplani els missatges abans de passar-los-hi o utilitzi una biblioteca com flat.

IntlProvider provoca renderitzacions repetides

Si crea l’objecte messages en línia dins de la funció de renderització, IntlProvider rep una referència d’objecte nova a cada renderització, fet que provoca que tots els consumidors es tornin a renderitzar. Faci servir useMemo per memoritzar els missatges o defineixi’ls fora del component.

Falta IntlProvider a les proves

Els components que utilitzen FormattedMessage o useIntl generaran una excepció si es renderitzen sense un IntlProvider en un nivell superior. A les proves, embolcalli el component amb IntlProvider, locale="en" i un objecte messages buit o mínim.

Estructura de fitxers recomanada

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

Provar i18n Agent ara

Arrossegar aquí el fitxer de traducció

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

o fer clic per explorar

Idiomes de destinació

No cal registrePressupost instantani

Configuració regional de reserva amb react-intl-locale-chain

Quan falta una clau de traducció en una configuració regional com pt-BR, react-intl passa directament a la configuració regional predeterminada en lloc de comprovar primer la configuració regional pare 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>

Consulti la nostra guia de configuracions regionals de reserva per veure la llista completa d’entorns de treball compatibles i les 75 cadenes integrades. Learn more →

Preguntes freqüents