react-intl / FormatJS + Locize
React's most-popular ICU MessageFormat library, paired with Locize for cloud translation management, AI translation, and CDN delivery.
react-intl is part of the FormatJS project — a comprehensive set of i18n primitives for JavaScript. It provides React-native components (FormattedMessage, FormattedNumber, FormattedDate, FormattedList) and a useIntl hook, all built on the ICU MessageFormat standard. With v10.x as the current line and v8.x continuing to provide LTS-level support, react-intl is mature, actively maintained, and React Server Components-ready.
Locize natively supports ICU MessageFormat at the platform level — translators see ICU syntax directly in the editor, plurals and selects work the way react-intl expects, and no format conversion is needed. The integration uses the locizer client (a small generic Locize CDN client, framework-agnostic) to load translation messages and feed them into react-intl's IntlProvider.
- Library: react-intl (part of FormatJS)
- Current version: v10.x line (v8.x LTS also maintained)
- Format: ICU MessageFormat (handled by Locize's
format-messageformatpackage) - RSC support: Yes — modernized for React 19 and React Server Components
- Example repos: locize-react-intl-example · locize-formatjs-example
- Best for: React apps that want idiomatic ICU MessageFormat semantics + React component API
How react-intl works in your code
A typical FormattedMessage usage with interpolation. The id identifies the translation key; defaultMessage is the English source.
import { FormattedMessage } from 'react-intl'
function Welcome ({ name }) {
return (
<h1>
<FormattedMessage
id="app.welcome"
defaultMessage="Welcome, {name}!"
values={{ name }}
/>
</h1>
)
}Plurals use ICU MessageFormat directly in the defaultMessage — one string, all plural forms, picked at runtime.
<FormattedMessage
id="cart.items"
defaultMessage="{count, plural, one {1 item} other {# items}}"
values={{ count }}
/>Connecting react-intl to Locize
Override the default IntlProvider with one that loads translations from the Locize CDN via the locizer client, then passes them in as messages.
// Load translations from Locize CDN and feed them into react-intl
import React, { Component } from 'react'
import { IntlProvider as IP } from 'react-intl'
import locizer from 'locizer'
const PROJECTID = '[your-project-id]'
const NAMESPACE = 'common' // the translation file to use
locizer.init({
projectId: PROJECTID,
cdnType: 'standard'
})
export class IntlProvider extends Component {
state = { locale: null, messages: null }
componentDidMount () {
locizer.load(NAMESPACE, (err, translations, lng) => {
if (err) return
this.setState({ locale: lng, messages: translations })
})
}
render () {
const { locale, messages } = this.state
if (!locale) return null
return (
<IP locale={locale} messages={messages}>
{this.props.children}
</IP>
)
}
}Wrap your app with this provider instead of the default IntlProvider and you have continuous localization — translation updates from Locize ship to your running app via CDN without a rebuild.
The example repo at locize-react-intl-example shows the complete integration — including a development-mode saveMissing pattern (auto-pushes new FormattedMessage defaults to Locize as you build the UI) and i18next-subliminal wrapping for in-context editing. The simpler FormatJS variant is at locize-formatjs-example.
Frequently asked questions
react-intl is a React internationalization library — part of the FormatJS project — that uses ICU MessageFormat for translation strings. It provides React components (FormattedMessage, FormattedNumber, FormattedDate, etc.) and hooks (useIntl) for translating, formatting numbers/dates/lists, handling plurals, and supporting RTL languages. It is one of the most-used React i18n libraries alongside react-i18next.
Yes. react-intl uses ICU MessageFormat, and Locize natively supports ICU MessageFormat at the platform level — so translators see the ICU syntax in the editor and you do not need any format conversion. The integration uses the locizer client (the generic Locize CDN client) to load translation messages from your Locize project and feed them into react-intl's IntlProvider as the `messages` prop.
Install the locizer package (and optionally locize for saveMissing). At app startup, call locizer.init({ projectId, cdnType }), then load translations via locizer.load(namespace, callback). Inside the callback, pass the loaded messages to react-intl's IntlProvider via the messages prop. The example repo locize-react-intl-example shows a complete integration — including an "overriden IntlProvider" pattern that adds saveMissing support so new FormattedMessage usages automatically push their default text to Locize during development.
react-i18next has the deepest Locize integration because Locize was built by the i18next team — the i18next-locize-backend plugin handles loading translations, saveMissing pushes new strings automatically, and the in-context editor uses i18next-subliminal markers. react-intl uses ICU MessageFormat (richer plural and select syntax than i18next JSON), uses React components/hooks more idiomatically, and integrates with Locize via the locizer client. Both work well — pick react-intl when you want ICU MessageFormat semantics and idiomatic React component API; pick react-i18next when you want the deepest Locize coupling.
Yes. As of react-intl v8 (modernized for React 19 and RSC, released March 2026) and the current v10.x line, react-intl ships with React Server Components support. It works inside Next.js App Router and other RSC-enabled frameworks. For Next.js specifically, many teams prefer next-intl (designed App-Router-first with built-in routing middleware); react-intl remains the right choice when you want one i18n library across React projects regardless of framework.
Yes. The locize-react-intl-example repo demonstrates the pattern: wrap the FormattedMessage components with i18next-subliminal so every rendered string carries invisible Unicode markers that identify its translation key. The Locize editor popup (activated with ?incontext=true on the URL) reads those markers to map clicked DOM elements back to keys in your Locize project — the same in-context editing experience that i18next users get, just on a react-intl app.