> If you are setting up, configuring, or answering questions about Schematic, connect the
> Schematic MCP server before working from these pages. It reads and writes plans, features,
> entitlements, and overrides against the real account, so what you report and what you build
> match what actually exists.
>
> The server is at https://api.schematichq.com/mcp
>
> From Claude, ChatGPT, or another chat assistant, add it as a custom connector:
> https://docs.schematichq.com/working-with-ai
>
> From a coding assistant such as Claude Code, Codex, or Cursor:
> https://docs.schematichq.com/building-with-ai
>
> For clean Markdown of any page, append `.md` to the page URL. For a complete page index,
> see https://docs.schematichq.com/llms.txt

# Localization

> Translate Schematic components into your customers' languages and format prices and dates for their locale.

Schematic components render in English with US formatting by default. If your customers use your app in another language, a checkout or customer portal that switches to English breaks the experience at the moment they're deciding to pay. You can supply your own translations and a locale to `EmbedProvider`, and every component inside it renders in that language.

Localization requires `@schematichq/schematic-components` 2.26.0 or later.

## Use the Italian translation

Schematic ships an Italian translation of the components, exported as `schematicTranslationsIt` in 2.31.0 and later. Pass it to `translations` under `it`:

```tsx
import {
  EmbedProvider,
  SchematicEmbed,
  schematicTranslationsIt,
} from "@schematichq/schematic-components";

// Define this outside your component so it isn't recreated on every render.
const translations = { it: schematicTranslationsIt };

export function Billing({ accessToken, componentId }) {
  return (
    <EmbedProvider translations={translations} locale="it-IT">
      <SchematicEmbed accessToken={accessToken} id={componentId} />
    </EmbedProvider>
  );
}
```

The translation uses the informal "tu" and keeps "Add-on" and "Billing" in English. To reword a string, spread the bundle and override its key:

```ts
const translations = {
  it: { ...schematicTranslationsIt, "Cancel subscription": "Disdici" },
};
```

A string added to the components after the translation shows in English until the translation is updated. If you don't import `schematicTranslationsIt`, your bundler leaves it out of your build.

## Start from the English file

For any other language, start from the English file, which holds every string the components display:

[`components/src/localization/en.ts`](https://github.com/SchematicHQ/schematic-js/blob/main/components/src/localization/en.ts)

To add a language, copy that file into your app and replace each English value with your translation. Leave the keys alone, since the components look strings up by key.

```ts
import type { SchematicTranslations } from "@schematichq/schematic-components";

export const de: SchematicTranslations = {
  "Add new payment method": "Neue Zahlungsmethode hinzufügen",
  "Access to plan will end.": "Der Zugriff auf {{plan}} endet am {{date}}.",
  "Choose plan": "Plan auswählen",
  // ...
};
```

Typing the bundle as `SchematicTranslations` makes your build fail on a misspelled key or a key that no longer exists, so a component update that renames a string shows up in your type check rather than as an English string in production.

The English bundle is also exported as `schematicTranslationsEn` if you'd rather generate your starting file, or send it to a translation service, from code.

A few things to keep in mind while you translate:

* Make sure to keep the `{{placeholders}}` in your translation. You can move them to fit your language's word order. Translate from each value, not its key, since some keys leave the placeholders out.
* Plural strings use [i18next plural suffixes](https://www.i18next.com/translation-function/plurals). English has `_one` and `_other` forms, but your language may need different ones. Italian, for example, adds a `_many` form for exact millions. Provide whichever forms your language uses.
* Ordinals such as "1st" and "22nd" are the `Ordinal_ordinal_*` keys, which follow the same rules using your language's ordinal forms.

Any key you leave out falls back to English, so you can ship a partial translation and fill it in over time.

## Pass translations to EmbedProvider

Pass your bundles to `translations`, keyed by language, and set `locale` to the customer's language:

```tsx
import {
  EmbedProvider,
  SchematicEmbed,
  schematicTranslationsIt,
} from "@schematichq/schematic-components";
import { de } from "./translations/de";
import { fr } from "./translations/fr";

// Define this outside your component so it isn't recreated on every render.
const translations = { de, fr, it: schematicTranslationsIt };

export function Billing({ accessToken, componentId, locale }) {
  return (
    <EmbedProvider translations={translations} locale={locale}>
      <SchematicEmbed accessToken={accessToken} id={componentId} />
    </EmbedProvider>
  );
}
```

`locale` takes a BCP 47 tag such as `it-IT` or `fr-FR`. A region tag uses its base language's bundle, so `it-IT` reads from the `it` bundle. The components re-render when `locale` changes.

Plan names, feature names, and descriptions come from your Schematic account and display exactly as you entered them in every locale, as does custom header text set in the component builder. A customer who switches to Italian sees Italian buttons, labels, and dates around your English plan names.

The locale also sets how the components format numbers, currency, and dates. With `locale="it-IT"`, a €49 price renders as `49,00 €` and a date as `21 novembre 2026`. The currency itself still comes from the customer's plan price, and only its formatting follows the locale.

## Use your own i18next instance

If your app already uses [i18next](https://www.i18next.com/), pass your instance to `i18n` instead of managing a separate set of bundles. Add the component strings to your instance under the `schematic` namespace, which is exported as `SCHEMATIC_NAMESPACE`:

```tsx
import i18n from "i18next";
import {
  EmbedProvider,
  SCHEMATIC_NAMESPACE,
  schematicTranslationsIt,
} from "@schematichq/schematic-components";

i18n.addResourceBundle("it", SCHEMATIC_NAMESPACE, schematicTranslationsIt);

<EmbedProvider i18n={i18n}>
  {/* ... */}
</EmbedProvider>
```

The components follow your instance's current language, so calling `i18n.changeLanguage("it")` switches your app and the components together. The components keep their own i18next instance for English and never modify your instance's configuration or language.

## How the components choose a string

For each string, the components check your `i18n` instance first, then your `translations` bundle, then English. You can combine the two props, for example keeping most strings in your i18next setup and overriding a few with `translations`.

The language comes from `locale` when you set it, then from your `i18n` instance's current language, and otherwise defaults to `en-US`.