i18n
Default. The locale registry: locales, default locale, display names, og:locale map and a flat translation table.
What it does
Isomorphic default. i18n holds the site's locales and translations as plain config. It has
no state, no events and no lifecycle work beyond a check while createApp runs. router,
head, content and build read it with ctx.require(i18nPlugin).
How it works
createApp checks two rules: locales is not empty, and defaultLocale is one of them. Every
lookup after that is total: a miss returns undefined, and t() falls back.
t(locale, key) resolves in a fixed order: the requested locale, then the default locale, then
the key itself. It never returns undefined.
Inside the framework, plugins that find no i18n use the same defaults it ships with: one
locale, "en". Because i18n is a default plugin, that only matters for plugins you test
alone.
Config
pluginConfigs.i18n.
| Option | Type | Default | Description |
|---|---|---|---|
locales | readonly string[] | ["en"] | Supported locales, in priority order. Must not be empty. |
defaultLocale | string | "en" | The fallback locale, served at bare paths. Must be in locales. |
localeNames | Record<string, string> | {} | Display names, e.g. { uk: "Українська" }. |
ogLocaleMap | Record<string, string> | {} | og:locale values, e.g. { en: "en_US" }. |
translations | Record<string, Record<string, string>> | {} | locale → key → text. |
API
Mounted at app.i18n, reachable with ctx.require(i18nPlugin).
| Method | Signature | Description |
|---|---|---|
locales | () => readonly string[] | The configured locales, in order. |
defaultLocale | () => string | The fallback locale. |
isLocale | (x: string) => boolean | Whether x is one of the locales. Case-sensitive. |
localeName | (locale: string) => string | undefined | The display name. |
ogLocale | (locale: string) => string | undefined | The og:locale value. |
t | (locale: string, key: string) => string | The translation, with fallback. |
Events
Emits
None.
Listens to
None.
Depends on
Nothing.
Example
import { createApp } from "@moku-labs/web";
const app = createApp({
pluginConfigs: {
site: { name: "My Blog", url: "https://blog.dev", author: "Ada", description: "Notes." },
i18n: {
locales: ["en", "uk"],
defaultLocale: "en",
localeNames: { en: "English", uk: "Українська" },
ogLocaleMap: { en: "en_US", uk: "uk_UA" },
translations: {
en: { "nav.home": "Home", "nav.about": "About" },
uk: { "nav.home": "Головна" }
}
}
}
});
console.log(app.i18n.t("uk", "nav.home")); // "Головна"
console.log(app.i18n.t("uk", "nav.about")); // "About": falls back to the default locale
console.log(app.i18n.t("uk", "nav.missing")); // "nav.missing": falls back to the key
console.log(app.i18n.localeName("uk"), app.i18n.ogLocale("en")); // "Українська" "en_US"bun scripts/i18n.ts Головна About nav.missing Українська en_US
defaultLocalemust be inlocales.createAppthrows[web] i18n.defaultLocale "en" is not in i18n.locales [uk].with the fix on the next line.- An empty
localesthrows.[web] i18n.locales must contain at least one locale. - hreflang is not here.
i18nownsog:localevalues.headbuilds the hreflang links fromlocales()and the router. - The config is shallow-merged. Passing
translationsreplaces the whole table; it is not merged key by key.
Related
- i18n: the guide, with URLs per locale.
- router plugin: the
{lang:?}slot. - content plugin: locale files and fallback.