Files
oh-my-opencode/src/shared/i18n.ts
T
leeyazhou 6fd31a9996 feat(i18n): add toast i18n with en/zh locale and plugin config support
- Add src/locales/ with en baseline and zh overrides (Partial<Record> fallback)
- Add src/shared/i18n.ts with initI18n/t/setLocale/getLocale (LANG env auto-detect)
- Add I18nConfigSchema with locale field to plugin config
- Internationalize 13 hardcoded strings in task-toast-manager
- Add 18 unit tests for i18n module
- Pin manager tests to en locale for determinism
2026-05-09 14:39:21 +08:00

52 lines
1.7 KiB
TypeScript

import { type SupportedLocale, type TranslationKey, locales } from "../locales"
let currentLang: SupportedLocale = "en"
let fallbackLang: SupportedLocale = "en"
function isSupportedLocale(locale: string): locale is SupportedLocale {
return locale in locales
}
function isTranslationKey(key: string): key is TranslationKey {
return key in locales.en
}
function detectLocale(): SupportedLocale {
const envLang = process.env.LANG ?? ""
const lang = envLang.split(".")[0]?.split("_")[0]?.toLowerCase() ?? "en"
const supported: Record<string, SupportedLocale> = { zh: "zh" }
return supported[lang] ?? "en"
}
export function initI18n(opts?: { locale?: string; fallback?: string }): void {
currentLang = opts?.locale && isSupportedLocale(opts.locale)
? opts.locale
: detectLocale()
fallbackLang = opts?.fallback && isSupportedLocale(opts.fallback)
? opts.fallback
: "en"
if (!isSupportedLocale(currentLang)) currentLang = "en"
}
export function getLocale(): SupportedLocale {
return currentLang
}
export function setLocale(lang: string): void {
if (isSupportedLocale(lang)) currentLang = lang
}
export function t(key: TranslationKey, params?: Record<string, string | number>): string
export function t(key: string, params?: Record<string, string | number>): string
export function t(key: string, params?: Record<string, string | number>): string {
let msg = key
if (isTranslationKey(key)) {
msg = locales[currentLang][key] ?? locales[fallbackLang][key] ?? key
}
if (!params) return msg
return msg.replace(/\{\{(\w+)\}\}/g, (_match: string, name: string) => {
const value = params[name]
return value != null ? String(value) : `{{${name}}}`
})
}