feat(app-iced): M120 实例页与启动阶段标签跟着界面语言走

来源:M106 r1 复审点名——中文机器上首屏(实例页)仍是英中混排(页头 / New instance /
Import / ALL INSTANCES / VERSION / Present on disk / Running · pid / Launch failed)。
用户的原话是「我系统语言是中文 为什么打开软件是英文」。

改了什么
- i18n:catalog/instances.rs 从 6 条死 key 补到 34 条(页头 / 列表列头 / 详情动作 /
  窄窗说明 / 元信息标签与值 / 隔离档位 / 运行状态 / 四个启动阶段)。族在装配链第 2 位,
  新 key 追加在本族末尾,golden 对应位置插入(不是文件末尾追加)。
- 页面:新增 pages/instances/text.rs(Texts)——页面唯一的取词入口,实例页里不再有
  任何可见英文字面量;detail / demo 也改从它取。
- 阶段标签:view/instances.rs 的 Running / Launch failed / 四阶段全部走目录;
  **数字与分隔符不随语言变形**(运行中 · pid 1234 与 Running · pid 1234 只换前半句)。
- 顺手修掉两处「语言反向泄漏」:原版徽标此前直接画 presenter 的中文「原版」(英文界面
  会漏中文),现在走 LoaderVanilla;隔离档位 isolated/shared 也从 core 的稳定 id 换成人话。
- 删掉 InstancesLastPlayed:M117 加的整句 key,从未接线,形状与「标签 + 值」的元信息卡
  不符,由 InstancesMetaLastPlayed + InstancesNeverPlayed 取代。

守门(pages/instances/tests/i18n.rs + app/view/tests.rs)
- 中文态无 ASCII 英文单词(品牌 Java / 技术标识 pid 白名单);
- 每一条 Instances* 的两套译文必须不同(切语言时真的变);
- Running 的数字与 · pid 分隔符在两套语言里逐字保留;
- 页面源码里 29 条旧英文基线不许回来;每条 key 都必须被页面引用(死 key)。

出图:DevDocs/artifacts/m120/01~12(有实例 / 空态 / 运行中 × 浅深 × 中英)。
This commit is contained in:
AskaEth committed 2026-11-05 13:36:44 +08:00
1 parent 2f491c31f9
commit 1a4e1fee12
17 files changed
+924 -119

No files matched your search

