react-intl is a powerful JavaScript internationalization (i18n) library built specifically for React applications. It's part of FormatJS, a collection of JavaScript libraries for internationalization. Its primary goal is to make it easy to format strings, dates, numbers, and handle plurals in a way that respects different linguistic and cultural conventions across various locales.
Why use react-intl?
Developing applications for a global audience requires more than just translating text. react-intl addresses the complexities of i18n by providing features for:
1. Message Translation: Managing and displaying translated text strings.
2. Date and Time Formatting: Displaying dates and times according to the user's locale (e.g., DD/MM/YYYY vs. MM/DD/YYYY, 12-hour vs. 24-hour clock).
3. Number and Currency Formatting: Formatting numbers (e.g., decimal separators, thousands separators) and currencies (e.g., "$1,234.56" vs. "1.234,56 €").
4. Pluralization Rules: Handling different plural forms based on quantity and locale (e.g., "1 item" vs. "2 items" vs. "0 items", which can vary greatly across languages).
5. Relative Time Formatting: Displaying relative times like "2 minutes ago" or "tomorrow".
Core Concepts and Components:
* `IntlProvider`: This is a React Context Provider that needs to wrap your application (or parts of it) to make `react-intl`'s features available to child components. You provide it with the current `locale` (e.g., 'en', 'es', 'fr') and a collection of `messages` for that locale.
* Message Descriptors: Messages are typically defined as objects or JSON files where keys map to translated strings. These strings can include placeholders for dynamic values and complex ICU MessageFormat syntax for plurals, selects, etc.
* `<FormattedMessage />`: A React component used to render a translated string. It takes an `id` (the key from your messages) and an optional `values` prop for placeholders.
* `<FormattedDate />`, `<FormattedTime />`, `<FormattedNumber />`, `<FormattedRelativeTime />`: Components for rendering locale-aware dates, times, numbers, and relative times without manual string manipulation. They intelligently handle options like style (long, short, currency display, etc.).
* `useIntl()` hook: For functional components, this hook provides direct access to the `react-intl` API, including methods like `formatMessage`, `formatDate`, `formatNumber`, etc. This is useful for formatting values outside of JSX, for example, in event handlers or API calls.
* `defineMessages` utility: A helper function to define message descriptors. While optional, it helps prevent typos and ensures message IDs are consistent, especially when used with build tools for extracting messages.
`react-intl` builds upon the browser's built-in `Intl` API, ensuring performance and standard compliance while providing a React-friendly interface.
Example Code
import React, { useState, useEffect } from 'react';
import { IntlProvider, FormattedMessage, FormattedDate, FormattedNumber, useIntl, defineMessages } from 'react-intl';
// 1. Define message translations for different locales
const messages = {
en: defineMessages({
appTitle: 'React Intl Example',
greeting: 'Hello, {name}! Today is {today}.',
welcome: 'Welcome to our internationalized application!',
itemCount: 'You have {count, plural, one {# item} other {# items}}.',
productPrice: 'The product costs {price}.',
todayDate: 'Today is:',
developerName: 'Developer Name:',
currentLanguage: 'Current Language:',
selectLanguage: 'Select Language:',
}),
es: defineMessages({
appTitle: 'Ejemplo de React Intl',
greeting: '¡Hola, {name}! Hoy es {today}.',
welcome: '¡Bienvenido a nuestra aplicación internacionalizada!',
itemCount: 'Tienes {count, plural, one {# artículo} other {# artículos}}.',
productPrice: 'El producto cuesta {price}.',
todayDate: 'Hoy es:',
developerName: 'Nombre del desarrollador:',
currentLanguage: 'Idioma actual:',
selectLanguage: 'Seleccionar idioma:',
}),
fr: defineMessages({
appTitle: 'Exemple React Intl',
greeting: 'Bonjour, {name}! Aujourd\'hui, c\'est le {today}.',
welcome: 'Bienvenue dans notre application internationalisée !',
itemCount: 'Vous avez {count, plural, one {# article} other {# articles}}.',
productPrice: 'Le produit coûte {price}.',
todayDate: 'Aujourd\'hui c\'est:',
developerName: 'Nom du développeur:',
currentLanguage: 'Langue actuelle:',
selectLanguage: 'Sélectionner la langue:',
}),
};
// Helper function to load messages for a given locale
const loadMessages = (locale) => messages[locale] || messages.en;
// 2. A component demonstrating FormattedMessage, FormattedDate, FormattedNumber, and useIntl hook
function MyComponent({ userName, itemCount, productPrice }) {
const intl = useIntl(); // Access the intl object directly
// Example of using formatMessage from useIntl hook
const developer = intl.formatMessage({
id: 'developerName',
defaultMessage: 'Developer Name:', // Always good to provide a defaultMessage
}) + ' John Doe';
return (
<div style={{ padding: '20px', border: '1px solid #ccc', borderRadius: '8px', margin: '20px' }}>
<h2>
<FormattedMessage
id="welcome"
defaultMessage="Welcome to our internationalized application!"
/>
</h2>
<p>
<FormattedMessage
id="greeting"
defaultMessage="Hello, {name}! Today is {today}."
values={{
name: <strong>{userName}</strong>,
today: <FormattedDate value={new Date()} weekday="long" year="numeric" month="long" day="numeric" />,
}}
/>
</p>
<p>
<FormattedMessage
id="itemCount"
defaultMessage="You have {count, plural, one {# item} other {# items}}."
values={{ count: itemCount }}
/>
</p>
<p>
<FormattedMessage
id="productPrice"
defaultMessage="The product costs {price}."
values={{
price: <FormattedNumber
value={productPrice}
style="currency"
currency="USD"
/>,
}}
/>
</p>
<p>
<FormattedMessage id="todayDate" defaultMessage="Today is:" />{' '}
<FormattedDate
value={new Date()}
year="numeric"
month="long"
day="numeric"
hour="numeric"
minute="numeric"
/>
</p>
<p>{developer}</p>
<p>
<FormattedMessage id="currentLanguage" defaultMessage="Current Language:" />{' '}
<strong>{intl.locale}</strong>
</p>
</div>
);
}
// 3. The main App component where IntlProvider is used
function App() {
const [locale, setLocale] = useState('en');
const [currentMessages, setCurrentMessages] = useState(loadMessages(locale));
useEffect(() => {
setCurrentMessages(loadMessages(locale));
}, [locale]);
const handleLocaleChange = (e) => {
setLocale(e.target.value);
};
return (
<IntlProvider locale={locale} messages={currentMessages} defaultLocale="en">
<div style={{ fontFamily: 'Arial, sans-serif' }}>
<header style={{ background: '#f0f0f0', padding: '10px', textAlign: 'center' }}>
<h1>
<FormattedMessage
id="appTitle"
defaultMessage="React Intl Example"
/>
</h1>
<p>
<FormattedMessage id="selectLanguage" defaultMessage="Select Language:" />
<select value={locale} onChange={handleLocaleChange} style={{ marginLeft: '10px', padding: '5px' }}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
</p>
</header>
<MyComponent userName="Alice" itemCount={1} productPrice={1234.56} />
<MyComponent userName="Bob" itemCount={5} productPrice={987.65} />
<MyComponent userName="Charlie" itemCount={0} productPrice={50} />
</div>
</IntlProvider>
);
}
export default App;








react-intl