Files
Unlucky-Launcher/crates/i18n/src/catalog/launch.rs
T
AskaEth 03741ecd2d fix(m161): 收更新键/按钮/矮窗口/启动错误/导入结果五笔债
① update.auto_check / update.channel 登记进 core setting schema(1.6.0)
   - 新增 setting/keys/update.rs(两键 + UPDATE_CHANNELS,只允许 stable);
     SettingSchema 加 with_all 供域键表批量登记。
   - 新增 setting/update_prefs.rs:cache/update/prefs.json → launcher.json 的一次性迁移。
     四条硬约束:源指纹闸门(幂等)、不丢 false、新值胜出、旧文件改名 .migrated 后不再被读;
     主配置不可写时不动旧文件。收据 config/update-prefs-migration.json。
   - presenter Runtime 建会话时迁一次并把结局留在 migration();prefs 字段换成
     auto_check + 每次派发从主配置读 channel(不再硬编码 Channel::Stable)。
     保留旧字段 auto_check 的真实来源(原有测试 cases 会断言)。
   - CLI config get/set/dump 先跑同一次迁移(幂等),输出里给 migration 段与收据路径。

② presenter/dto/events.rs 的「本次会话不再弹提示条」注释改成真实语义
   (记的是版本号:同版本压住、更高版本照弹、手动检查清掉)。

③ 检查/下载进行中按钮禁用:pages/update/busy.rs 的 busy/can_check/can_apply;
   设置页两颗按钮改画禁用(不是消失),app 层 on_update_action 再挡一道
   (忙碌时 CheckNow/Apply 不派发);新增两条用例(含「忙完恢回可点」)。

④ 内容库低高度:content_layout::MIN_BODY_HEIGHT=460 + BodyMode(按固定件+三整行算出来,
   用例守着算式);frame::body_height 从 Ui::metrics 算正文可用高,pages::Model 带 window_height。
   ≥460 列表自己滚;<460 主列整列一个滚动条、列表按自然高度铺开。

⑤ 启动错误文案本地化:presenter 删掉 launch_summary / 「启动失败:」前缀 / 五条中文阶段前缀,
   改发 LaunchFailureView{stage,detail};LaunchFinished 改带 exit_code/uptime_ms/failure,
   Toast 由 app 层按 i18n key 现求(与 install_cancelled 同构)。InstancesFailed 拆成
   InstancesFailedStage(列表单行)+ LaunchStageFailed(详情/Toast 全文)。

⑥ 导入结果块:ImportReportView 加 failure_stage(NotStarted/RolledBack/RollbackIncomplete,
   由 core 的 rollback 机器位推出);标题、图标、底色三处分档,预检失败不再说「已回滚」。

顺带:六处注释/文档漂移(update.rs 的分工表与偏好落点、pack 的「已整包回滚」、
build_request 的 Errors、settings/update 的按钮禁用说明等),
以及为守 400 行把 update/cli-config/core-keys/presenter-dto/presenter-launch/i18n-golden
里贴线或越线的文件按模块拆开(纯搬移,行为不变)。
2026-11-07 15:02:13 +08:00

71 lines
4.4 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 启动结局文案:一句话 = 一个 key(原来 UI 把 `"Launch failed"` 与 core 的「静默失败」拼成一句话)。
//!
//! 域文件的形状见 [`crate::catalog`] 的「域装配」一节。
macro_rules! launch_entries {
($next:ident, $($rest:ident,)* { $($acc:tt)* }) => {
$next! { $($rest,)* {
$($acc)*
// ── 启动结局(原来 UI 把 "Launch failed" 与 core 的「静默失败」拼成一句话,现在一句话 = 一个 key)
LaunchOutcomeNormal => ("Finished normally", "正常结束"),
LaunchOutcomeCrash => ("The game crashed", "游戏崩溃"),
LaunchOutcomeSilent => (
"Suspected silent failure: exit code 0, but the game never really started",
"疑似静默失败:退出码 0,但游戏没真正跑起来"
),
LaunchFailedWithCode => ("Launch failed (exit {code}): {reason}", "启动失败(退出码 {code}):{reason}"),
// M161:启动失败的**阶段**词表。presenter 只给稳定 slug
// (`LaunchFailureStage`),界面在这里选词——此前这些前缀是 presenter 里拼的中文
// (「读版本 JSON 失败」「隔离目录派生失败」…),英文界面上原样露出来。
LaunchStageVersionManifest => ("Reading the version file", "读版本文件"),
LaunchStageInheritance => ("Resolving the inheritance chain", "解析继承链"),
LaunchStageInstanceConfig => ("Reading the instance settings", "读实例设置"),
LaunchStageIsolation => ("Preparing the isolated game folder", "准备隔离游戏目录"),
LaunchStageIdentity => ("Preparing the account", "准备账户"),
LaunchStageSpawn => ("Starting the game process", "启动游戏进程"),
LaunchStageFailed => ("Launch failed · {stage}: {detail}", "启动失败 · {stage}:{detail}"),
LaunchToastEnded => ("{outcome} · {seconds}s", "{outcome} · {seconds} 秒"),
// M117:微软轨的 client id 没配是**配置缺失**,不是「本期未支持」。这句话是那条
// 启动失败文案的**双语口径**(真源在 `core::auth::microsoft` 的
// `MISSING_CLIENT_ID_MESSAGE`,中文逐字一致;英文这条给 En 界面用)。
// 判据:中英都点名 `ULL_MSA_CLIENT_ID` 并给出构建期注入这条路,且**不许**出现
// 「unsupported / 未支持」——用户实跑就是被那句误导读成「功能没做」。
LaunchMsaNotConfigured => (
"Microsoft sign-in is not configured: it needs an Azure public client id (the login flow itself is implemented). Build with ULL_MSA_CLIENT_ID=<id>, or set that environment variable before launching.",
"微软登录未配置:缺少 Azure 公共客户端 id(登录功能已实现,只差这一项配置)。构建时注入:ULL_MSA_CLIENT_ID=<id> cargo build;或启动前设置同名环境变量 ULL_MSA_CLIENT_ID=<id>。"
),
} }
};
}
pub(crate) use launch_entries;
#[cfg(test)]
mod tests {
use crate::{Catalog, Key, Lang};
#[test]
fn msa_not_configured_copy_is_accurate_in_both_languages() {
// 抓得住:文案退回「本期未支持」这类说法(M117 用户实跑踩到的原 bug),
// 以及两条译文只剩一句「需要 id」却不给怎么配。
// 抓不住:读起来顺不顺——那要靠 review 与截图。
let en = Catalog::of(Lang::En).text(Key::LaunchMsaNotConfigured);
let zh = Catalog::of(Lang::ZhCn).text(Key::LaunchMsaNotConfigured);
for (tag, text) in [("en", en), ("zh-CN", zh)] {
assert!(text.contains("ULL_MSA_CLIENT_ID"), "{tag}: {text}");
}
assert!(en.contains("client id"), "{en}");
assert!(en.contains("not configured"), "{en}");
assert!(!en.to_lowercase().contains("unsupported"), "{en}");
assert!(!en.to_lowercase().contains("not implemented"), "{en}");
assert!(zh.contains("客户端 id"), "{zh}");
assert!(zh.contains("未配置"), "{zh}");
assert!(!zh.contains("未支持"), "{zh}");
assert!(!zh.contains("未实现"), "{zh}");
// 硬约束:词条里只许出现 `<id>` 占位,不出现真 id(repo 任何文件都不许带)。
assert!(en.contains("<id>") && zh.contains("<id>"));
}
}