v0.16.0: 后台体验升级——i18n(默认英文)/浅深主题/字号放大/关站维护页/个人设置(头像·语言·主题·密码·MCP Token)/权限管理(菜单+MCP·API)/询盘抽屉翻倍+PHP序列化数据清洗(22.7万行)+去裸JSON

This commit is contained in:
bigcode
2026-11-05 01:46:00 +08:00
parent c3df5d9db1
commit a018019504
47 changed files with 3008 additions and 830 deletions
+72
View File
@@ -0,0 +1,72 @@
/**
* # 模块 后台 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<string, AdminDict>([["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, string | number>): 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<typeof createAdminT>;
// ---- 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 <AdminLocaleContext.Provider value={{ locale, setLocale, t }}>{props.children}</AdminLocaleContext.Provider>;
}
/** # 函数 组件内取后台语言上下文(locale / setLocale / t) */
export function useAdminI18n() {
return useContext(AdminLocaleContext);
}
/** # 函数 组件内取后台翻译函数(便捷别名) */
export function useAdminT(): AdminT {
return useContext(AdminLocaleContext).t;
}