/** * # 模块 后台 i18n 核心(React 上下文 + t 函数) * 词典以中文源串为 key(各页面直接 t("中文字符串")),en 词典提供英文译文, * 缺词回退源串(中文)。默认英文:localStorage 未设置时 locale=en。 */ import { createContext, useContext, useEffect, useState, type ReactNode } from "react"; import { getAdminLocalePref, setAdminLocalePref, type AdminDict, type AdminLocaleDef, } from "./shared"; import { en } from "./locales/en"; // 客户端安全部分原样转出 export { ADMIN_LOCALES, ADMIN_LOCALE_STORAGE_KEY, ADMIN_THEME_STORAGE_KEY, getAdminLocalePref, setAdminLocalePref, getAdminThemePref, setAdminThemePref } from "./shared"; export type { AdminDict, AdminLocaleDef, AdminTheme } from "./shared"; /** # 成员变量 词典注册表(locale → AdminDict;en 启动即注册) **/ const dicts = new Map([["en", en]]); /** # 函数 注册某语言的后台词典 */ export function registerAdminDict(code: string, dict: AdminDict): void { dicts.set(code, dict); } /** # 函数 构造后台翻译函数:按词典查 key,缺词回退源串(中文),支持 {var} 插值 */ export function createAdminT(locale: string) { const d = dicts.get(locale); return (key: string, vars?: Record): string => { let s: string = d?.[key] ?? key; if (vars) for (const [k, v] of Object.entries(vars)) s = s.replaceAll(`{${k}}`, String(v)); return s; }; } /** # 类型 后台 t 函数 **/ export type AdminT = ReturnType; // ---- React 上下文 ---- /** # 成员变量 后台语言上下文(默认英文) **/ const AdminLocaleContext = createContext<{ locale: string; setLocale: (code: string) => void; t: AdminT }>({ locale: "en", setLocale: () => {}, t: createAdminT("en"), }); /** # 组件 后台语言提供者(纯客户端:SSR 渲染英文,水合后读 localStorage 切换,无水合不一致) */ export function AdminLocaleProvider(props: { children: ReactNode }) { const [locale, setLocaleState] = useState("en"); // 水合后应用本地偏好(effect 中 setState 不触发水合校验) useEffect(() => { setLocaleState(getAdminLocalePref()); }, []); /** # 函数 切换后台语言:写 localStorage → 重渲染(组件树即时切换,无需整页刷新) */ const setLocale = (code: string) => { setAdminLocalePref(code); setLocaleState(code); }; const t = createAdminT(locale); return {props.children}; } /** # 函数 组件内取后台语言上下文(locale / setLocale / t) */ export function useAdminI18n() { return useContext(AdminLocaleContext); } /** # 函数 组件内取后台翻译函数(便捷别名) */ export function useAdminT(): AdminT { return useContext(AdminLocaleContext).t; }