ADR-0001: 界面中英文切换方案

历史参考:本篇记录旧 GUI(tod/gui/)时代的决策,已被 ADR-0007(大爆炸替换)与 ADR-0014(UI 迁移到 Tauri)取代,仅作历史参考,不再指导现行实现。

状态

已接受

上下文

本项目为 PyQt6 桌面应用,目标用户为中文航天研究人员。自创建以来,所有 GUI 文本、脚本描述、用户文档均为中文硬编码。随着用户群体扩大,需要提供英文界面支持。

约束条件:

  • 必须保持向后兼容,现有中文用户无感知

  • 技术栈为 PyQt6,不可引入重型 Web 框架

  • GUI 文本、脚本描述/help 文本、Sphinx 用户文档均需提供英文版

  • 维护者自行承担翻译工作

决策

采用三套机制并行的方案:

内容类型

机制

源文件

运行时行为

GUI 文本

PyQt6 QTranslator + .ts → .qm

tod/gui/i18n/gui.en.ts

启动时按配置加载对应 .qm,tr() 自动拦截替换

脚本描述/help

自定义 JSON 翻译表

tod/gui/i18n/scripts.en.json

启动时加载 JSON,脚本注册时按语言查表替换

Sphinx 用户文档

Sphinx 标准 gettext/sphinx-intl

docs/source/ 中文 .rst 为源

构建时按 language 配置生成对应语言版本

关键设计选择:

  1. 源语言为中文:代码中 tr() 包裹中文文本,从中文翻译到英文。这与大多数项目(英文为源)相反,但符合本项目历史(全中文起步)和主要用户群。

  2. 两套翻译机制并存而非统一:GUI 文本用 Qt 原生 QTranslator,脚本描述用自定义 JSON。三套内容的形态不同(框架控件 / 运行时字符串 / 静态文档),强求统一机制反而增加复杂度。Qt 翻译器对控件布局自适应、快捷键处理有原生支持,不可替代。

  3. 重启生效,非热切换:热切换需遍历所有控件重新设置文本,参数面板动态生成处理尤其复杂。科研工具切换语言的频率极低,重启生效成本可忽略。

  4. 翻译缺失回退到中文:科研工具的可理解性优先于翻译完整性。缺失翻译时用户至少能读懂。

  5. 动态文本用 %1/%2 占位符:f-string 无法被 pylupdate6 提取,需改写为 Qt 占位符格式 self.tr("任务 %1 完成").arg(job_id)。

  6. 预留多语言扩展:文件命名采用 gui.<lang>.ts / scripts.<lang>.json 格式,语言配置读取自 gui_defaults.json 的 settings.language,未设置时默认 "zh"。

后果

正面

  • GUI 文本翻译利用 PyQt 原生机制,对控件布局、快捷键、文本方向等处理最可靠

  • 脚本描述 JSON 表与 SCRIPT_ENTRY 结构天然对齐,维护直观

  • Sphinx 标准 gettext 与 GUI 方案源语言中文配合提取翻译思路一致

  • 默认中文,现有用户完全无感知

负面

  • 大规模代码改动:所有 GUI 文件中的硬编码中文需替换为 self.tr("..."),约 15-20 个文件受影响

  • 动态文本需改写:所有 f-string / .format() 格式化的中文文本需改为 %1 占位符形式

  • 现有英文文本需逆向翻译:代码中已有的英文(如 "Copy All")在中文版中需通过 .qm 翻译为中文,实现统一

  • 两套翻译文件需分别维护:.ts 走 Qt Linguist 工具链,.json 手动编辑

备选方案

方案

未选原因

统一用 gettext/babel

PyQt GUI 文本需手动调用翻译函数,失去控件布局自适应等原生支持

纯自定义 JSON 字典

完全自研,工作量更大,无法利用 Qt Linguist 可视化翻译

运行时热切换

动态参数面板刷新逻辑过于复杂,收益与成本不成正比

英文作为源语言

需先将全部中文重构为英文,再翻译回中文,改动量翻倍

实施状态与覆盖边界

截至 issue #190 / #234,三套机制的落地状态如下:

  • GUI 文本:主要界面文本已通过 tod/gui/i18n/gui.en.ts 与编译后的 gui.en.qm 覆盖。运行时按 gui_defaults.json 的 settings.language 加载对应 Qt 翻译文件;未设置时默认中文。

  • 脚本描述/help:tod/gui/i18n/scripts.en.json 当前翻译数据仅填充脚本 description。翻译加载代码已支持 group_label、cli_params、env_params 的 label / help 字段,但这些字段的英文数据尚未全量补齐;缺失翻译时继续显示中文源文本。

  • Sphinx 用户文档:文档国际化基础设施已采用 Sphinx gettext / sphinx-intl。中文 .rst / .md 为源文档,英文 .po 位于 docs/source/locale/en/LC_MESSAGES/,初始条目可以保持空 msgstr;未翻译条目在英文构建中回退显示中文源文。

  • API 参考正文:Sphinx gettext 会处理整棵 docs/source/ 文档树,因此英文 .po 中可能出现 API .rst 壳文件文本,也可能出现 autodoc 从 Python docstring 动态生成的正文。当前工作只落地可维护的翻译基础设施,不承诺完成 API 正文英文翻译;缺失翻译时仍以中文 docstring 为源文回退显示。API 参考正文的术语梳理和英文翻译需作为后续独立工作处理。