Skip to content
Moku LabsDocs
@moku-labs/web pages

i18n

Default. The locale registry: locales, default locale, display names, og:locale map and a flat translation table.

i18n.mdllms.txt

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.

OptionTypeDefaultDescription
localesreadonly string[]["en"]Supported locales, in priority order. Must not be empty.
defaultLocalestring"en"The fallback locale, served at bare paths. Must be in locales.
localeNamesRecord<string, string>{}Display names, e.g. { uk: "Українська" }.
ogLocaleMapRecord<string, string>{}og:locale values, e.g. { en: "en_US" }.
translationsRecord<string, Record<string, string>>{}locale → key → text.

API

Mounted at app.i18n, reachable with ctx.require(i18nPlugin).

MethodSignatureDescription
locales() => readonly string[]The configured locales, in order.
defaultLocale() => stringThe fallback locale.
isLocale(x: string) => booleanWhether x is one of the locales. Case-sensitive.
localeName(locale: string) => string | undefinedThe display name.
ogLocale(locale: string) => string | undefinedThe og:locale value.
t(locale: string, key: string) => stringThe translation, with fallback.

Events

Emits

None.

Listens to

None.

Depends on

Nothing.

Example

scripts/i18n.ts
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"
run
bun scripts/i18n.ts
Головна
About
nav.missing
Українська en_US
  • defaultLocale must be in locales. createApp throws [web] i18n.defaultLocale "en" is not in i18n.locales [uk]. with the fix on the next line.
  • An empty locales throws. [web] i18n.locales must contain at least one locale.
  • hreflang is not here. i18n owns og:locale values. head builds the hreflang links from locales() and the router.
  • The config is shallow-merged. Passing translations replaces the whole table; it is not merged key by key.