mrkeyoor.com_
Sat 08 Aug 22:49 UTC
npmWeb Frontendupdated 08 Aug 2026

react-intl

react-intl is FormatJS's React binding for translating interface messages and formatting numbers, currencies, dates, times, ranges, lists, display names, and relative time with the platform Intl APIs. An IntlProvider supplies the active locale and message catalog; components such as FormattedMessage and the useIntl hook consume that context. Messages use ICU MessageFormat, so translators can control plural and select branches instead of receiving sentence fragments assembled in code. It handles runtime formatting, not translation authoring, catalog hosting, locale negotiation, or a translation-management service.

Verdict

The strongest default for React teams that want ICU messages, mature extraction tooling, and standards-based formatting across client and server. It is a system you adopt, not a drop-in string dictionary, so budget for catalog delivery, polyfills, translator training, and major-version migrations.

API stability3/5IntlProvider, FormattedMessage, FormattedNumber, FormattedDate, and the imperative intl shape are mature, but major upgrades are not ceremonial. Version 10 requires React 18, removes the injectIntl higher-order component and related types, removes the window global-context workaround for duplicate installations, converts IntlProvider from a class to a function, and adds a separate server entry. Applications that stayed on older patterns need code changes.
Docs5/5FormatJS maintains dedicated React Intl pages for setup, runtime requirements, every component, the imperative API, ICU syntax, extraction, distribution, TypeScript customization, polyfills, testing, performance, React Native, Next.js server components, and each major upgrade. The docs include live examples and explicit fallback behavior. The main weakness is navigation breadth: production setup spans several sections and can feel like learning a platform rather than one package.
Maintenance5/5npm published 10.1.20 on August 2, 2026, and the FormatJS monorepo was pushed on August 8, 2026. The current changelog shows frequent dependency, CLDR, parser, timezone-data, extraction, and platform fixes, while the shared repository reports only 10 open issues and pull requests. Active work covers the full stack around react-intl, including CLI tooling, polyfills, parsers, server usage, and new runtime implementations.
Ecosystem5/5react-intl recorded 3,144,269 downloads for the measured week and belongs to a 14,737-star monorepo. FormatJS supplies CLI extraction, Babel and TypeScript transforms, an unplugin, SWC support, ESLint rules, ICU parsers, focused Intl polyfills, locale data, and framework guides. ICU MessageFormat and ECMA-402 Intl APIs also reduce dependence on private conventions, though translation vendors still vary in how well they preserve ICU messages.

Use it if

  • You want standards-based ICU messages that let translators own plural, select, and rich-text sentence structure
  • Your React 18+ application needs one typed API for translated strings plus locale-aware dates, numbers, lists, and display names
  • You want build-time message extraction through the wider FormatJS CLI, Babel, TypeScript, SWC, or bundler tooling
  • You need the same message catalog and formatting rules in client components, server rendering, and React Server Components
Skip it if

Setup reality

Install react-intl alongside React 18 or newer; the current package also lists @types/react >=18 as a peer, which is relevant even though JavaScript-only apps may not otherwise install React types. Every rendered consumer must sit under IntlProvider or RawIntlProvider. Your application, not the library, must detect the locale, fetch the matching messages, choose fallbacks, persist the user's choice, and decide whether rendering waits for a catalog or briefly shows the source language. Set defaultLocale to the language used by defaultMessage values or fallback sentences can mix a source-language phrase with a date formatted in the active locale. Production work normally adds @formatjs/cli or a compiler plugin to extract descriptors, sends catalogs through translation, then validates and compiles returned messages; none of that workflow comes from installing react-intl alone. ICU quoting, plural offsets, exact-number branches, and rich-text tags need translator guidance and tests. The runtime relies on Intl.NumberFormat, Intl.DateTimeFormat, and Intl.PluralRules, with RelativeTimeFormat and DisplayNames needed when those features are used. Older browsers and some React Native runtimes need FormatJS polyfills loaded in the documented dependency order plus per-locale data, which can outweigh the core package. The docs also warn that FormatJS ESM dependencies may need transpilation in some build pipelines. Version 10 removed injectIntl and the global multiple-copy context workaround, so deduplicate react-intl and migrate class wrappers to useIntl. For Next.js React Server Components, import createIntl from react-intl/server rather than pulling the client-marked main entry into a server component. Decide how onError handles missing translations in production; silencing it globally can hide broken catalogs.

Patterns

Wrap the app with a locale and catalogprovide-locale-messages

import {IntlProvider} from 'react-intl';
import fr from './lang/fr.json';

