Skip to navigation

Localization

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:

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:

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

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.

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. 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:

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, 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:

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.