mrkeyoor.com_
Wed 23 Sept 00:33 UTC
npmWeb Frontendupdated 22 Sept 2026

react-intl review

react-intl 10.1.23 is FormatJS's React layer for ICU messages and locale-aware formatting. `IntlProvider` supplies the active locale and catalog; components and `useIntl()` format translated text, plurals, numbers, currencies, dates, ranges, lists, display names, and relative time. ICU syntax lets translators reorder values and own plural or select branches instead of receiving sentence fragments. The package does not detect languages, fetch catalogs, or run a translation service. Version 10.1.23 is a coordinated monorepo release with no react-intl runtime change called out; its notes center on extraction, review tooling, and docs. Our 10.1.22 full-import bundle measured 58.3 KB minified and 17.5 KB gzipped.

Verdict

Our react-intl 10.1.22 install took 2.7 seconds, used 3 MB across 9 packages, and produced a 17.5 KB gzipped full import with no audit findings; 10.1.23 lists no package-specific runtime change. Choose it for a serious ICU and extraction workflow across React client and server code, not for a couple of native formatter calls.

We installed it

Lab card: what happened when we installed react-intlScreenshot of react-intl documentation
Install✓ · 2.7s9 packages on disk · 3 MB
ImportESM import works · require() works · ESM package with exports map
Browser17.5 KBgzipped (58.3 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does react-intl install cleanly?

Yes. In a fresh container with an empty cache, npm install react-intl finished in 3 seconds, leaving 9 packages and 3 MB on disk. npm audit reported no known vulnerabilities.

How much does react-intl add to a browser bundle?

17.5 KB gzipped (58.3 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does react-intl work with both ESM and CommonJS?

Yes. Both import 'react-intl' and require('react-intl') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does react-intl include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

react-intl or react-i18next: which should you use?

react-i18next: Choose it when language detection, resource backends, namespaces, and the i18next plugin system matter most. Our react-intl 10.1.22 install took 2.7 seconds, used 3 MB across 9 packages, and produced a 17.5 KB gzipped full import with no audit findings; 10.1.23 lists no package-specific runtime change.

When should you not use react-intl?

You want language detection, resource loading, namespaces, and backend adapters in the runtime package. The application must supply those around react-intl.

API stability3/5`IntlProvider`, `FormattedMessage`, the number and date components, and the imperative `intl` object are established APIs. Major upgrades still remove real application patterns. Version 10 requires React 18, removes `injectIntl` and its wrapper types, drops the multiple-copy window workaround, changes the provider implementation, and adds a server entry. A hook-based React 18 codebase has a steady path; older class wrappers need migration work.
Docs5/5FormatJS documents setup, runtime requirements, each component, imperative calls, ICU syntax, extraction, catalog distribution, TypeScript customization, polyfills, testing, performance, React Native, Next.js server components, and major upgrades. Examples explain fallback order and rich-text handling rather than only showing a provider. The cost is breadth: a correct production setup spans runtime, compiler, polyfill, and distribution pages, so the quick start is only the first layer.
Maintenance5/5npm published 10.1.23 on August 23, 2026, and the FormatJS monorepo was pushed on August 26. GitHub shows 14,743 stars and only 6 open issues and pull requests across the repository at fetch time. The current release is mainly coordinated tooling and documentation work, while earlier August releases updated the parser and intl runtime dependencies. Maintenance covers the full localization toolchain rather than the React package in isolation.
Ecosystem5/5npm counted 3,359,588 react-intl downloads in the week ending August 24, 2026. FormatJS supplies catalog extraction, compiler transforms, lint rules, ICU parsers, focused Intl polyfills, locale data, and server guidance around the React API. ICU MessageFormat and ECMA-402 reduce dependence on private formatting rules. Translation vendors still differ in ICU support, so the surrounding workflow must preserve syntax and descriptions correctly.

Use it if

  • A React 18+ interface needs ICU plural and select messages whose grammar stays under translator control.
  • The same typed API should format text, numbers, dates, ranges, lists, and display names in components and server code.
  • Build-time extraction through FormatJS CLI, Babel, TypeScript, SWC, or bundler plugins is part of the localization workflow.
  • Client components, server rendering, and React Server Components need one catalog format and matching ECMA-402 behavior.
Skip it if

Setup reality

We installed react-intl 10.1.22 in 2.7 seconds in a fresh Node 22 Bookworm sandbox. It left 9 packages and 3 MB on disk. The package was 204 KB unpacked with 3 direct and 2 peer dependencies, and npm audit found 0 known vulnerabilities. It shipped TypeScript declarations as an ESM package with an exports map. Both require() and ESM import worked. Our esbuild full import measured 58.3 KB minified and 17.5 KB gzipped.

The registry now serves 10.1.23, so the lab figures remain tied to 10.1.22. The current manifest peers on React 18+ and @types/react 18+, which can surprise JavaScript projects that do not normally install React types. Every consumer needs IntlProvider or RawIntlProvider. Your app chooses the locale, loads catalogs, defines fallback behavior, stores user preference, and decides what renders before translations arrive. Set defaultLocale to the language of defaultMessage strings.

A production workflow usually adds FormatJS extraction or compiler tooling, sends source catalogs for translation, validates returned ICU, and compiles messages. Installing react-intl does none of that. Test apostrophe quoting, plural offsets, exact-number branches, rich-text tags, and missing translations. Runtime support depends on Intl.NumberFormat, Intl.DateTimeFormat, and Intl.PluralRules, plus RelativeTimeFormat or DisplayNames when used. Older browsers and some React Native targets need polyfills loaded in the documented order with locale data.

FormatJS packages are ESM and may need transpilation in older build setups. Deduplicate react-intl because version 10 removed its former global workaround for multiple copies. In React Server Components, import createIntl from react-intl/server so the client-marked main entry stays out. Review onError; an empty handler hides parse and formatting failures along with missing messages. Version 10.1.23 lists no package-specific runtime change, so its value is alignment with the current FormatJS release rather than a new React API.

Patterns

Supply one locale and its messages to the tree provide-catalog

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 used in `defaultMessage`. Locale detection and catalog loading remain application responsibilities.

Render one extractable message with a value render-message

import {FormattedMessage} from 'react-intl';

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

Keeping source text and description beside the call gives extraction tools context that a bare ID cannot provide to translators.

Let the active locale choose a plural branch render-plural

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

Exact branches such as `=0` are checked before locale categories. Keep the full sentence in ICU rather than joining translated fragments in JSX.

Turn an ICU tag into a React link render-rich-text

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

The translator may reposition the tagged phrase. Supply a React-producing function instead of inserting catalog text through raw HTML.

Create translated text for an aria label format-attribute

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>;
}

The imperative API is needed when a string goes into `aria-label`, `title`, `placeholder`, or a non-React API. It still reads provider context.

Render a monetary value without converting it format-currency

import {FormattedNumber} from 'react-intl';

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

The input is in major currency units. Formatting adds locale rules and a symbol but performs no exchange-rate or minor-unit conversion.

Fix the time zone for server and browser output format-zoned-date

import {FormattedDate} from 'react-intl';

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

Without `timeZone`, each runtime uses its local zone. Server and client can then render different dates and trigger hydration mismatches.

Render a relative minute value that refreshes format-relative-time

import {FormattedRelativeTime} from 'react-intl';

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

The value is already relative to now in the chosen unit. The runtime must provide `Intl.RelativeTimeFormat` or load its polyfill and locale data.

Join names with locale-specific punctuation format-list

import {FormattedList} from 'react-intl';

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

`Intl.ListFormat` decides separators and the final conjunction. A manual comma join cannot adapt that grammar by locale.

Use the server entry inside a Server Component format-on-server

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's `/server` entry avoids importing the main client-marked module. Build a new formatter when locale or messages change.

Handle missing translations without hiding parse errors report-missing-message

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

An empty `onError` also swallows malformed ICU and formatter failures. Filter the known missing-message case and preserve visibility for the rest.

Extract source descriptors into a catalog extract-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 messages on its own. Pin the CLI and keep the ID strategy stable so source edits do not churn unrelated identifiers.

Alternatives

PackageRegistryPick it when
react-i18nextnpmChoose it when language detection, resource backends, namespaces, and the i18next plugin system matter most.
@lingui/reactnpmChoose it for a compile-time catalog workflow with React bindings and a smaller runtime-centered design.
next-intlnpmChoose it in a Next.js App Router project that wants locale routing, request configuration, navigation, and server conventions together.

More web frontend guides

postcss · react · react-dom · tailwindcss · htmlparser2 · tailwind-merge · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.