Skip to content

i18n

Feature-scoped translations — ‘Hallo’ and ‘Hello’ in the same app.

  • r.translations() for multi-language feature keys
  • Plurals

A translation value can be a CLDR plural-forms object instead of a plain string. other is required; the rest (zero/one/two/few/many) only exist where the locale’s grammar needs them:

"greeting.unread_count": {
de: { one: "{count} ungelesene Nachricht", other: "{count} ungelesene Nachrichten" },
en: { one: "{count} unread message", other: "{count} unread messages" },
},

t(key, locale, { count }) picks the CLDR category for count via Intl.PluralRules(locale), then interpolates {count} (and any other {name} placeholder) into the chosen form.

Feature entry point: src/feature.ts.

Terminal window
cd samples/recipes/i18n
bun test

The feature entry point — embedded straight from the source file, so the code here is exactly what runs. Multi-file samples keep their remaining files next to it on GitHub (link below):

// i18n Sample
// Shows: r.translations() for multi-language feature keys, and plural forms
// (CLDR categories) for a count-dependent key
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
export const greetingFeature = defineFeature("greeting", (r) => {
r.translations({
keys: {
"greeting.welcome": {
de: "Willkommen",
en: "Welcome",
fr: "Bienvenue",
},
"greeting.goodbye": {
de: "Auf Wiedersehen",
en: "Goodbye",
fr: "Au revoir",
},
"greeting.hello_name": {
de: "Hallo, {name}!",
en: "Hello, {name}!",
fr: "Bonjour, {name}!",
},
"greeting.unread_count": {
de: { one: "{count} ungelesene Nachricht", other: "{count} ungelesene Nachrichten" },
en: { one: "{count} unread message", other: "{count} unread messages" },
pl: {
one: "{count} nieprzeczytana wiadomość",
few: "{count} nieprzeczytane wiadomości",
many: "{count} nieprzeczytanych wiadomości",
other: "{count} nieprzeczytanej wiadomości",
},
},
},
});
});
export const errorFeature = defineFeature("errors", (r) => {
r.translations({
keys: {
"errors.not_found": {
de: "Nicht gefunden",
en: "Not found",
},
"errors.access_denied": {
de: "Zugriff verweigert",
en: "Access denied",
},
},
});
});

📄 On GitHub: samples/recipes/i18n/src/feature.ts