
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
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.
npm install react-intlConfigurar 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.
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>
);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
{
"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"
}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.
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.
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.
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>,
}}
/>
);
}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.
# 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.jsonPlurales 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 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}個の商品があります"
}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.
// 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
Errores habituales
Depender demasiado de defaultMessage
Objetos anidados en vez de claves planas
IntlProvider provoca renderizados repetidos
Falta IntlProvider en las pruebas
Estructura de archivos recomendada
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.jsonTambién puede traducir:
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
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.
npm install react-intl-locale-chain<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 →