root.render(
  <IntlProvider locale="fr" defaultLocale="en" messages={fr}>
    <App />
  </IntlProvider>
);

defaultLocale must match the language of defaultMessage strings. The application is responsible for loading and selecting the catalog.

Render a translated message with valuesformat-basic-message

import {FormattedMessage} from 'react-intl';

<FormattedMessage
  id="account.greeting"
  defaultMessage="Hello, {name}"
  description="Greeting above the account page"
  values={{name: user.displayName}}
/>

Keep defaultMessage and description beside the call so FormatJS extraction tools can give translators useful source context.

Let ICU choose plural branchesformat-plural-message

<FormattedMessage
  id="cart.items"
  defaultMessage="{count, plural, =0 {Your cart is empty} one {# item} other {# items}}"
  values={{count: items.length}}
/>

Do not pluralize by concatenating translated fragments. ICU plural rules vary by locale, and exact branches such as =0 are checked before categories.

Map message tags to React elementsformat-rich-text-message

<FormattedMessage
  id="terms.notice"
  defaultMessage="Read our <terms>terms</terms> before continuing."
  values={{
    terms: (chunks) => <a href="/terms">{chunks}</a>,
  }}
/>

Tags are part of the ICU message, so translators can move the linked phrase. Supply functions, not raw HTML, for rich-text values.

Format text for an attribute with useIntlformat-imperative-message

import {useIntl} from 'react-intl';

function DeleteButton({name}) {
  const intl = useIntl();
  const label = intl.formatMessage(
    {id: 'user.delete', defaultMessage: 'Delete {name}'},
    {name}
  );
  return <button aria-label={label}>×</button>;
}

Use the imperative API when a string must go into aria-label, title, placeholder, or a non-React API. The component still needs IntlProvider context.

Format a currency amountformat-currency

import {FormattedNumber} from 'react-intl';

<FormattedNumber
  value={invoice.total}
  style="currency"
  currency={invoice.currency}
  currencyDisplay="symbol"
/>

The value is in major currency units, not minor units. Currency formatting does not convert exchange rates.

Render a date in an explicit time zoneformat-date-timezone

import {FormattedDate} from 'react-intl';

<FormattedDate
  value={new Date(event.startsAt)}
  dateStyle="long"
  timeZone="America/New_York"
/>

Without timeZone, output uses the runtime's zone, which can cause server and client markup to disagree during hydration.

Show relative time that updatesformat-relative-time

import {FormattedRelativeTime} from 'react-intl';

<FormattedRelativeTime
  value={-5}
  unit="minute"
  numeric="auto"
  updateIntervalInSeconds={60}
/>

The value is relative to now in the selected unit. This feature requires Intl.RelativeTimeFormat or its polyfill.

Join a localized listformat-list

import {FormattedList} from 'react-intl';

<FormattedList
  value={['Ada', 'Grace', 'Linus']}
  type="conjunction"
  style="long"
/>

List punctuation and the final conjunction come from the active locale. This is safer than joining translated UI text with commas.

Format inside a React Server Componentcreate-server-formatter

import {createIntl, createIntlCache} from 'react-intl/server';

const cache = createIntlCache();
const intl = createIntl({locale: 'en', messages: {}}, cache);

export function Price({value}) {
  return intl.formatNumber(value, {style: 'currency', currency: 'USD'});
}

Version 10 provides react-intl/server so server components do not import the main entry marked use client. Recreate intl when locale or messages change.

Report missing messages without hiding other errorshandle-missing-translations

<IntlProvider
  locale={locale}
  defaultLocale="en"
  messages={messages}
  onError={(error) => {
    if (error.code === 'MISSING_TRANSLATION') {
      reportMissingMessage(error.message);
      return;
    }
    console.error(error);
  }}
>
  <App />
</IntlProvider>

Do not replace onError with an empty function. Parse failures and formatting errors need visibility even if missing translations use defaultMessage.

Extract declared messages for translationextract-message-catalog

npm install --save-dev @formatjs/cli

# package.json
# "scripts": {
#   "i18n:extract": "formatjs extract 'src/**/*.{ts,tsx}' --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'"
# }

npm run i18n:extract

react-intl does not extract catalogs by itself. Keep the CLI version and ID strategy stable or message identifiers can churn across builds.

Alternatives

PackageRegistryPick it when
react-i18nextnpmChoose it when language detection, resource backends, namespaces, and the wider i18next plugin model matter more than an ICU-first workflow
@lingui/reactnpmChoose it for a compile-time catalog workflow with React bindings and a smaller runtime-centered architecture
next-intlnpmChoose it in a Next.js App Router project that wants routing, server-component, request-locale, and navigation conventions together