Overview
Welcome to React Intl's docs! This is the place to find React Intl's docs. Feel free to open a pull request and contribute to the docs to make them better.
Runtime Requirements
We support IE11 & 2 most recent versions of Edge, Chrome, Firefox & Safari.
React Intl relies on these Intl
APIs:
- Intl.NumberFormat: Available on IE11+
- Intl.DateTimeFormat: Available on IE11+
- Intl.PluralRules: This can be polyfilled using this package.
- Intl.RelativeTimeFormat: This can be polyfilled using this package.
- (Optional) Intl.DisplayNames: Required if you use
formatDisplayName
orFormattedDisplayName
. This can be polyfilled using this package.
If you need to support older browsers, we recommend you do the following:
-
If you're supporting browsers that do not have
Intl
, include this polyfill in your build. -
Polyfill
Intl.NumberFormat
with@formatjs/intl-numberformat
. -
Polyfill
Intl.DateTimeFormat
with@formatjs/intl-datetimeformat
-
If you're supporting browsers that do not have
Intl.PluralRules
(e.g IE11 & Safari 12-), include this polyfill in your build. -
If you're supporting browsers that do not have Intl.RelativeTimeFormat (e.g IE11, Edge, Safari 12-), include this polyfill in your build along with individual CLDR data for each locale you support.
-
If you need
Intl.DisplayNames
, include this polyfill in your build along with individual CLDR data for each locale you support.
Node.js
full-icu
Starting with Node.js 13.0.0 full-icu is supported by default.
If using React Intl in an earlier version of Node.js, your node
binary has to either:
- Get compiled with
full-icu
using these instructions
OR
- Uses
full-icu
npm package
If your node
version is missing any of the Intl
APIs above, you'd have to polyfill them accordingly.
React Native
If you're using react-intl
in React Native, make sure your runtime has built-in Intl
support (similar to JSC International variant). See these issues for more details:
React Native on iOS
If you cannot use the Intl variant of JSC (e.g on iOS), follow the instructions in Runtime Requirements to polyfill those APIs accordingly.
The react-intl
Package
Install the react-intl
npm package via npm:
- npm
- yarn
npm i -S react-intl
yarn add react-intl
The react-intl
npm package distributes the following modules (links from unpkg):
- CommonJS:
unbundled dependencies,
"main"
inpackage.json
, warnings in dev. - ES6:
unbundled dependencies,
"module"
inpackage.json
, warnings in dev.
Module Bundlers
We've made React Intl work well with module bundlers like: Browserify, Webpack, or Rollup which can be used to bundle React Intl for the browser:
-
The
"browser"
field inpackage.json
is specified so that only basic English locale data is included when bundling. This way when using the"main"
module in Node all locale data is loaded, but ignored when bundled for the browser. -
An ES6 version of React Intl is provided as
"jsnext:main"
and"module"
inpackage.json
and can be used with Rollup. -
Development-time warnings are wrapped with
process.env.NODE_ENV !== 'production'
, this allows you to specifyNODE_ENV
when bundling and minifying to have these code blocks removed.
The React Intl Module
Whether you use the ES6, CommonJS, or UMD version of React Intl, they all provide the same named exports:
injectIntl
defineMessages
IntlProvider
FormattedDate
FormattedTime
FormattedRelativeTime
FormattedNumber
FormattedPlural
FormattedMessage
When using the UMD version of React Intl without a module system, it will expect react
to exist on the global variable: React
, and put the above named exports on the global variable: ReactIntl
.
Creating an I18n Context
Now with React Intl and its locale data loaded an i18n context can be created for your React app.
React Intl uses the provider pattern to scope an i18n context to a tree of components. This allows configuration like the current locale and set of translated strings/messages to be provided at the root of a component tree and made available to the <Formatted*>
components. This is the same concept as what Flux frameworks like Redux use to provide access to a store within a component tree.
All apps using React Intl must use the <IntlProvider>
component.
The most common usage is to wrap your root React component with <IntlProvider>
and configure it with the user's current locale and the corresponding translated strings/messages:
ReactDOM.render(
<IntlProvider locale={usersLocale} messages={translationsForUsersLocale}>
<App />
</IntlProvider>,
document.getElementById('container')
)
See: The <IntlProvider>
docs for more details.
Formatting Data
React Intl has two ways to format data, through React components and its API. The components provide an idiomatic-React way of integrating internationalization into a React app, and the <Formatted*>
components have benefits over always using the imperative API directly. The API should be used when your React component needs to format data to a string value where a React element is not suitable; e.g., a title
or aria
attribute, or for side-effect in componentDidMount
.
React Intl's imperative API is accessed via injectIntl
, a High-Order Component (HOC) factory. It will wrap the passed-in React component with another React component which provides the imperative formatting API into the wrapped component via its props
. (This is similar to the connect-to-stores pattern found in many Flux implementations.)
Here's an example using <IntlProvider>
, <Formatted*>
components, and the imperative API to setup an i18n context and format data:
import React from 'react';
import ReactDOM from 'react-dom';
import {IntlProvider, FormattedRelative, useIntl} from 'react-intl';
const MS_IN_DAY = 1e3 * 3600 * 24
const PostDate = ({date}) => {
const intl = useIntl()
return (
<span title={intl.formatDate(date)}>
<FormattedRelativeTime value={(Date.now() - date)/MS_IN_DAY} unit="day"/>
</span>
)
});
const App = ({post}) => (
<div>
<h1>{post.title}</h1>
<p>
<PostDate date={post.date} />
</p>
<div>{post.body}</div>
</div>
);
ReactDOM.render(
<IntlProvider locale={navigator.language}>
<App
post={{
title: 'Hello, World!',
date: new Date(1459913574887),
body: 'Amazing content.',
}}
/>
</IntlProvider>,
document.getElementById('container')
);
Assuming navigator.language
is "en-us"
:
<div>
<h1>Hello, World!</h1>
<p><span title="4/5/2016">yesterday</span></p>
<div>Amazing content.</div>
</div>
See: The API docs and Component docs for more details.
ESM Build
react-intl
and its underlying libraries (@formatjs/icu-messageformat-parser
, intl-messageformat
, @formatjs/intl-relativetimeformat
) export ESM artifacts. This means you should configure your build toolchain to transpile those libraries.
Jest
Add transformIgnorePatterns
to always include those libraries, e.g:
{
transformIgnorePatterns: [
'/node_modules/(?!intl-messageformat|@formatjs/icu-messageformat-parser).+\\.js$',
],
}
webpack
If you're using babel-loader
, or ts-loader
, you can do 1 of the following:
- Add those libraries in
include
:
{
include: [
path.join(__dirname, 'node_modules/react-intl'),
path.join(__dirname, 'node_modules/intl-messageformat'),
path.join(__dirname, 'node_modules/@formatjs/icu-messageformat-parser'),
]
}
OR
- Add those libraries in
exclude
:
exclude: /node_modules\/(?!react-intl|intl-messageformat|@formatjs\/icu-messageformat-parser)/,
Core Concepts
- Formatters (Date, Number, Message, Relative)
- Provider and Injector
- API and Components
- Message Descriptor
- Message Syntax
- Defining default messages for extraction
- Custom, named formats
Example Apps
There are several runnable example apps in this Git repo. These are a great way to see React Intl's core concepts in action in simplified applications.
API Reference
There are a few API layers that React Intl provides and is built on. When using React Intl you'll be interacting with Intl
built-ins, React Intl's API, and its React components:
TypeScript Usage
react-intl
is written in TypeScript, thus having 1st-class TS support.
In order to use react-intl
in TypeScript, make sure your compilerOptions
's lib
config include ["esnext.intl", "es2017.intl", "es2018.intl"]
.
Typing message IDs and locale
By default, the type for the id
prop of <FormattedMessage>
and formatMessage
is string
. However, you can set a more restrictive type to get autocomplete and error checking. In order to do this, override the following global namespace with the union type of all of your message IDs. You can do this by including the following somewhere in your code:
declare global {
namespace FormatjsIntl {
interface Message {
ids: keyof typeof messages
}
}
}
Where messages
is the object you would normally pass to <IntlProvider>
, and would look something like:
const messages = {
greeting: 'Hello',
planet: 'World',
// ...
}
You can also override the following global to use a custom type for locale
declare global {
namespace FormatjsIntl {
interface IntlConfig {
locale: 'en' | 'fr'
}
}
}
Advanced Usage
Our Advanced Usage has further guides for production setup in environments where performance is important.
Supported Tooling
Message extraction
We've built @formatjs/cli that helps you extract messages from a list of files. It uses babel-plugin-formatjs under the hood and should be able to extract messages if you're declaring using 1 of the mechanisms below:
import {defineMessages} from 'react-intl'
defineMessages({
foo: {
id: 'foo',
defaultMessage: 'foo',
description: 'bar',
},
})
import {FormattedMessage} from 'react-intl'
;<FormattedMessage id="foo" defaultMessage="foo" description="bar" />
function Comp(props) {
const {intl} = props
return intl.formatMessage({
// The whole `intl.formatMessage` is required so we can extract
id: 'foo',
defaultMessage: 'foo',
description: 'bar',
})
}
ESLint Plugin
We've also built eslint-plugin-formatjs that helps enforcing specific rules on your messages if your translation vendor has restrictions.