Skip to main content

Guía de react-intl: configuración de internacionalización en React

Configure react-intl de FormatJS en su aplicación React con IntlProvider, FormattedMessage, useIntl, el formato de mensajes ICU y traducciones automatizadas.

¿Utiliza react-i18next? Consulte nuestra guía de react-i18next

1

Instalar react-intl

react-intl forma parte del proyecto FormatJS. Proporciona componentes y hooks de React para dar formato a cadenas, números, fechas y plurales mediante el estándar ICU MessageFormat.

react-intl no tiene dependencias de ejecución aparte de React. Utiliza la API Intl integrada en el navegador para dar formato a números y fechas e incluye su propio analizador ICU MessageFormat para plurales, select y texto enriquecido.
Terminal
npm install react-intl
2

Configurar IntlProvider

Envuelva la aplicación con IntlProvider en la raíz. Pase la configuración regional activa y un objeto plano de mensajes. Después, todos los componentes inferiores podrán acceder a las traducciones mediante 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 requiere un objeto plano de mensajes con pares de clave y valor —por ejemplo, { "app.greeting": "Hello" }—. Debe aplanar el JSON anidado antes de pasarlo a IntlProvider o utilizar una utilidad como flat para convertirlo.

Archivos de mensajes

Cree un archivo JSON por configuración regional. react-intl utiliza de forma nativa la sintaxis ICU MessageFormat: plurales, select y variables se expresan en línea dentro de las cadenas.

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"
}
Utilice identificadores separados por puntos como «nav.home» para organizar. A diferencia de react-i18next, react-intl espera un objeto plano de mensajes: aplana las claves, no la estructura.
3

Utilizar traducciones en los componentes

react-intl ofrece dos API principales: el componente FormattedMessage para renderizar JSX traducido y el hook useIntl para acceso imperativo —marcadores de entrada, etiquetas aria y formato programático—.

Componente FormattedMessage

Utilice FormattedMessage para traducciones declarativas en JSX. Pase el identificador del mensaje y los valores de interpolación. Renderiza directamente la cadena traducida.

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

Utilice useIntl() cuando necesite la cadena traducida como valor plano: para marcadores de entrada, aria-labels, document.title o al pasar cadenas a API ajenas a React. También proporciona formatNumber, formatDate y 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>
  );
}

Texto enriquecido (HTML en las traducciones)

Inserte JSX en las traducciones mediante etiquetas similares a XML dentro de los mensajes. Pase los gestores mediante la prop values para renderizar enlaces, negrita o cualquier componente React dentro de un mensaje traducido.

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 renderiza de forma predeterminada un React Fragment. Si necesita un elemento envolvente concreto, pase la prop textComponent a IntlProvider o envuelva FormattedMessage en su propio elemento.

Extracción de mensajes con @formatjs/cli

FormatJS ofrece una CLI que extrae automáticamente identificadores de mensajes del código fuente a un archivo JSON. Así mantiene sincronizado el archivo de mensajes con los componentes sin llevar un registro 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

Plurales y select de ICU

react-intl utiliza ICU MessageFormat de forma nativa. Los plurales, select según el género y formatos anidados se expresan directamente en las cadenas, sin convenciones de sufijos ni claves independientes.

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}個の商品があります"
}
Nunca codifique directamente la lógica de plurales en JavaScript. El árabe tiene 6 formas, el francés considera singular el 0 y el japonés no distingue plurales. Deje que ICU MessageFormat gestione las reglas; solo tiene que pasar el valor count.

Select de ICU para géneros y roles

Utilice la sintaxis select de ICU para traducciones dependientes del contexto, como el género, los roles de usuario o los estados. La expresión elige la variante correcta a partir del valor proporcionado.

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

Automatizar la calidad de la traducción

Detecte las claves ausentes y los marcadores rotos antes de publicar con i18n-validate. Pruebe la interfaz con pseudotraducciones mediante i18n-pseudo antes de recibir las reales.

Errores habituales

Depender demasiado de defaultMessage

defaultMessage es un respaldo para desarrollo, no una estrategia de traducción. Si lo utiliza para todas las cadenas, la salida de extracción contendrá el texto inglés, pero los traductores pueden pasar por alto claves nuevas. Extraiga y mantenga siempre un archivo regional de origen completo.

Objetos anidados en vez de claves planas

IntlProvider espera un Record&lt;string, string&gt; plano en messages. Si pasa un JSON anidado como { nav: { home: "Home" } }, react-intl no encontrará la clave «nav.home». Aplane los mensajes antes de pasarlos o utilice una biblioteca como flat.

IntlProvider provoca renderizados repetidos

Si crea el objeto messages en línea dentro de la función de renderizado, IntlProvider recibe una referencia nueva cada vez y todos los consumidores vuelven a renderizarse. Memorice messages con useMemo o defínalo fuera del componente.

Falta IntlProvider en las pruebas

Los componentes que utilizan FormattedMessage o useIntl lanzan un error si se renderizan sin un antecesor IntlProvider. En las pruebas, envuelva su componente en IntlProvider con locale="en" y un objeto messages vacío o mínimo.

Estructura de archivos recomendada

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

Pruebe i18n Agent ahora

Arrastre y suelte aquí su archivo de traducción

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

o haga clic para seleccionar

Idiomas de destino

No es necesario registrarsePresupuesto al instante

Respaldo de configuraciones regionales con react-intl-locale-chain

Cuando falta una clave en una configuración regional como pt-BR, react-intl pasa directamente a la predeterminada en vez de comprobar primero la principal 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>

Consulte nuestra guía de respaldo de configuraciones regionales para ver todos los frameworks admitidos y las 75 cadenas integradas. Learn more →

Preguntas frecuentes