Navigated to /docs/core/localization

Localization

Create locale-aware messages, detection, document direction, and localized application links.

Use one application i18n service

createI18n owns supported locales, nested messages, the current locale, and optional locale prefixes. Creating src/i18n.ts alone does not run it: import the service from your browser entry before bootTavo and supply it as ssr.i18n in tavo.config.ts. Both environments must initialize the same catalog so SSR, hydration, links, and later navigation agree.

Define locales and messages together

The default locale is also the fallback unless you configure another. Locale detection can use the path, cookie, and Accept-Language header.

TSsrc/i18n.ts — create this localization service
tsimport { createI18n } from "@tavojs/core";

export const i18n = createI18n({
  defaultLocale: "en",
  routing: { enabled: true },
  locales: {
    en: { label: "English", dir: "ltr" },
    es: { label: "Español", dir: "ltr" }
  },
  messages: {
    en: { projects: { title: "Projects" } },
    es: { projects: { title: "Proyectos" } }
  }
});

Initialize the service in both entry points

Merge these lines into the existing configuration and browser entry. Creating the service registers it as tavo:i18n, which Link discovers; passing it to ssr.i18n also makes the server setup explicit.

TStavo.config.ts — preserve existing settings
tsimport { defineConfig } from "@tavojs/core/config";
import { i18n } from "./src/i18n";

export default defineConfig({
  ssr: { i18n }
});
TSXsrc/main.tsx — import before the existing boot call
tsximport "./i18n";
import { bootTavo } from "@tavojs/core";

void bootTavo();
TSXsrc/pages/projects.tsx — read a translated message
tsximport { i18n } from "../i18n";

export default function ProjectsPage() {
  return <main><h1>{i18n.t("projects.title")}</h1></main>;
}

Keep server and browser locale state aligned

  • Resolve the request locale before rendering route loaders and metadata.

  • Use the Tavo.js Link integration so internal destinations receive the active locale prefix.

  • Set document language and direction from the resolved locale.

  • Do not read a browser-only locale during the first render of an SSR page.

Localization options and defaults

  • locale and fallbackLocale default to defaultLocale. Direction defaults to ltr.

  • The locale cookie defaults to tavo_locale and detection order defaults to path, cookie, then Accept-Language.

  • The default locale has no URL prefix unless defaultLocalePrefix is always or localizePath requests includeDefaultLocale.

  • The service registers as tavo:i18n by default so Link and the pages runtime can discover it. Set serviceName: false to avoid registration.

TS
tscreateI18n({
  defaultLocale,
  locale?,
  fallbackLocale?,
  messages,
  locales?: { [locale]: { label?: string; dir?: "ltr" | "rtl" | "auto" } },
  routing?: false | {
    enabled?: boolean;
    defaultLocalePrefix?: "always" | "never";
    cookieName?: string;
    detectFrom?: Array<"path" | "cookie" | "header">;
  },
  serviceName?: string | false,
  onMissingKey?: ({ key, locale, fallbackLocale }) => string | void
});

Localization service reference

  • text and t are reactive when read during component rendering. t interpolates string parameters and stringifies non-string leaf values.

  • setLocale persists by default when cookie detection is enabled; pass persist: false for a temporary selection.

  • A missing key uses onMissingKey when supplied and otherwise returns the key itself.

  • defineMessages marks the central catalog for build-time locale splitting. Generated locale chunks are applied automatically by the framework runtime.

TS
tsi18n.locale; i18n.defaultLocale; i18n.fallbackLocale; i18n.locales; i18n.dir;
i18n.messages; i18n.text; i18n.store;
i18n.setLocale(locale, { persist?: boolean });
i18n.setMessages(locale, messages, { merge?: boolean });
i18n.getLocaleInfo(locale?);
i18n.detectLocale({ pathname?, request?, headers?, cookie? });
i18n.resolvePath(pathname);
i18n.localizePath(pathname, locale?, { includeDefaultLocale?: boolean });
i18n.setLocaleFromRequest(input?); i18n.setLocaleFromPath(pathname);
i18n["t"](key, params?);
i18n.subscribe(listener, { immediate?: boolean });
i18n.watchLocale(listener, { immediate?: boolean });

Look up exact public types

Follow linked API names to their canonical TypeScript declarations and package boundaries.