React-Intl - Documentation

What is React Intl?

React Intl is a JavaScript library built on top of the Intl object provided by modern browsers and Node.js. It provides a simple, powerful, and efficient way to internationalize (i18n) and localize (l10n) React applications. This means it helps you build applications that can be easily adapted to different languages and cultural conventions, displaying dates, numbers, currencies, and text appropriately for each locale. Instead of manually managing translations and formatting, React Intl handles the complexities, leaving you to focus on building your application’s core features.

Why use React Intl?

Using React Intl offers several key advantages:

Setting up React Intl

Setting up React Intl in your project is straightforward. First, install the necessary package:

npm install react-intl

or

yarn add react-intl

Next, import and use the necessary components within your React application. The most common component is <IntlProvider>, which provides locale and messages to your application. Example:

import { IntlProvider, FormattedMessage } from 'react-intl';
import messages from './messages'; // Your translation messages

function MyComponent() {
  return (
    <IntlProvider locale="en" messages={messages.en}>
      <FormattedMessage id="greeting" /> {/* Example usage */}
    </IntlProvider>
  );
}

This example requires a messages.en object containing your English translations (you’d typically have similar objects for other locales, e.g., messages.es for Spanish). The <FormattedMessage> component looks up and renders the translation for the specified id.

Remember to handle locale detection and switching (often based on user browser settings or explicit selection) to manage different languages effectively.

Core Concepts

React Intl revolves around several core concepts:

Understanding these core concepts is crucial for effectively using React Intl to create robust and internationally-ready applications.

Formatting Messages

Using FormattedMessage

The FormattedMessage component is the cornerstone of translating text within your React application using React Intl. It allows you to display localized messages based on the locale provided by the <IntlProvider>. You identify messages using a unique id, which maps to a key within your message catalog (e.g., a JSON object).

Basic Usage:

import { FormattedMessage } from 'react-intl';

// Assuming messages.en = {greeting: "Hello!"}
<FormattedMessage id="greeting" /> 

This will render “Hello!” if the locale is “en”.

Adding placeholders (interpolation):

You can use placeholders within your message strings to dynamically insert values. These are indicated by {placeholder} within the message string. You provide the values using the values prop:

<FormattedMessage
  id="welcomeMessage"
  values={{ name: 'John' }}
/>

With the message definition (in messages.en for example):

"welcomeMessage": "Welcome, {name}!"

This will render “Welcome, John!”

Handling HTML:

For more complex scenarios, use the defaultMessage prop to handle messages that might not be present in all locales or for debugging. You can also embed HTML using dangerouslySetInnerHTML, but remember to sanitize any user-provided data. Directly embedding HTML within the id message is generally discouraged for security reasons.

Working with Plural Rules

React Intl handles pluralization automatically, ensuring correct grammatical agreement with numbers. Use plural forms within your message strings, delineated using special syntax within your message catalog. The specific syntax varies depending on your chosen pluralization library (often CLDR).

Example (using a common syntax):

"apples": "{count, plural, =0 {No apples} one {One apple} other {# apples}}"

This message will render differently depending on the value of {count}:

Handling Gender and Selectors

Similar to pluralization, React Intl supports gendered messages. These use a selector within the message string to choose the correct form based on a provided gender value. The syntax varies depending on the locale and message format.

Example (a common, but locale-dependent, syntax):

"greeting": "{gender, select, male {Hello, sir!} female {Hello, madam!} other {Hello!}}"

Using Number Formatting

The <FormattedNumber> component provides robust number formatting, adhering to locale-specific conventions for decimal separators, thousands separators, and currency symbols.

import { FormattedNumber } from 'react-intl';

<FormattedNumber value={1234.56} style="currency" currency="USD" />

Using Date and Time Formatting

The <FormattedDate> and <FormattedTime> components format dates and times according to locale conventions. You can specify the desired format using the value (date object) and dateStyle or timeStyle props (e.g., ‘short’, ‘medium’, ‘long’, ‘full’).

import { FormattedDate, FormattedTime } from 'react-intl';

<FormattedDate value={new Date()} />
<FormattedTime value={new Date()} />

You can also customize the formatting even more precisely using the format prop with ICU MessageFormat patterns.

Custom Formatting Functions

For highly customized formatting needs beyond what’s offered by built-in components, you can create and use custom formatting functions. These functions will receive the locale and the value to format. You’d then integrate these custom functions within your React components, likely alongside FormattedMessage. This is useful for highly specific formatting requirements not directly supported by the default formatters.

Internationalization Components

FormattedDate

The FormattedDate component renders a date according to the current locale. It uses the browser’s built-in Intl.DateTimeFormat API for optimal performance and accuracy.

Props:

Example:

import { FormattedDate } from 'react-intl';

<FormattedDate value={new Date()} />  {/* Uses default 'medium' style */}
<FormattedDate value={new Date()} dateStyle="long" />
<FormattedDate value={new Date()} dateStyle="short" timeStyle="short" />
<FormattedDate value={new Date()} format="yyyy-MM-dd HH:mm:ss" />

FormattedNumber

The FormattedNumber component formats numbers according to the current locale’s number formatting conventions, including decimal separators, grouping separators, and currency symbols.

Props:

Example:

import { FormattedNumber } from 'react-intl';

