|
| 1 | +--- |
| 2 | +id: react-intl |
| 3 | +title: Overview |
| 4 | +--- |
| 5 | + |
| 6 | +[](https://www.npmjs.org/package/react-intl) |
| 7 | + |
| 8 | +**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. |
| 9 | + |
| 10 | +## Runtime Requirements |
| 11 | + |
| 12 | +**We support IE11 & 2 most recent versions of Edge, Chrome, Firefox & Safari.** |
| 13 | + |
| 14 | +React Intl relies on these `Intl` APIs: |
| 15 | + |
| 16 | +- [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat): Available on IE11+ |
| 17 | +- [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat): Available on IE11+ |
| 18 | +- [Intl.PluralRules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules): This can be polyfilled using [this package](polyfills/intl-pluralrules.md). |
| 19 | +- [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormat): This can be polyfilled using [this package](polyfills/intl-relativetimeformat.md). |
| 20 | +- (Optional) [Intl.DisplayNames](https://tc39.es/proposal-intl-displaynames/): Required if you use [`formatDisplayName`](react-intl/api.md#formatdisplayname) |
| 21 | + or [`FormattedDisplayName`](react-intl/components.md#formatteddisplayname). This can be polyfilled using [this package](polyfills/intl-displaynames.md). |
| 22 | + |
| 23 | +If you need to support older browsers, we recommend you do the following: |
| 24 | + |
| 25 | +1. Polyfill `Intl.NumberFormat` with [`@formatjs/intl-numberformat`](polyfills/intl-numberformat.md). |
| 26 | +2. Polyfill `Intl.DateTimeFormat` with [`@formatjs/intl-datetimeformat`](polyfills/intl-datetimeformat.md) |
| 27 | +3. If you're supporting browsers that do not have [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules) (e.g IE11 & Safari 12-), include this [polyfill](polyfills/intl-pluralrules.md) in your build. |
| 28 | + |
| 29 | +4. If you're supporting browsers that do not have [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormat) (e.g IE11, Edge, Safari 12-), include this [polyfill](polyfills/intl-relativetimeformat.md) in your build along with individual CLDR data for each locale you support. |
| 30 | + |
| 31 | +5. If you need `Intl.DisplayNames`, include this [polyfill](polyfills/intl-displaynames.md) in your build along with individual CLDR data for each locale you support. |
| 32 | + |
| 33 | +### Browser |
| 34 | + |
| 35 | +We officially support IE11 along with 2 most recent versions of Edge, Chrome & Firefox. |
| 36 | + |
| 37 | +### Node.js |
| 38 | + |
| 39 | +#### full-icu |
| 40 | + |
| 41 | +Starting with Node.js 13.0.0 full-icu is supported by default. |
| 42 | + |
| 43 | +If using React Intl in an earlier version of Node.js, your `node` binary has to either: |
| 44 | + |
| 45 | +- Get compiled with `full-icu` using these [instructions](https://nodejs.org/api/intl.html) |
| 46 | + |
| 47 | +**OR** |
| 48 | + |
| 49 | +- Uses [`full-icu` npm package](https://www.npmjs.com/package/full-icu) |
| 50 | + |
| 51 | +If your `node` version is missing any of the `Intl` APIs above, you'd have to polyfill them accordingly. |
| 52 | + |
| 53 | +### React Native |
| 54 | + |
| 55 | +If you're using `react-intl` in React Native, make sure your runtime has built-in `Intl` support (similar to [JSC International variant](https://github.com/react-native-community/jsc-android-buildscripts#international-variant)). See these issues for more details: |
| 56 | + |
| 57 | +- https://github.com/formatjs/formatjs/issues/1356 |
| 58 | +- https://github.com/formatjs/formatjs/issues/992 |
| 59 | + |
| 60 | +#### React Native on iOS |
| 61 | + |
| 62 | +If you cannot use the Intl variant of JSC (e.g on iOS), follow the instructions in [Runtime Requirements](#runtime-requirements) to polyfill those APIs accordingly. |
| 63 | + |
| 64 | +## Experimental Intl Features |
| 65 | + |
| 66 | +FormatJS also provides types & polyfill for the following Intl API proposals: |
| 67 | + |
| 68 | +- NumberFormat: [polyfill](polyfills/intl-numberformat.md) & [spec](https://tc39.es/ecma402/) |
| 69 | +- DisplayNames: [polyfill](polyfills/intl-displaynames.md) & [spec](https://tc39.es/proposal-intl-displaynames/) |
| 70 | + |
| 71 | +## The `react-intl` Package |
| 72 | + |
| 73 | +Install the [`react-intl` npm package](https://www.npmjs.com/package/react-intl) via npm: |
| 74 | + |
| 75 | +```bash |
| 76 | +$ npm install react-intl --save |
| 77 | +``` |
| 78 | + |
| 79 | +The `react-intl` npm package distributes the following modules (links from [unpkg](https://unpkg.com/)): |
| 80 | + |
| 81 | +- [**CommonJS**](https://unpkg.com/react-intl@latest/dist/index.js): |
| 82 | + unbundled dependencies, `"main"` in `package.json`, warnings in dev. |
| 83 | +- [**ES6**](https://unpkg.com/react-intl@latest/lib/index.js): |
| 84 | + unbundled dependencies, `"module"` in `package.json`, warnings in dev. |
| 85 | +- [**UMD dev**](https://unpkg.com/react-intl@latest/dist/react-intl.js): |
| 86 | + bundled dependencies (except `react`), browser or Node, warnings. |
| 87 | +- [**UMD prod**](https://unpkg.com/react-intl@latest/dist/react-intl.min.js): |
| 88 | + minified, bundled dependencies (except `react`), browser or Node, no warnings. |
| 89 | + |
| 90 | +### Module Bundlers |
| 91 | + |
| 92 | +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: |
| 93 | + |
| 94 | +- The `"browser"` field in `package.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. |
| 95 | + |
| 96 | +- An ES6 version of React Intl is provided as `"jsnext:main"` and `"module"` in `package.json` and can be used with Rollup. |
| 97 | + |
| 98 | +- Development-time warnings are wrapped with `process.env.NODE_ENV !== 'production'`, this allows you to specify `NODE_ENV` when bundling and minifying to have these code blocks removed. |
| 99 | + |
| 100 | +## The React Intl Module |
| 101 | + |
| 102 | +Whether you use the ES6, CommonJS, or UMD version of React Intl, they all provide the same named exports: |
| 103 | + |
| 104 | +- [`injectIntl`](react-intl/api.md#injectintl) |
| 105 | +- [`defineMessages`](react-intl/api.md#definemessages) |
| 106 | +- [`IntlProvider`](react-intl/components.md#intlprovider) |
| 107 | +- [`FormattedDate`](react-intl/components.md#formatteddate) |
| 108 | +- [`FormattedTime`](react-intl/components.md#formattedtime) |
| 109 | +- [`FormattedRelativeTime`](react-intl/components.md#formattedrelativetime) |
| 110 | +- [`FormattedNumber`](react-intl/components.md#formattednumber) |
| 111 | +- [`FormattedPlural`](react-intl/components.md#formattedplural) |
| 112 | +- [`FormattedMessage`](react-intl/components.md#formattedmessage) |
| 113 | + |
| 114 | +:::danger react |
| 115 | +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`**. |
| 116 | +::: |
| 117 | + |
| 118 | +## Creating an I18n Context |
| 119 | + |
| 120 | +Now with React Intl and its locale data loaded an i18n context can be created for your React app. |
| 121 | + |
| 122 | +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](http://redux.js.org/) use to provide access to a store within a component tree. |
| 123 | + |
| 124 | +**All apps using React Intl must use the [`<IntlProvider>` component](react-intl/components.md#intlprovider).** |
| 125 | + |
| 126 | +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: |
| 127 | + |
| 128 | +```tsx |
| 129 | +ReactDOM.render( |
| 130 | + <IntlProvider locale={usersLocale} messages={translationsForUsersLocale}> |
| 131 | + <App /> |
| 132 | + </IntlProvider>, |
| 133 | + document.getElementById('container') |
| 134 | +) |
| 135 | +``` |
| 136 | + |
| 137 | +**See:** The [**`<IntlProvider>` docs**](react-intl/components.md#intlprovider) for more details. |
| 138 | + |
| 139 | +## Formatting Data |
| 140 | + |
| 141 | +React Intl has two ways to format data, through [React components](react-intl/components.md) and its [API](react-intl/api.md). The components provide an idiomatic-React way of integrating internationalization into a React app, and the `<Formatted*>` components have [benefits](react-intl/components.md#why-components) 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`. |
| 142 | + |
| 143 | +React Intl's imperative API is accessed via [**`injectIntl`**](react-intl/api.md#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.) |
| 144 | + |
| 145 | +Here's an example using `<IntlProvider>`, `<Formatted*>` components, and the imperative API to setup an i18n context and format data: |
| 146 | + |
| 147 | +```tsx |
| 148 | +import React from 'react'; |
| 149 | +import ReactDOM from 'react-dom'; |
| 150 | +import {injectIntl, IntlProvider, FormattedRelative, useIntl} from 'react-intl'; |
| 151 | + |
| 152 | +const MS_IN_DAY = 1e3 * 3600 * 24 |
| 153 | + |
| 154 | +const PostDate = ({date}) => { |
| 155 | + const intl = useIntl() |
| 156 | + return ( |
| 157 | + <span title={intl.formatDate(date)}> |
| 158 | + <FormattedRelativeTime value={(Date.now() - date)/MS_IN_DAY} unit="day"/> |
| 159 | + </span> |
| 160 | + ) |
| 161 | +}); |
| 162 | + |
| 163 | +const App = ({post}) => ( |
| 164 | + <div> |
| 165 | + <h1>{post.title}</h1> |
| 166 | + <p> |
| 167 | + <PostDate date={post.date} /> |
| 168 | + </p> |
| 169 | + <div>{post.body}</div> |
| 170 | + </div> |
| 171 | +); |
| 172 | + |
| 173 | +ReactDOM.render( |
| 174 | + <IntlProvider locale={navigator.language}> |
| 175 | + <App |
| 176 | + post={{ |
| 177 | + title: 'Hello, World!', |
| 178 | + date: new Date(1459913574887), |
| 179 | + body: 'Amazing content.', |
| 180 | + }} |
| 181 | + /> |
| 182 | + </IntlProvider>, |
| 183 | + document.getElementById('container') |
| 184 | +); |
| 185 | +``` |
| 186 | + |
| 187 | +Assuming `navigator.language` is `"en-us"`: |
| 188 | + |
| 189 | +```html |
| 190 | +<div> |
| 191 | + <h1>Hello, World!</h1> |
| 192 | + <p><span title="4/5/2016">yesterday</span></p> |
| 193 | + <div> |
| 194 | + Amazing content. |
| 195 | + </div> |
| 196 | +</div> |
| 197 | +``` |
| 198 | + |
| 199 | +**See:** The [**API docs**][api] and [**Component docs**][components] for more details. |
| 200 | + |
| 201 | +# ESM Build |
| 202 | + |
| 203 | +`react-intl` and its underlying libraries (`intl-messageformat-parser`, `intl-messageformat`, `@formatjs/intl-relativetimeformat`, `intl-utils`) export ESM artifacts. This means you should configure your build toolchain to transpile those libraries. |
| 204 | + |
| 205 | +### Jest |
| 206 | + |
| 207 | +Add `transformIgnorePatterns` to always include those libraries, e.g: |
| 208 | + |
| 209 | +```tsx |
| 210 | +{ |
| 211 | + transformIgnorePatterns: [ |
| 212 | + '/node_modules/(?!intl-messageformat|intl-messageformat-parser).+\\.js$', |
| 213 | + ], |
| 214 | +} |
| 215 | +``` |
| 216 | + |
| 217 | +### webpack |
| 218 | + |
| 219 | +If you're using `babel-loader`, or `ts-loader`, you can do 1 of the following: |
| 220 | + |
| 221 | +1. Add those libraries in `include`: |
| 222 | + |
| 223 | +```ts |
| 224 | +{ |
| 225 | + include: [ |
| 226 | + path.join(__dirname, 'node_modules/react-intl'), |
| 227 | + path.join(__dirname, 'node_modules/intl-messageformat'), |
| 228 | + path.join(__dirname, 'node_modules/intl-messageformat-parser'), |
| 229 | + ] |
| 230 | +} |
| 231 | +``` |
| 232 | + |
| 233 | +OR |
| 234 | + |
| 235 | +2. Add those libraries in `exclude`: |
| 236 | + |
| 237 | +```tsx |
| 238 | +exclude: /node_modules\/(?!react-intl|intl-messageformat|intl-messageformat-parser)/, |
| 239 | +``` |
| 240 | + |
| 241 | +# Core Concepts |
| 242 | + |
| 243 | +- Formatters (Date, Number, Message, Relative) |
| 244 | +- Provider and Injector |
| 245 | +- API and Components |
| 246 | +- Message Descriptor |
| 247 | +- Message Syntax |
| 248 | +- Defining default messages for extraction |
| 249 | +- Custom, named formats |
| 250 | + |
| 251 | +# Example Apps |
| 252 | + |
| 253 | +There are several [**runnable example apps**](https://github.com/formatjs/formatjs/tree/master/packages/react-intl/examples) in this Git repo. These are a great way to see React Intl's [core concepts](#core-concepts) in action in simplified applications. |
| 254 | + |
| 255 | +# API Reference |
| 256 | + |
| 257 | +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: |
| 258 | + |
| 259 | +- [ECMAScript Internationalization API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) |
| 260 | +- [React Intl API](react-intl/api.md) |
| 261 | +- [React Intl Components](react-intl/components.md) |
| 262 | + |
| 263 | +# TypeScript Usage |
| 264 | + |
| 265 | +`react-intl` is written in TypeScript, thus having 1st-class TS support. |
| 266 | + |
| 267 | +In order to use `react-intl` in TypeScript, make sure your `compilerOptions`'s `lib` config include `["esnext.intl", "es2017.intl", "es2018.intl"]`. |
| 268 | + |
| 269 | +# Advanced Usage |
| 270 | + |
| 271 | +Our [Advanced Usage](guides/advanced-usage.md) has further guides for production setup in environments where performance is important. |
| 272 | + |
| 273 | +# Supported Tooling |
| 274 | + |
| 275 | +## Message extraction |
| 276 | + |
| 277 | +We've built [@formatjs/cli](tooling/cli.md) that helps you extract messages from a list of files. It uses [babel-plugin-react-intl](tooling/babel-plugin.md) under the hood and should be able to extract messages if you're declaring using 1 of the mechanisms below: |
| 278 | + |
| 279 | +```tsx |
| 280 | +import {defineMessages} from 'react-intl' |
| 281 | + |
| 282 | +defineMessages({ |
| 283 | + foo: { |
| 284 | + id: 'foo', |
| 285 | + defaultMessage: 'foo', |
| 286 | + description: 'bar', |
| 287 | + }, |
| 288 | +}) |
| 289 | +``` |
| 290 | + |
| 291 | +```tsx |
| 292 | +import {FormattedMessage} from 'react-intl' |
| 293 | +;<FormattedMessage id="foo" defaultMessage="foo" description="bar" /> |
| 294 | +``` |
| 295 | + |
| 296 | +```tsx |
| 297 | +function Comp(props) { |
| 298 | + const {intl} = props |
| 299 | + return intl.formatMessage({ |
| 300 | + // The whole `intl.formatMessage` is required so we can extract |
| 301 | + id: 'foo', |
| 302 | + defaultMessage: 'foo', |
| 303 | + description: 'bar', |
| 304 | + }) |
| 305 | +} |
| 306 | +``` |
| 307 | + |
| 308 | +## ESLint Plugin |
| 309 | + |
| 310 | +We've also built [eslint-plugin-formatjs](tooling/linter.md) that helps enforcing specific rules on your messages if your translation vendor has restrictions. |
0 commit comments