fix(i18n): better-locale 接入改为 activation-order-safe
ctx.get('betterLocale') 是非响应式读取(cordis 只对声明的 inject
依赖重新求值)。如果 better-locale 在 better-sidebar 之后激活,
apply 顶层的 ctx.get 返回 undefined,attachBetterLocale(undefined)
使整个覆盖接入变成 no-op,即使用户后来在设置页选了日语,
better-sidebar 的 t() 也不查询 override store。
改为在 ctx.effect 中订阅 ctx.locale.subscribe:better-locale 在
激活时(若有持久化的 override)和用户切换 override 时都会 bump
locale revision,subscribe 回调触发 sync(),重新读取 ctx.get
('betterLocale')。store 可用后 attachBetterLocale(store) + register
ja dict;store 不可用时 detach。
这解决了插件激活顺序不确定的问题:无论 better-locale 先于还是后于
better-sidebar 激活,override 接入都能正确建立。
This commit is contained in:
+37
-21
@@ -67,28 +67,44 @@ export function apply(ctx: Context): void {
|
||||
// directly) also switches to the override language. We also register
|
||||
// the ja dict with the better-locale store so external callers of
|
||||
// ctx.locale.lookup('betterSidebar', key) get the override text too.
|
||||
// Optional peer: ctx.get returns undefined when better-locale is absent,
|
||||
// in which case the whole block is a no-op and the zh/en chain runs.
|
||||
const betterLocale = ctx.get('betterLocale') as
|
||||
| {
|
||||
readonly active: string | undefined
|
||||
getOverride(dshActive: string, ns: string, key: string): string | undefined
|
||||
isOverrideActive(dshActive: string): boolean
|
||||
register(ns: string, dicts: Record<string, Record<string, string>>): () => void
|
||||
subscribe(listener: () => void): () => void
|
||||
//
|
||||
// Activation-order-safe: ctx.get('betterLocale') is a non-reactive read
|
||||
// (cordis only re-evaluates declared `inject` deps). If better-locale
|
||||
// activates after better-sidebar, the initial read returns undefined.
|
||||
// We subscribe to the locale revision — better-locale bumps it on
|
||||
// activation (when a persisted override exists) and on every override
|
||||
// switch — and re-check ctx.get on each bump, attaching + registering
|
||||
// the ja dict once the store becomes available.
|
||||
ctx.effect(() => {
|
||||
let dispose: (() => void) | undefined
|
||||
const sync = (): void => {
|
||||
dispose?.()
|
||||
dispose = undefined
|
||||
const store = ctx.get('betterLocale') as
|
||||
| {
|
||||
readonly active: string | undefined
|
||||
getOverride(dshActive: string, ns: string, key: string): string | undefined
|
||||
isOverrideActive(dshActive: string): boolean
|
||||
register(ns: string, dicts: Record<string, Record<string, string>>): () => void
|
||||
subscribe(listener: () => void): () => void
|
||||
}
|
||||
| undefined
|
||||
attachBetterLocale(store)
|
||||
if (store !== undefined) {
|
||||
dispose = store.register(LOCALE_NS, { ja })
|
||||
}
|
||||
| undefined
|
||||
attachBetterLocale(betterLocale)
|
||||
if (betterLocale !== undefined) {
|
||||
ctx.effect(() => {
|
||||
// Register the ja dict for the betterSidebar namespace. Better-locale's
|
||||
// patched lookup consults this when the user has selected the ja
|
||||
// override; the dict stays owned by better-sidebar (the namespace
|
||||
// owner), so a single source of truth covers both ctx.locale callers
|
||||
// and the internal t().
|
||||
return betterLocale.register(LOCALE_NS, { ja })
|
||||
}, 'dsh-better-sidebar: better-locale ja dict')
|
||||
}
|
||||
}
|
||||
// Initial check (picks up the store if better-locale activated first).
|
||||
sync()
|
||||
// Re-check on every locale revision bump (better-locale bumps when it
|
||||
// activates with a persisted override, and when the user switches).
|
||||
const unsubscribe = ctx.locale.subscribe(sync)
|
||||
return () => {
|
||||
unsubscribe()
|
||||
dispose?.()
|
||||
attachBetterLocale(undefined)
|
||||
}
|
||||
}, 'dsh-better-sidebar: better-locale lazy integration')
|
||||
// One store instance per activation: production code creates it only here,
|
||||
// then hands it to the mounted panel and closes over it in the slot
|
||||
// registrations (the official createXXXStore() factory rule — no
|
||||
|
||||
Reference in New Issue
Block a user