sveltekit-i18n Internationalization for SvelteKit

Playground

Every panel below drives a real instance through the public API. Change an input and the library answers — nothing here is a recording.

Message formats

The core holds no message format of its own: a parser fills the slot. Curly comes with this package; ICU is the alternative, on the core directly.

Output

You have 1,234 messages.

No reports. A report never raises — the placeholder takes its fallback and the rest of the message resolves.

Show the code
import { I18n } from 'sveltekit-i18n';

const i18n = new I18n({
  initLocale: locale,
  translations: { [locale]: { inbox: message } },
  parserOptions: { onReport: (report) => reports.push(report) },
});

i18n.t('inbox', payload);

Preprocessing

Nested translations become the flat keys t() reads. The mode decides how far that goes.

full

  • nav.home
  • nav.about
  • tags.0
  • tags.1

preserveArrays

  • nav.home
  • nav.about
  • tags array

none

  • nav object
  • tags array

rawTranslations keeps the input as it arrived; translations is what you see here.

Show the code
const i18n = new I18n({ initLocale: 'en', preprocess: mode });

i18n.addTranslations({ en: input });

Object.keys(i18n.translations.en);

Loaders

A loader runs when its locale matches and its routes match the current route, once per freshness window. Load the same route twice and watch the second attempt do nothing.

Pick a locale and a route, then load.

Show the code
const i18n = new I18n({
  initLocale: 'en',
  loaders: [
    // No routes: every route, so it loads once and never again.
    { locale, key: 'common', loader },
    // A string route is an exact match.
    { locale, key: 'home', routes: ['/'], loader },
    // A whole section needs a pattern.
    { locale, key: 'docs', routes: [/^\/docs(\/|$)/], loader },
  ],
});

await i18n.loadTranslations(locale, route);

Fallback locale

A key the active locale does not carry resolves through fallbackLocale instead of rendering empty.

Keycst(key)
titlePřekladyPřeklady
subtitleLoaded per route
ctaRead the docs

Only the missing keys fall back. What a key missing everywhere renders as is fallbackValue.

Show the code
const i18n = new I18n({
  initLocale: 'cs',
  fallbackLocale: 'en',
  translations: { en: complete, cs: partial },
});

i18n.t('subtitle'); // the English text: 'cs' has no such key