# CodePlanet 界面国际化维护说明

本文说明中英文界面切换的实现方式、日常维护步骤与常见问题。源语言为**简体中文**，英文通过 Qt 官方 `QTranslator` + `.ts`/`.qm` 提供。

## 架构概览

```
用户：工具 → 语言 → 中文 / English
        ↓
Application::setLocale("zh_CN" | "en")
        ↓
  zh_CN：removeTranslator
  en   ：load codeplanet_en.qm → installTranslator
        ↓
notifyLanguageChange() → 各控件 changeEvent(LanguageChange) → retranslateUi()
```

| 组件 | 职责 |
|------|------|
| `Application` | 安装/卸载翻译器、广播 `LanguageChange`、持久化 `ui/locale` |
| `resources/translations/codeplanet_en.ts` | 翻译源（lupdate 生成/更新） |
| `resources/translations/codeplanet_en.qm` | 运行时英文包（lrelease 编译） |
| `bin/translations/codeplanet_en.qm` | 发布副本（构建或 `generate_i18n.bat` 复制） |
| 各 GUI 控件 | `tr("中文")` + `retranslateUi()` |

## 相关文件

| 路径 | 说明 |
|------|------|
| `src/services/UiLocaleService.{h,cpp}` | `setLocale`、`applyStoredLocale`、`applySessionLocale`（子进程） |
| `src/editor/Application.{h,cpp}` | Ops `setLocale`、`applyStoredLocale` |
| `src/runtime/RuntimeMainWindow.cpp` | Runtime 界面 `tr()` + `retranslateUi()`；由 Launcher 传入 `--locale=en` 时英文生效（如「Mock 硬件触发 camA」→ `codeplanet_en.ts`） |
| `src/launcher/LauncherService.cpp` | 启动 Runtime 时附加 `--locale=` |
| `src/editor/MainWindow.cpp` | 主界面创建后调用 `applyStoredLocale()` |
| `src/gui/widgets/codeeditorwidget2.cpp` | 语言菜单、`retranslateUi()` |
| `src/gui/widgets/*` | 查找替换、参数、图片等子控件 |
| `src/gui/editor/codeeditor.{h,cpp}` | 行列状态栏文案 |
| `scripts/generate_i18n.bat` | `lrelease` 并复制到 `bin/translations/` |
| `scripts/update_i18n_ts.bat` | `lupdate` 从源码刷新 `.ts` |
| `src/editor/editor.pro` | 存在 `.qm` 时构建后复制到 `bin/translations/` |

## 日常维护流程

### 1. 新增或修改界面文案

1. 在代码中使用 **`tr("中文源文")`**，类需带 `Q_OBJECT`。
2. 固定不翻译的标签（如语言名「中文」）使用：
   ```cpp
   QString::fromUtf8(u8"中文");
   ```
   不要用 `QStringLiteral("中文")`（MSVC 下可能乱码）。
3. 在控件中实现：
   - `void retranslateUi();`
   - `changeEvent()` 中处理 `QEvent::LanguageChange` 并调用 `retranslateUi()`。
4. 构造函数末尾调用一次 `retranslateUi()`。

### 2. 更新翻译表

```bat
REM 1. 从源码提取新字符串到 .ts
scripts\update_i18n_ts.bat

REM 2. 用 Qt Linguist 编辑 resources\translations\codeplanet_en.ts 中的英文

REM 3. 编译 .qm 并复制到 bin
scripts\generate_i18n.bat
```

`generate_i18n.bat` 内 Qt 路径默认为 `D:\Qt\Qt5.11.1\5.11.1\msvc2017_64\bin`，若本机不同请修改脚本中的 `LRELEASE` / `LUPDATE`。

### 3. 构建与发布

- 执行 **qmake** 后编译；若 `resources/translations/codeplanet_en.qm` 存在，`editor.pro` 会自动复制到 `bin/translations/`。
- 发布安装包时需包含 **`translations/codeplanet_en.qm`**（与 `CodeEditor.exe` 同级的 `translations` 子目录，或依赖工程目录下的 `resources/translations/` 路径）。

## 编码与 MSVC 注意事项

- MSVC：`src/editor/editor.pro` 已全局启用 `/utf-8`；源码 UTF-8 保存；**已移除** `#pragma execution_character_set`（二者不可同时使用）。
- 若出现 **C4819**：确认文件为 UTF-8；AST 模块错误信息使用英文 ASCII 字面量。
- 语言菜单项「中文」使用 `QString::fromUtf8(u8"中文")`，不经过 `tr()`。

## 用户可见行为

- **中文**：卸载翻译器，显示 `tr()` 源文。
- **English**：加载 `codeplanet_en.qm`；若加载失败，`qWarning` 输出路径且界面保持中文。
- 上次选择的语言保存在数据库键 **`ui/locale`**（`DatabaseService`，与 Ops 共用）；Launcher 首次启动默认 **English**，Ops 首次启动默认 **中文**。
- Launcher 窗口右上角 **CH/EN 图标**切换语言（显示当前语言）；与 Ops「工具 → 语言」写入同一 `ui/locale`。
- **Runtime**：Launcher 点击「立即启动」时通过命令行 **`--locale=zh_CN|en`** 传入当前界面语言；Runtime 使用 `UiLocaleService::applySessionLocale` **只读应用、不回写** `ui/locale`，进程存活期间不受 Launcher 后续切换影响。

## 尚未国际化的范围

以下仍为硬编码中文或英文，后续可按同样模式扩展：

- Runtime / Launcher 日志区 `[main]`、`[runtime]` 等运行消息（ intentionally ASCII 便于 grep）
- 格式检查/调试表格中的运行时消息（`codeeditorwidget2.cpp` 内拼接字符串）
- 部分调试日志与 `qDebug` 输出
- 插件与 `FunctionLib.ini` 中的函数描述

## 新增一种语言（扩展参考）

1. 复制 `codeplanet_en.ts` 为 `codeplanet_xx.ts`，翻译后 `lrelease` 得到 `.qm`。
2. 在 `Application::setLocale` 中增加 locale 分支与加载路径。
3. 在语言菜单增加对应 `QAction`。
4. 更新 `scripts/generate_i18n.bat`（或增加并行脚本）与 `editor.pro` 复制规则。

## 故障排查

| 现象 | 处理 |
|------|------|
| 选 English 仍为中文 | 确认 `bin/translations/codeplanet_en.qm` 或 `resources/translations/codeplanet_en.qm` 存在；查看控制台 `Failed to load English translation` |
| 「中文」菜单乱码 | 确认使用 `QString::fromUtf8(u8"中文")`，勿用 `QStringLiteral("中文")` |
| 编译 C3437 | `/utf-8` 与 `#pragma execution_character_set` 冲突；工程已统一用 `/utf-8`，pragma 已全部删除 |
| lrelease 找不到 | 使用完整路径或 `.\lrelease.exe`（PowerShell 当前目录执行） |

---

维护者请在修改界面文案或 locale 逻辑后，同步检查本文与 `docs/开发指南.md` 中的「国际化」小节。
