Integration Guide
App setup
Create the i18n instance once, then import t, setLocale, getLocale, and initI18n wherever needed:
// i18n.ts
import { createI18n } from "@domphy/i18n"
import en from "./locales/en.json"
import vi from "./locales/vi.json"
export type Locale = "en" | "vi"
export const i18n = createI18n<Locale, typeof en>({
globalKey: "__myapp_i18n__",
namespace: "app",
locales: { en, vi },
defaultLocale: "en",
})In your app entry point:
import { i18n } from "./i18n"
await i18n.initI18n(i18n.detectLocale({ pathSegment: true, storageKey: "locale" }))Locale switcher component
import { i18n } from "./i18n"
import type { Locale } from "./i18n"
const LOCALES: { code: Locale; label: string }[] = [
{ code: "en", label: "English" },
{ code: "vi", label: "Tiếng Việt" },
]
const LocaleSwitcher = {
div: [
{
select: LOCALES.map(({ code, label }) => ({
option: label,
value: code,
})),
value: (l) => i18n.locale.get(l),
onChange: async (e: Event) => {
const lng = (e.target as HTMLSelectElement).value as Locale
await i18n.setLocale(lng)
localStorage.setItem("locale", lng)
},
"aria-label": "Select language",
},
],
}Router integration — locale from URL
Use detectLocale with pathSegment: true to read the locale from /vi/... URL prefixes:
import { i18n } from "./i18n"
import { createRouter } from "@domphy/router"
const router = createRouter({
beforeLoad: async ({ pathname }) => {
// Detect locale from /vi/... prefix
const detected = i18n.detectLocale({ pathSegment: true, storageKey: "locale" })
await i18n.initI18n(detected)
},
})Using translations in elements
import { i18n } from "./i18n"
const { t } = i18n
const Header = {
header: [
{
nav: [
{ a: (l) => t(l, "nav.home"), href: "/" },
{ a: (l) => t(l, "nav.about"), href: "/about" },
],
},
LocaleSwitcher,
],
}t(listener, key) subscribes to locale changes — the element re-renders automatically when setLocale() is called.
RTL support
Handle right-to-left languages (Arabic, Hebrew, Persian):
import { effect } from "@domphy/core"
import { i18n } from "./i18n"
const RTL_LANGUAGES = new Set(["ar", "he", "fa", "ur"])
effect(() => {
const lng = i18n.locale.get()
document.documentElement.setAttribute("dir", RTL_LANGUAGES.has(lng) ? "rtl" : "ltr")
document.documentElement.setAttribute("lang", lng)
})Domphy respects dir on the root element — CSS logical properties (margin-inline-start, padding-inline) flip automatically for RTL.