feat(i18n): 接入 @huanlin/dsh-plugin-better-locale 支持 ja 覆盖
新增 ja 词典(src/client/locales-ja.ts,326 keys,与 zh key-set-equal),
通过可选 peer @huanlin/dsh-plugin-better-locale 接入第三语言覆盖:
- locales.ts: 新增 attachBetterLocale(store) + ja dict export;t() 先查
store.getOverride(active, 'betterSidebar', key),命中则返回覆盖文本,
否则走原 zh/en 链;isZh() 在 override 激活时返回 false
- client/index.tsx: apply 中 ctx.get('betterLocale') 取得 override store
(optional,未安装时为 undefined),attachBetterLocale 注入 t();同时
register('betterSidebar', { ja }) 把 ja 词典注册进 better-locale 的
store,让外部 ctx.locale.lookup 调用者也能拿到 ja 文本
- Sidebar.tsx: 新增 betterLocaleActive uSES 订阅 store.subscribe,覆盖
切换时全树重渲染(DSH locale 的 active 字段不变,既有 localeRevision
uSES 不会触发)
- package.json: @huanlin/dsh-plugin-better-locale 加为 optional peer
+ devDep link
- tests/locales.spec.ts: 新增 7 个 better-locale override 测试(命中/
fallback/detach/interpolate/ja dict 完整性 smoke check)
未安装 better-locale 时 ctx.get 返回 undefined,整段为 no-op,zh/en
行为完全不变。
This commit is contained in:
@@ -188,6 +188,37 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) {
|
||||
)
|
||||
void localeRevision
|
||||
|
||||
// better-locale override freshness: when @huanlin/dsh-plugin-better-locale
|
||||
// is installed and the user picks an override language (e.g. ja), the
|
||||
// store's `active` changes but the DSH locale's `active` does NOT —
|
||||
// better-locale keeps the dsh active value (zh/en) unchanged and only
|
||||
// patches `LocaleRuntime.prototype.lookup`. The localeRevision uSES
|
||||
// above reads `getSnapshot().active`, so it sees no change and skips
|
||||
// re-render. This second uSES reads the better-locale store's `active`
|
||||
// directly, so an override switch fires a full re-render and t() picks
|
||||
// up the new override text. Optional: ctx.get returns undefined when
|
||||
// better-locale is absent, in which case this is a no-op uSES.
|
||||
type BetterLocaleStore = {
|
||||
readonly active: string | undefined
|
||||
subscribe(listener: () => void): () => void
|
||||
}
|
||||
const betterLocaleStore = (ctx as unknown as {
|
||||
get(name: 'betterLocale'): BetterLocaleStore | undefined
|
||||
}).get('betterLocale')
|
||||
const betterLocaleActive = useSyncExternalStore(
|
||||
useMemo(() => {
|
||||
const store = betterLocaleStore
|
||||
if (store === undefined) return (_cb: () => void) => () => {}
|
||||
return (callback: () => void) => store.subscribe(callback)
|
||||
}, [betterLocaleStore]),
|
||||
useMemo(() => {
|
||||
const store = betterLocaleStore
|
||||
if (store === undefined) return () => undefined
|
||||
return () => store.active
|
||||
}, [betterLocaleStore]),
|
||||
)
|
||||
void betterLocaleActive
|
||||
|
||||
// Tab-registry revision: TabContent memo cells must pick up a descriptor
|
||||
// a plugin registers/disposes after mount (the + menu / icons already read
|
||||
// the registry at render). Rare events (plugin (un)mount), so one full
|
||||
|
||||
Reference in New Issue
Block a user