React Intl compatibility
@messagevisor/react-intl-compat is a migration layer for React applications that already use react-intl patterns. It lets teams keep familiar APIs while moving message ownership into Messagevisor datafiles.
Use it together with @messagevisor/react and a configured @messagevisor/sdk instance.
Install#
$ npm install @messagevisor/sdk @messagevisor/react @messagevisor/react-intl-compatIf your messages use ICU placeholders, plurals, select, or rich text tags, also install the ICU module:
$ npm install @messagevisor/module-icuProvider setup#
The compatibility layer reads the same MessagevisorProvider context as the React SDK:
import { createMessagevisor } from "@messagevisor/sdk";import { createICUModule } from "@messagevisor/module-icu";import { MessagevisorProvider } from "@messagevisor/react";import { FormattedMessage, useIntl } from "@messagevisor/react-intl-compat";import datafile from "./datafiles/messagevisor-web-en-US.json";const m = createMessagevisor({ datafile, modules: [createICUModule({ ignoreTags: false })],});export function AppRoot() { return ( <MessagevisorProvider instance={m} defaultRichTextElements={{ strong: (chunks) => <strong>{chunks}</strong>, link: (chunks) => <a href="/terms">{chunks}</a>, }} > <App /> </MessagevisorProvider> );}function App() { const intl = useIntl(); return ( <main> <FormattedMessage id="dashboard.welcome" values={{ name: "Ada" }} /> <p>{intl.formatNumber(1200, "compactShort")}</p> </main> );}What is compatible#
The package exports familiar React Intl-style APIs:
useIntl()FormattedMessageFormattedDateFormattedTimeFormattedNumberFormattedRelativeTimeFormattedListFormattedDisplayNameFormattedPlural- parts components such as
FormattedNumberParts defineMessage()anddefineMessages()injectIntl()
The returned intl object also exposes messagevisor, so you can drop down to the underlying SDK when you need a Messagevisor-specific capability.
formatMessage#
formatMessage() first tries the descriptor id as a Messagevisor message key. If the key is missing and the descriptor includes defaultMessage, the compatibility layer passes it to the SDK as defaultTranslation.
const intl = useIntl();intl.formatMessage( { id: "checkout.total", defaultMessage: "Total: {amount, number, money}", }, { amount: 42 });This makes incremental migration practical:
- existing descriptors can keep their IDs
defaultMessagecan remain as a fallback during migration- Messagevisor becomes the source of truth as keys are added to datafiles
Formatted components#
Formatted components are useful when you want to keep JSX call sites close to React Intl:
<FormattedMessage id="legal.terms" values={{ product: "Messagevisor" }} /><FormattedNumber value={1234.56} format="money" /><FormattedDate value="2026-05-06T10:00:00Z" format="long" /><FormattedRelativeTime value={-1} unit="day" />The format prop can be a named Messagevisor preset or an inline Intl options object, matching the lower-level SDK helpers.
Rich text#
Rich text uses ICU-style tags. Configure createICUModule({ ignoreTags: false }), then provide handlers:
<FormattedMessage id="legal.terms" defaultMessage="Read the <link>terms</link>." values={{ link: (chunks) => <a href="/terms">{chunks}</a>, }}/>For common tags, prefer defaultRichTextElements on MessagevisorProvider. Per-call values win when a message needs a custom handler.
Migration notes#
This package is intentionally a compatibility layer, not a full copy of React Intl internals.
Recommended migration path:
- add Messagevisor datafile loading and
MessagevisorProvider - replace imports from
react-intlwith@messagevisor/react-intl-compat - keep existing descriptors and
defaultMessagevalues during the transition - move canonical message text into Messagevisor
messages/ - add tests and examples for messages with values, rich text, and formatting
Use the native React SDK hooks for new code when possible. Use this compatibility layer where reducing migration risk matters more than adopting the new API immediately.
Edge cases and behavior notes#
ICU module is required for formatting syntax#
Without createICUModule(), strings such as Hello {name} or rich text tags are treated as plain strings. The compatibility layer throws a helpful error when descriptor formatting appears to require ICU but no ICU module is active.
Locale comes from the SDK instance#
useIntl() derives locale, default translations, and default formats from the active Messagevisor instance when the component renders. For new components that must react directly to locale, datafile, context, currency, or time zone changes, prefer the focused hooks from React SDK, such as useLocale(), useDirection(), and useTranslation().
Keep datafiles target-specific#
React Intl applications often had one messages object per locale. Messagevisor datafiles are also target-specific, so a web app should load the web target datafile rather than a universal project export unless that is intentional.

