feat(i18n): 接入 @huanlin/dsh-plugin-better-locale 支持 19 语言覆盖(ja/de/fr/...) - #339
Merged
Merged
Conversation
新增 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
行为完全不变。
HuanLinOTO
marked this pull request as draft
August 22, 2026 17:23
better-locale 的覆盖本质上是借用 DSH 的英文槽位来渲染第三语言: - store.getOverride(dshActive, ns, key) 改为只在 dshActive === 'en' 时返回覆盖文本;DSH 在 zh 下覆盖完全惰性(保持原生 zh) - 新增 store.isOverrideActive(dshActive):返回 active !== undefined && dshActive === 'en',供 better-sidebar 的 isZh() 判断 - isZh() 改用 isOverrideActive(dshActive) 判断(仅在 DSH=en 且有 override 时返回 false),zh 下返回 true - LanguageSwitcher 接收 dshActive prop,选了非 native 且 DSH 非 en 时显示「请将 DSH 切换到英文以查看 [语言名]」提示 - 新增 switchToEnHint copy key(zh + en) - 测试:better-locale +3 store tests(en-only / inert on zh / isOverrideActive),+1 patch test(inert on zh);better-sidebar +1 locales test(override inert while DSH on zh),FakeBetterLocale 加 isOverrideActive 方法
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 接入都能正确建立。
…l/zh-HK/zh-TW/zh-MO)
Sidebar.tsx read ctx.get('betterLocale') unconditionally. In real
cordis hosts ctx.get exists and returns undefined when better-locale
is absent — but the unit-test mocks build a minimal ctx without a
get method, throwing 'TypeError: ctx.get is not a function' inside
<Sidebar> render and taking down 7 tests
(bottom-auto-terminal + sidebar-crash suites).
Add a typeof guard so the optional contract holds even when ctx.get
is missing. The activation-order-safe ctx.effect path in index.tsx
is unaffected (real cordis Context, runs once).
HuanLinOTO
marked this pull request as ready for review
August 23, 2026 09:54
Menghuan1918
requested changes
Aug 23, 2026
Menghuan1918
approved these changes
Aug 23, 2026
Menghuan1918
added a commit
that referenced
this pull request
Aug 24, 2026
- README / README_EN: add v0.16.0 changelog (free windows #354, model-driven sidebar opens #353, Markdown inline HTML + TOC #360, 19-language overlays #339, multi-repo git + linked worktrees #326/#285, browser loopback allowlist, Vue + 28 legacy languages #202, preview refresh trio #215/#228, local Markdown images #292, ego-browser catalog #340; fixes: market/cordis #338, ctx.get() reads #357, workspace boundary #345, panel-host layering #330/#278, layout-push hardening #310/#130/#180, width sharing #36, terminal cleanup #130, fs-search noise dirs #342, mermaid #341, Nerd Font #190, UTF-8 HTML #193, trust-fence #182, reveal-in-explorer #94, PowerShell #47, GET probe fallback #69, unrun devDep #336) and move v0.15.2 into history - feature tour: free windows + Markdown inline HTML/TOC (EN), feature list - plugin ecosystem: add ego-browser (24 tab plugins), install pin ^0.16.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
接入
@huanlin/dsh-plugin-better-locale(可选 peer)让 better-sidebar 支持 19 种第三语言覆盖:ja / de / fr / pt / ko / ar / hi / id / tr / vi / th / ru / it / nl / sv / pl / zh-HK / zh-TW / zh-MO。better-locale 通过运行时 monkey-patch
LocaleRuntime.prototype.lookup注入第三语言,但 better-sidebar 的内置t()不走 ctx.locale(它有自己的attachLocale+ zh/en 词典),所以需要 better-sidebar 自己接入各语言词典才能翻译界面。覆盖借用 DSH 的英文模式:只在 DSH active locale 为
en时生效;DSH 在zh下覆盖完全惰性(保持原生 zh,界面不混语言)。改动
src/client/locales-<lang>.ts(19 个新文件):各语言词典(每种约 340 keys),与 zh key-set 完全一致,typecheck 守护缺 key/多 key。src/client/locales.ts:attachBetterLocale(store)—— 与attachLocale对称,注入 better-locale 的 override store。locales-<lang>.ts导入,Record<keyof typeof zh, string>类型注解编译期强制 key 集相等)。t()改为先查store.getOverride(active, 'betterSidebar', key),命中则返回覆盖文本,否则走原 zh/en 链。isZh()改为store.isOverrideActive(active)语义(仅在 DSH=en 且 override 激活时返回 false;Chinese-specific selectors 切回)。src/client/index.tsx:apply()里从ctx.get('betterLocale')取得 override store(optional,未安装时为 undefined),attachBetterLocale注入t();同时store.register('betterSidebar', { ja, de, ... })把 19 语言词典注册进 better-locale 的 store,让外部ctx.locale.lookup('betterSidebar', key)调用者也能拿到覆盖文本。注册包在ctx.effect内,HMR 安全。src/client/Sidebar.tsx:新增BetterLocaleActiveuSES 订阅store.subscribe,覆盖切换时全树重新渲染。tests/locales.spec.ts:新增 19 语言 override 测试(命中 / fallback / detach / interpolate / 各 dict key-set 完整性)。package.json:@huanlin/dsh-plugin-better-locale加为 optional peer + devDep link。AGENTS.md / README.md:文档化第三语言覆盖机制。兼容性
未安装 better-locale 时,
ctx.get('betterLocale')返回undefined,整段为 no-op;zh/en 行为完全不变。better-locale 是 optional peer(
peerDependenciesMeta.optional: true),不影响现有安装。测试
pnpm typecheck✅pnpm test -- tests/locales.spec.ts✅(含 19 语言 dict key-set 完整性断言)其他平台性失败测试(smoke/pty/sidebar-crash)为 Windows 预存问题(CRLF、pty spawning),与该 PR 无关(stash 验证 main 同样失败)。
关联
依赖插件 @huanlin/dsh-plugin-better-locale(v0.1.0 已发布):仓库
huanlinoto/dsh-plugin-better-locale,npm@huanlin/dsh-plugin-better-locale。设计文档:
dsh-plugin-better-locale/docs/plans/2026-08-23-better-locale-design.md鸣谢
俄语词典参考了 @Vladimir-Kryshchenko 在 #302 的贡献。