<FormattedNumber value={1234.56} />        {/* Decimal style */}
<FormattedNumber value={1234.56} style="currency" currency="USD" /> {/* USD currency style */}
<FormattedNumber value={0.75} style="percent" />   {/* Percent style */}

FormattedTime

Similar to FormattedDate, FormattedTime formats time values according to the current locale.

Props:

Example:

import { FormattedTime } from 'react-intl';

<FormattedTime value={new Date()} />      {/* Uses default 'medium' style */}
<FormattedTime value={new Date()} timeStyle="short" />
<FormattedTime value={new Date()} format="HH:mm:ss" />

FormattedRelative

FormattedRelative displays a relative time representation (e.g., “a few seconds ago”, “2 hours ago”). It’s ideal for displaying timestamps in a user-friendly manner.

Props:

Example:

import { FormattedRelative } from 'react-intl';

<FormattedRelative value={new Date(Date.now() - 3600000)} /> {/* One hour ago */}

FormattedPlural

FormattedPlural is used for displaying messages that vary depending on the quantity of items, handling plural forms correctly for the current locale.

Props:

Example (Illustrative, Actual plural rules depend on locale):

import { FormattedPlural } from 'react-intl';

<FormattedPlural value={2} one="One item" other="{value} items" />

FormattedList

FormattedList renders a list of items, applying locale-appropriate separators and conjunctions.

Props:

Example:

import { FormattedList } from 'react-intl';

<FormattedList values={['apple', 'banana', 'orange']} />

Note: The exact behavior and available options for these components might be subject to minor changes across different versions of React Intl. Always refer to the latest documentation for the most up-to-date information.

Working with Locale Data

Loading Locale Data

React Intl relies on locale data to perform accurate formatting and translation. This data typically includes translations for messages, as well as rules for number, date, and time formatting. You load this data in your application using different methods:

Defining Custom Locales

While React Intl supports a vast number of standard locales, you might need to define custom locales for less common languages or specific formatting requirements. This involves creating a custom locale object that conforms to the Intl API’s specifications. This is generally more complex and requires a deep understanding of locale data structures.

Locale Detection and Switching

Handling locale detection and switching is crucial for a good user experience. Common strategies include:

Using Different Number/Date/Time Systems

React Intl relies on the browser’s built-in Intl API, which respects the locale’s inherent number, date, and time formatting rules. This means if a locale uses different number systems (like Arabic numerals versus Devanagari numerals) or different calendar systems (Gregorian vs. Islamic), React Intl will handle this automatically. You don’t need to explicitly configure this; it’s determined by the locale you provide. However, ensure your message catalogs and JSON files accurately reflect the conventions for the locale to avoid mismatches.

Advanced Usage

Using React Intl with Redux

Integrating React Intl with Redux involves managing the application’s locale and messages within the Redux store. This allows for centralized state management and easy sharing of locale information across different parts of the application.

  1. Store Locale: Create a slice of your Redux store to hold the current locale. Actions can be dispatched to change this locale.

  2. Provide <IntlProvider>: Wrap your main app component with the <IntlProvider>, passing the locale from the Redux store via a selector. You’ll likely use connect from react-redux to connect your component to the store.

  3. Dispatch Locale Changes: Dispatch actions to update the locale in the store whenever the user changes their preference.

Example (conceptual):

// Redux actions
export const setLocale = (locale) => ({ type: 'SET_LOCALE', locale });

// Redux reducer
const reducer = (state = { locale: 'en' }, action) => {
  switch (action.type) {
    case 'SET_LOCALE':
      return { ...state, locale: action.locale };
    default:
      return state;
  }
};

// Connected component
const MyComponent = connect(state => ({ locale: state.locale }))(MyComponent);

Internationalization of UI Components

When internationalizing UI components, consider these best practices:

Testing React Intl applications

Testing React Intl applications requires careful consideration of how to manage the locale context during testing.

Example using enzyme and a mocked IntlProvider:

import { shallow } from 'enzyme';
import { IntlProvider } from 'react-intl';
import MyComponent from './MyComponent';

it('renders correctly', () => {
  const wrapper = shallow(
    <IntlProvider locale="en">
      <MyComponent />
    </IntlProvider>
  );
  // assertions here
});

Performance Optimization

For optimal performance, consider:

Handling Complex Data Structures

For complex data structures needing translation, you need to design a mechanism for translating nested objects or arrays. Recursive functions or custom helper functions can traverse and translate deeply nested data. This often requires restructuring your data to use keys and IDs that map to your translation strings.

Extending React Intl with Custom Components

React Intl provides extensibility to create custom components for specific formatting needs. You can build custom components to handle complex formatting scenarios not directly addressed by the built-in components. This involves utilizing the Intl APIs and constructing your own components that integrate with the React Intl context. You might create components for specialized date formatting, custom number display, or even creating custom message formatters that handle complex data.

Contributing and Community

Contributing to the Project

Contributions to React Intl are welcome! Before contributing, please take the time to review the project’s contribution guidelines. These guidelines outline the process for submitting pull requests, writing tests, and adhering to the project’s coding style. Key aspects typically covered include:

Community Support and Resources

The React Intl community provides various avenues for support and collaboration:

Engaging with the community is highly encouraged to get assistance, share your knowledge, and contribute to the ongoing development and improvement of React Intl. Check the project’s repository for links to community resources and communication channels.