facebook / facebook/astryx

i18n: Translator adapter to reuse an existing i18n runtime for astryx strings

Open
#4,029 0 comments 0 reactions 1 assignee Claimed by @nynexman4464 View on GitHub
discussion
Dominant language
TypeScript
Stars
13k
Forks
1.1k
Avg merge
1d 15h
Merged PRs (30d)
690

Description

## Motivation

The original RFC (#3641) proposed a `Translator` adapter interface so consumers could plug their existing i18n runtime (react-intl, i18next, next-intl, LinguiJS, etc.) into `` as the resolver for astryx-shipped strings. Consumers with an existing i18n stack could then merge astryx's catalog into their own and get one-provider / one-catalog / one-runtime — no double bookkeeping.

The v1 implementation (PRs #3765 → #4016) shipped everything except this adapter. The current story is the two-provider coexistence pattern documented in [`npx astryx docs internationalization`](https://astryx.atmeta.com/docs/internationalization#using-astryx-with-your-own-i18n-library):

```tsx



```

That works and matches how MUI + react-intl users compose today, but it means two providers, two catalogs (`appFr` + `astryxFr`), and manual locale-sync. The adapter would collapse all of that into:

```tsx

```

## Design sketch

The adapter is a small interface (RFC #3641 already sketched it):

```ts
export interface Translator {
format(message: string, values?: Record, locale?: string): string;
}
```

`` would use the passed translator instead of the built-in `intl-messageformat` runtime. astryx keys (`@astryx.*`) still live in astryx's shipped `en.json` catalog; the caller merges those into whatever catalog store their runtime uses (react-intl `messages`, i18next resources, etc.).

Open design questions:

1. **Catalog merging** — does astryx export a helper to fold `@astryxdesign/core/locales/en.json` into a react-intl / i18next-shaped store, or do consumers do it manually?
2. **Regional fallback** — astryx's built-in resolver walks `pt-BR → pt → en`. Do we keep that in the runtime and only delegate the *final message.format(values)* to the adapter, or do we punt fallback to the consumer's runtime entirely?
3. **ICU parity** — react-intl handles ICU MessageFormat natively (both use `intl-messageformat` under the hood, actually). i18next uses `{{mustache}}` interpolation by default and needs a plugin for ICU — do we ship an example adapter with the required config?
4. **RSC/SSR compatibility** — the adapter needs to work in server components too; the built-in runtime already has RSC support via the `react-server` export condition. Adapter design should keep that door open.

## Prior art

- `react-intl` itself: `` with an injected `formatMessage` fn.
- `next-intl`: has a first-class integration with MUI's `LocalizationProvider` via a documented pattern.
- MUI DataGrid's `localeText` prop is the sibling of what we're proposing — same idea (delegate string resolution to the consumer), lower ambition (one component, one catalog).

## Scope

- New PR building on the current i18n stack (post #4016 merge).
- Adds the `Translator` type to `@astryxdesign/core/i18n`.
- Extends `` with an optional `translator` prop that overrides the built-in runtime when provided.
- Ships an example adapter for `react-intl` (smallest surface, most-used) as an integration guide in `packages/cli/docs/internationalization.doc.mjs`.
- Ships a codemod (`npx astryx upgrade`) is nice-to-have but not required — the migration is opt-in.

## Non-goals

- **Not** replacing `intl-messageformat` as the built-in runtime. Consumers who don't opt in continue to get today's behavior.
- **Not** shipping first-party astryx translations (tracked separately in the roadmap).
- **Not** breaking the two-provider coexistence pattern documented today — it stays as a valid alternative for consumers who prefer runtime isolation.

## Related

- #3641 — parent RFC
- #4016 — docs page that mentions the adapter as a roadmap item
- PRs #3765 → #4016 — v1 implementation the adapter builds on

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.