panatgithub_AnkiHeadingSync/docs/i18n-decisions.md
Dusk 67854cf154 feat: implement full bilingual i18n and structured error rendering
- 新增完整双语 i18n 支持,支持按 Obsidian 语言自动切换
- 实现结构化 warning / user error 渲染
- Added full bilingual i18n support with automatic switching based on Obsidian language settings
- Implemented structured warning and user error rendering
2026-04-21 13:34:27 +08:00

3 KiB
Raw Blame History

i18n Decisions

1. 实现入口

本轮继续沿用现有分层,不做额外框架化改造:

  1. src/presentation/i18n/ 放 locale、消息字典、t()formatList()
  2. 展示层入口继续是 AnkiHeadingSyncPluginregisterCommandsPluginSettingTabEmptyDeckSelectionModalNoticeService
  3. 结构化用户错误定义放在 src/application/errors/,供 application / presentation 共用。

2. locale 策略

  1. 运行时唯一来源是 obsidian.getLanguage()
  2. 仅当返回值严格等于 zh 时使用简体中文。
  3. 其他所有语言码都回退到英文,包括 enen-GBjazh-TW
  4. 不缓存 locale 常量;t()renderUserMessage() 每次调用都重新解析当前语言。

3. message 结构

按计划固定以下 key 分组:

  1. commands.*
  2. settings.*
  3. modal.emptyDeck.*
  4. notice.*
  5. errors.*
  6. warnings.deck.*

zh.ts 通过 satisfies typeof en 约束字典 shape避免漏 key。

4. 用户错误模型

  1. 新增 PluginUserError,仅承载 keyparams
  2. 新增 isPluginUserError()renderUserMessage()
  3. 插件自有、会冒泡到 Notice/UI 的错误统一抛 PluginUserError
  4. 未结构化的第三方或底层异常继续允许透传 error.message 作为诊断信息。

5. warning / failure 结构

  1. DeckResolutionWarning 改为 { filePath, code, params? }
  2. getDeckResolutionWarningKey() 使用 filePath + code + stable(params) 去重,不再依赖最终展示文案。
  3. deck 相关领域服务只输出 warning code/params最终显示由 NoticeService 渲染。
  4. clear/reset/write-back 类失败项也改为结构化 code + params,避免 lower layer 直接生成最终字符串。

6. 设置页集成方式

  1. 保持现有 imperative render不引入新的设置元描述层。
  2. 所有标题、说明、按钮、状态文案、preview、dropdown label、scope 文案、aria-label 直接切到 t()
  3. 动态状态统一改成 key + params而不是继续内联拼接。
  4. note type、field name、deck name、folder path 等业务数据原样透传,不做翻译。

7. 仓库兼容性偏差

相对草案,采用以下更贴合仓库的落地方式:

  1. PluginUserError 放在 application 层而不是 presentation 层,因为 validatePluginSettings()ManualSyncServiceNoteFieldMappingService 都在 application。
  2. NoticeService 负责 summary、warning 列表和结构化 failure 的最终格式化,避免在 plugin 主类里重复拼接。
  3. pluginState 中持久化的 deckWarnings 直接升级为结构化 payload不做兼容旧 message 字段的额外迁移逻辑,因为本任务明确不要求 settings schema 迁移,且 warning 不属于设置 schema。

8. 验证策略

  1. 先做 locale / i18n 单测,确保基础设施稳定。
  2. 再补 settings / modal / notice 的双语表现测试。
  3. 最后更新 error / warning / persistence 相关测试,跑完整 npm testnpm run buildnpm run lint