+14
View File
@@ -159,6 +159,20 @@ mod settings;
///
/// 其余各行仍逐字节等于拆分前那份快照——也就是说这张表现在证明的是「除这几条按令改过的,
/// 其余一字未动」,不再是「整表一字未动」。
///
/// ## M120 动了实例页那一族(1 条改译文 + 1 条删除 + 28 条新增)
///
/// 实例页的文案以前是英文基线字面量,M120 全搬进 `catalog/instances.rs`。那一族在装配链
/// **第 2 位**(紧跟 nav),所以这批行是**插在中间**的,不是文件末尾追加:
///
/// | 动作 | 条目 |
/// |---|---|
/// | 改译文 | [`Key::InstancesEmptyBody`](换成详情列真正画的那句) |
/// | 删除 | `InstancesLastPlayed`(M117 加的整句,从未接线;页面是「标签 + 值」的元信息卡) |
/// | 新增 | `InstancesTitle` … `InstancesStageWindow`(页头 / 动作 / 空态 / 元信息标签与值 / 隔离档位 / 运行状态 / 阶段,共 28 条) |
///
/// 位置跟着族走这个事实本身就是判据:金表是 `Key::ALL` 的逐 index 镜像,
/// 「为把新 key 排到文件末尾而去重排别人的族」会让这里整片红。
#[cfg(test)]
mod golden;
+31 -6
View File
@@ -1,7 +1,5 @@
//! 金表的**表数据**(`Key::ALL` 顺序 × (en, zh-CN) 的逐字快照)。
//!
//! 「为什么有这么一张表、它抓得住什么」写在 `catalog.rs` 中 `mod golden;` 的文档里——
//! M119 r2 把它搬到那儿,是为了给这张表腾出追加新 key 的行数(400 行硬线),一个字的说明都没删。
//! 金表的**表数据**(`Key::ALL` 顺序 × (en, zh-CN) 的逐字快照)。「为什么有这张表、它抓得住
//! 什么」全在 `catalog.rs` 的 `mod golden;` 文档里——本文件只放数据,是因为每加一条 key 就多一行。
/// 拆分前 `Key::ALL` 的顺序 × (en, zh-CN)。第一列是变体名(`Key::name()` 的返回值)。
pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
@@ -14,9 +12,36 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
("InstancesImport", "Import", "导入"),
("InstancesBack", "Back to instances", "返回实例列表"),
("InstancesPlay", "Play", "启动"),
("InstancesLastPlayed", "Last played {when}", "上次游玩 {when}"),
("InstancesEmptyTitle", "No instance selected", "未选择实例"),
("InstancesEmptyBody", "Pick an instance to see its details.", "选择一个实例查看详情。"),
("InstancesEmptyBody", "Pick an instance on the left to see its version, loader and launch options.", "在左侧选择一个实例,查看它的版本、加载器与启动选项。"),
("InstancesTitle", "Instances", "实例"),
("InstancesSubtitle", "Local versions and their mod loaders", "本地版本与它们的模组加载器"),
("InstancesAllTitle", "ALL INSTANCES", "全部实例"),
("InstancesStop", "Stop", "停止"),
("InstancesDuplicate", "Duplicate", "复制"),
("InstancesOpenFolder", "Open folder", "打开文件夹"),
("InstancesDelete", "Delete", "删除"),
("InstancesNarrowNote", "Below 840 px the list and the detail share one column, so opening an instance replaces this screen (full-page switch). Widen the window to see both panes again.", "窗口窄于 840 像素时,列表与详情共用一列:打开一个实例会整页替换这一屏(整页切换)。把窗口拉宽就能重新同时看见两栏。"),
("InstancesMetaVersion", "VERSION", "版本"),
("InstancesMetaLoader", "LOADER", "加载器"),
("InstancesMetaMemory", "MEMORY", "内存"),
("InstancesMetaJava", "JAVA", "Java"),
("InstancesMetaMods", "MODS", "模组"),
("InstancesMetaIsolation", "ISOLATION", "隔离方式"),
("InstancesMetaVersionId", "VERSION ID", "版本标识"),
("InstancesMetaFiles", "FILES", "文件"),
("InstancesMetaLastPlayed", "LAST PLAYED", "上次游玩"),
("InstancesPresentOnDisk", "Present on disk", "已在磁盘上"),
("InstancesMissing", "Missing", "缺失"),
("InstancesNeverPlayed", "Never", "从未游玩"),
("InstancesIsolationIsolated", "Isolated", "独立目录"),
("InstancesIsolationShared", "Shared", "共用目录"),
("InstancesRunning", "Running · pid {pid}", "运行中 · pid {pid}"),
("InstancesFailed", "Launch failed · {reason}", "启动失败 · {reason}"),
("InstancesStageDownload", "Downloading", "下载中"),
("InstancesStageVerify", "Verifying", "校验中"),
("InstancesStageLaunch", "Starting", "启动中"),
("InstancesStageWindow", "Waiting for window", "等待游戏窗口"),
("LoaderVanilla", "Vanilla", "原版"),
("LaunchOutcomeNormal", "Finished normally", "正常结束"),
("LaunchOutcomeCrash", "The game crashed", "游戏崩溃"),
+68 -4
View File
@@ -1,19 +1,83 @@
//! 实例页文案:页头动作、返回、上次游玩时间、空态。
//! 实例页文案:页头、列表列头、详情动作、元信息卡的标签与值、运行状态与启动阶段。
//!
//! 域文件的形状见 [`crate::catalog`] 的「域装配」一节。
//!
//! ## 这一族在装配链的**第 2 位**(M120 钉住)
//!
//! `instances_entries!` 紧跟 `nav_entries!`,所以本族的 key 落在 `Key::ALL` 的前段、
//! `LoaderVanilla` 之前。M120 的新 key 因此**追加在本域末尾**(= `InstancesEmptyBody` 之后),
//! 既没插到别的族中间,也没为了「排在文件末尾」去重排别人的族:
//! 金表([`crate::catalog::golden`])是 `Key::ALL` 的逐 index 镜像,位置跟着族走。
//!
//! ## M120 之前这七条全是**死 key**
//!
//! M117 加 `InstancesNew` / `InstancesImport` / `InstancesBack` / `InstancesPlay` /
//! `InstancesLastPlayed` / `InstancesEmptyTitle` / `InstancesEmptyBody` 时,实例页并没有接它们
//! ——页面上还是英文基线字面量(`"New instance"` / `"ALL INSTANCES"` / `"Present on disk"`…)。
//! M120 一次接完,同时:
//!
//! - `InstancesEmptyBody` 的译文换成详情列真正画的那句(原来那句是「看详情」的泛说);
//! - **`InstancesLastPlayed` 删掉**:它的形状是「上一次游玩 {when}」这种整句,而页面上是
//! 元信息卡(标签 `LAST PLAYED` + 值 `2026-10-29 19:22 UTC`,或值 `Never`)。留着它只会
//! 多出一条没人用的 key,所以拆成 [`Key::InstancesMetaLastPlayed`](标签)与
//! [`Key::InstancesNeverPlayed`](值)。
//!
//! ## 两条口径(复审会盯)
//!
//! 1. **品牌与技术标识不翻译**:`Java`(元信息标签的值域)与 `pid`(进程号)原样保留两套语言;
//! 2. **数字与分隔符不随语言变形**:[`Key::InstancesRunning`] 的中英都写成
//! `… · pid {pid}`,只有前半句换了;`{pid}` 之外一个字都不许动(`pages/instances/tests/i18n.rs`
//! 用「中英同位置取占位符 + 数字原样」的断言钉这条)。
macro_rules! instances_entries {
($next:ident, $($rest:ident,)* { $($acc:tt)* }) => {
$next! { $($rest,)* {
$($acc)*
// ── 实例页
// ── 实例页(M117 的七条:其中 `InstancesLastPlayed` 见模块文档,M120 删除)
InstancesNew => ("New instance", "新建实例"),
InstancesImport => ("Import", "导入"),
InstancesBack => ("Back to instances", "返回实例列表"),
InstancesPlay => ("Play", "启动"),
InstancesLastPlayed => ("Last played {when}", "上次游玩 {when}"),
InstancesEmptyTitle => ("No instance selected", "未选择实例"),
InstancesEmptyBody => ("Pick an instance to see its details.", "选择一个实例查看详情。"),
InstancesEmptyBody => ("Pick an instance on the left to see its version, loader and launch options.", "在左侧选择一个实例,查看它的版本、加载器与启动选项。"),
// ── 页头与列表列头(M120)
InstancesTitle => ("Instances", "实例"),
InstancesSubtitle => ("Local versions and their mod loaders", "本地版本与它们的模组加载器"),
InstancesAllTitle => ("ALL INSTANCES", "全部实例"),
// ── 详情动作(M120)
InstancesStop => ("Stop", "停止"),
InstancesDuplicate => ("Duplicate", "复制"),
InstancesOpenFolder => ("Open folder", "打开文件夹"),
InstancesDelete => ("Delete", "删除"),
InstancesNarrowNote => (
"Below 840 px the list and the detail share one column, so opening an instance replaces this screen (full-page switch). Widen the window to see both panes again.",
"窗口窄于 840 像素时,列表与详情共用一列:打开一个实例会整页替换这一屏(整页切换)。把窗口拉宽就能重新同时看见两栏。"
),
// ── 元信息卡的标签(M120;`Java` 是品牌名,两套语言都写 Java)
InstancesMetaVersion => ("VERSION", "版本"),
InstancesMetaLoader => ("LOADER", "加载器"),
InstancesMetaMemory => ("MEMORY", "内存"),
InstancesMetaJava => ("JAVA", "Java"),
InstancesMetaMods => ("MODS", "模组"),
InstancesMetaIsolation => ("ISOLATION", "隔离方式"),
InstancesMetaVersionId => ("VERSION ID", "版本标识"),
InstancesMetaFiles => ("FILES", "文件"),
InstancesMetaLastPlayed => ("LAST PLAYED", "上次游玩"),
// ── 元信息卡的值(M120)
InstancesPresentOnDisk => ("Present on disk", "已在磁盘上"),
InstancesMissing => ("Missing", "缺失"),
InstancesNeverPlayed => ("Never", "从未游玩"),
// 隔离档位的两个稳定 id(`core::game::IsolationMode::as_str`)→ 人话。
// 白名单只覆盖真实存在的这两档;`inherit` / `custom` / 未知值原样上屏(不猜)。
InstancesIsolationIsolated => ("Isolated", "独立目录"),
InstancesIsolationShared => ("Shared", "共用目录"),
// ── 运行状态与启动阶段(M120;数字与分隔符不随语言变形)
InstancesRunning => ("Running · pid {pid}", "运行中 · pid {pid}"),
InstancesFailed => ("Launch failed · {reason}", "启动失败 · {reason}"),
InstancesStageDownload => ("Downloading", "下载中"),
InstancesStageVerify => ("Verifying", "校验中"),
InstancesStageLaunch => ("Starting", "启动中"),
InstancesStageWindow => ("Waiting for window", "等待游戏窗口"),
} }
};
}
+4 -2
View File
@@ -17,9 +17,11 @@ const PARTIAL_ZH: &[(Key, &str)] = &[
(Key::InstancesImport, "导入"),
(Key::InstancesBack, "返回实例列表"),
(Key::InstancesPlay, "启动"),
(Key::InstancesLastPlayed, "上次游玩 {when}"),
(Key::InstancesEmptyTitle, "未选择实例"),
(Key::InstancesEmptyBody, "选择一个实例查看详情。"),
(
Key::InstancesEmptyBody,
"在左侧选择一个实例,查看它的版本、加载器与启动选项。",
),
(Key::LoaderVanilla, "原版"),
(Key::LaunchOutcomeNormal, "正常结束"),
(Key::LaunchOutcomeCrash, "游戏崩溃"),