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
里贴线或越线的文件按模块拆开(纯搬移,行为不变)。
This commit is contained in:
AskaEth committed 2026-11-07 15:02:13 +08:00
1 parent b2d9f3927f
commit 03741ecd2d
69 files changed
+2653 -707

No files matched your search

+20
View File
@@ -292,6 +292,26 @@ macro_rules! content_entries {
"路径过不了包内规整,已跳过"
),
PackReasonUnreadable => ("cannot read it, skipped", "读不出来,已跳过"),
// --- M161:导入结果的两种失败**不许共用一句话** ---
// 「预检没通过(一个字节都没写)」与「写进去之后回滚完成」是两件事:
// 前者用户去修包/修配置再试,后者说明已经动过目标目录。此前两者共用
// `PackStatusFailed`("Import failed — rolled back"),预检失败时那句话是假的。
PackStatusFailedNotStarted => (
"Import failed — nothing was written",
"导入失败 —— 还没写任何文件"
),
PackStatusFailedIncomplete => (
"Import failed — rollback did not finish",
"导入失败 —— 回滚没做完"
),
PackFatalTitleNotStarted => (
"Preflight failed — nothing was written",
"预检未通过 —— 一个字节都没写"
),
PackFatalTitleIncomplete => (
"Rollback did not finish — the target folder may differ",
"回滚没做完 —— 目标目录可能与导入前不同"
),
} }
};
}
+8 -4
View File
@@ -35,7 +35,7 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
("InstancesIsolationIsolated", "Isolated", "独立目录"),
("InstancesIsolationShared", "Shared", "共用目录"),
("InstancesRunning", "Running · pid {pid}", "运行中 · pid {pid}"),
("InstancesFailed", "Launch failed · {reason}", "启动失败 · {reason}"),
("InstancesFailedStage", "Launch failed · {stage}", "启动失败 · {stage}"),
("InstancesStageDownload", "Downloading", "下载中"),
("InstancesStageVerify", "Verifying", "校验中"),
("InstancesStageLaunch", "Starting", "启动中"),
@@ -59,17 +59,21 @@ pub(super) const GOLDEN: &[(&str, &str, &str)] = &[
("InstancesLaunchReset", "Reset to global", "恢复跟随全局"),
];
/// 金表的**全量**行(前半段在本文件、后半段在 [`tail`],顺序即 `Key::ALL`)。
/// 金表的**全量**行(三段:本文件 + [`tail`] + [`tail2`],顺序即 `Key::ALL`)。
///
/// 拆成两段只为守 400 行硬线(M157 加了 19 行启动参数文案后越线);对调用方是**一条**序列,
/// `catalog/tests.rs` 的逐字节断言不用关心分段。
pub(super) fn rows() -> impl Iterator<Item = &'static (&'static str, &'static str, &'static str)> {
GOLDEN.iter().chain(tail::ROWS.iter())
GOLDEN
.iter()
.chain(tail::ROWS.iter())
.chain(tail2::ROWS.iter())
}
/// 金表总行数(`Key::ALL` 的条数)。
pub(super) fn len() -> usize {
GOLDEN.len() + tail::ROWS.len()
GOLDEN.len() + tail::ROWS.len() + tail2::ROWS.len()
}
mod tail;
mod tail2;
+8 -208
View File
@@ -3,13 +3,20 @@
//! 为什么拆:`golden.rs` 在 M157 加了 19 行启动参数文案后到 416 行,越过 400 行硬线;
//! 拆分口径与仓库其它 `-p1/-p2` 一致——**纯搬移、一行不改**,顺序即 `Key::ALL` 的后半段。
//! 拼装与断言在 `golden.rs` 的 [`rows`] 与 `catalog/tests.rs`。
pub(super) const ROWS: &[(&str, &str, &str)] = &[
("LoaderVanilla", "Vanilla", "原版"),
("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}"),
("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} 秒"),
("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>。"),
("FontCjkNeedsDownload", "No Chinese font found on this system. Download an open-source (OFL) Chinese font?", "系统里没找到中文字体。要下载一套开源(OFL)中文字体吗?"),
("FontCjkDownloading", "Downloading Chinese font… {percent}%", "正在下载中文字体… {percent}%"),
@@ -112,8 +119,6 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("AgentSubtitleReal", "Conversation", "会话"),
("AgentPlaceholderReal", "Message the assistant…", "给助手发消息…"),
("AgentEmptyBodyReal", "Ask about instances, downloads or logs.", "可以问实例、下载或日志。"),
// ── M106 `I18NFOLLOW`:General 分组真控件(语言选择器 + 其余三行)。**只追加在链尾**,
// 上一行到 `LogsEmptyAction` 的既有顺序一字未动(金表要证明的正是这件事)。
("SettingsLanguageFollowSystem", "Follow system", "跟随系统"),
("SettingsLanguageZhCn", "Chinese (Simplified)", "简体中文"),
("SettingsLanguageEn", "English", "英文"),
@@ -136,7 +141,6 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("SettingsOverridesEmptyBody", "Overrides let one instance keep its own Java runtime, memory or JVM flags while the rest of the launcher keeps the defaults above.", "逐实例覆盖让某个实例保留自己的 Java 运行时、内存或 JVM 参数,其余实例沿用上面的默认值。"),
("SettingsOverridesAdd", "Add override", "新增覆盖"),
("AgentFallbackBody", "The assistant page is not built yet. Chat lives in the docked panel once the AI mission lands; this screen is the M68 skeleton fallback.", "助手页还没做。AI 接线落地后对话会出现在右侧停靠面板;这一屏是 M68 的骨架回退。"),
// --- M107 版本管理页(追加在链尾:`Key::ALL` 顺序 = 金表顺序) ---
("VersionRailTitle", "Version type", "版本类型"),
("VersionMajorTitle", "Major version", "主版本"),
("VersionMajorAll", "All versions", "全部版本"),
@@ -147,11 +151,9 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("VersionSearchEmptyBody", "Try a shorter piece of the number — 1.21, 24w, a1.", "试试更短的片段 — 1.21、24w、a1。"),
("VersionSearchElsewhere", "{count} versions match, but they are in another type.", "有 {count} 个版本匹配,但它们在别的类型里。"),
("VersionSearchElsewhereAction", "Show all types", "看全部类型"),
// --- M107 r2(追加在末尾:`Key::ALL` 顺序 = 金表顺序) ---
("VersionSearchHitsOne", "1 match", "1 个匹配"),
("VersionSearchElsewhereTitle", "Found in another type", "在别的类型里找到了"),
("VersionSearchElsewhereOne", "1 version matches, but it is in another type.", "有 1 个版本匹配,但它在别的类型里。"),
// --- M109 内容库页(同样追加在链尾:`Key::ALL` 顺序 = 金表顺序) ---
("ContentTitle", "Content", "内容库"),
("ContentSubtitle", "Modpacks, mods, resource packs and shaders", "整合包、Mod、资源包与光影"),
("ContentSectionVersions", "Version management", "版本管理"),
@@ -206,206 +208,4 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("PackDismiss", "Dismiss", "关闭"),
("PackTargetLabel", "Install into", "装到实例"),
("PackTargetNew", "New instance", "新建实例"),
("PackInstanceName", "Instance name", "实例名"),
("PackStageLine", "Step {index}/{total} · {stage}", "步骤 {index}/{total} · {stage}"),
("PackStageProbe", "Reading the manifest", "读取清单"),
("PackStageExtract", "Unpacking overrides", "解包覆盖内容"),
("PackStageFetch", "Fetching missing files", "补下载文件"),
("PackStageCommit", "Writing files", "落地写盘"),
("PackStageRegister", "Registering the instance", "登记实例"),
("PackProbeTitle", "This pack is almost a known format", "这个包差一点就是已知格式"),
("PackProbeLooksLike", "Looks like {format}, but missing: {missing}", "看起来像 {format},但缺:{missing}"),
("PackProbeUnknown", "No known format claims this pack", "没有任何已知格式认领这个包"),
("PackProbeSaw", "Found in the pack: {saw}", "包里看到:{saw}"),
("PackProbeNothing", "nothing recognisable", "没有可识别的东西"),
("PackStatusSuccess", "Imported", "已导入"),
("PackStatusPartial", "Imported with gaps", "导入完成,但有缺口"),
("PackStatusFailed", "Import failed — rolled back", "导入失败 —— 已整包回滚"),
("PackReportWritten", "Files written: {count} · {bytes}", "{count} 个文件已写盘 · {bytes}"),
("PackReportMissing", "Could not fetch (tolerated): {count}", "有 {count} 个文件没搞到(可容忍)"),
("PackReportConflicts", "Conflicts: {count}", "冲突:{count} 个"),
("PackReportRejected", "The client does not support these: {count}", "这些组件客户端不支持:{count} 个"),
("PackReportRejectedNote", "not supported by the client", "客户端不支持"),
("PackCancelled", "Import keeps running in the background — this result is discarded. Files already written stay.", "导入会在后台继续跑完 —— 本次结果作废;已经写下的文件会留下。"),
("PackOverwriteAction", "Re-import, the pack wins", "以包为准重新导入"),
("PackOverwriteNote", "Keeping both (renamed) is not supported yet: for each existing file you pick either “keep” or “overwrite”.", "「两者都留(改名)」暂不支持:每个已存在的文件只能选「保留」或「覆盖」。"),
("PackMissingOffline", "offline import", "离线导入"),
("PackMissingNoSource", "no download source available yet", "暂时拿不到下载地址"),
("PackMissingFetchFailed", "download failed: {detail}", "下载失败:{detail}"),
("PackFatalTitle", "Rolled back — nothing was left behind", "已回滚 —— 目标目录零残留"),
("PackFatalHint", "What to try next", "下一步可以试"),
("PackConflictUserModified", "you changed it", "你改过"),
("PackConflictUserDeleted", "you deleted it", "你删过"),
("PackConflictPreExisting", "was already there", "本来就在"),
("PackChoiceKeepUser", "kept yours", "保留我的"),
("PackChoiceOverwrite", "pack version used", "用包里的"),
("PackConflictHashes", "pack {pack} · base {base} · disk {disk}", "包内 {pack} · 基线 {base} · 磁盘 {disk}"),
("PackConflictDetail", "Hashes", "三方哈希"),
("PackPickTitle", "Before importing: {count} files already exist with different content", "导入前:有 {count} 个文件已存在且内容不同"),
("PackPickSummary", "Keep {keep} · overwrite {overwrite} · overwriting discards {bytes}", "保留 {keep} · 覆盖 {overwrite} · 覆盖将丢弃 {bytes}"),
("PackPickKeepAll", "Keep all mine", "全部保留我的"),
("PackPickOverwriteAll", "Overwrite all", "全部覆盖"),
("PackPickRowKeep", "Keep", "保留"),
("PackPickRowOverwrite", "Overwrite", "覆盖"),
("PackPickPage", "Items {from}-{to} of {total}", "第 {from}-{to} 项,共 {total} 项"),
("PackPickPrev", "Previous", "上一页"),
("PackPickNext", "Next", "下一页"),
("PackPickConfirm", "Import with these choices", "按这些选择导入"),
("PackPickCancel", "Cancel import", "取消导入"),
("PackPickDefaultNote", "Anything you do not change stays as you have it: file content is only replaced where you pick “Overwrite”.", "没有改动的一律按「保留」:只有你点了「覆盖」的文件才会被包内内容替换。"),
("PackPickUnknownRemote", "{count} remote entries only learn their path after download; they follow “keep”.", "还有 {count} 条远端条目要下载后才知道路径,一律按「保留」处置。"),
("PackPickSourceOverrides", "in the pack (overrides/)", "包内 overrides/"),
("PackPickSourceClientOverrides", "in the pack (client-overrides/)", "包内 client-overrides/"),
("PackPickSourceManifest", "manifest files[]", "清单 files[]"),
("PackPickDisk", "yours: {size}", "你的:{size}"),
("PackPickIncoming", "pack: {size}", "包内:{size}"),
("PackFormatModrinth", "Modrinth .mrpack", "Modrinth 的 .mrpack"),
("PackFormatCurseforge", "CurseForge manifest", "CurseForge 清单"),
("PackFormatMultimc", "MultiMC / Prism instance", "MultiMC·Prism 实例"),
("PackExportTitle", "Export this instance", "导出这个实例"),
("PackExportOpen", "Export…", "导出…"),
("PackExportFormat", "Format", "格式"),
("PackExportName", "Pack name", "包名"),
("PackExportVersion", "Version", "版本"),
("PackExportOutput", "Save to", "保存到"),
("PackExportOutputPlaceholder", "empty = suggested path", "留空 = 自动给一个路径"),
("PackExportPrecheck", "Dry run", "预检"),
("PackExportConfirm", "Write the pack", "确认写盘"),
("PackExportAbort", "Back", "返回"),
("PackExportMultimcNote", "MultiMC/Prism can only be imported, not exported (by design).", "MultiMC·Prism 只能导入、不能导出(有意省略)。"),
("PackExportDone", "Wrote {path} · {bytes}", "已写出 {path} · {bytes}"),
("PackExportFailed", "Export failed: {reason}", "导出失败:{reason}"),
("PackExportPending", "Scanning the instance…", "正在扫描实例…"),
("PackPreviewHead", "Will inline {inline} files · cannot export: {skipped}", "将内联 {inline} 个文件 · 无法导出 {skipped} 项"),
("PackPreviewRemote", "{count} files can be referenced remotely", "{count} 个文件可走远程引用"),
("PackPreviewInlineBytes", "{bytes} copied into overrides/", "{bytes} 会原样拷进 overrides/"),
("PackPreviewInlineTitle", "Copied into overrides/ (first {shown}):", "原样拷进 overrides/(只列前 {shown} 个):"),
("PackPreviewSkippedTitle", "Not in the pack: {count}", "没进包:{count} 项"),
("PackPreviewNotes", "Known losses", "已知损失"),
("PackPreviewTarget", "Will be written to {path}", "将写到 {path}"),
("PackPreviewMore", "…and {count} more files (not shown here)", "…还有 {count} 个文件(这里不展开)"),
("PackPreviewComplete", "Nothing is left out", "没有遗漏任何文件"),
("PackPreviewIncomplete", "Some files will not be in the pack", "有文件不会进包"),
("PackReasonModrinthSha1", "Modrinth match (SHA-1)", "Modrinth 命中(SHA-1)"),
("PackReasonCurseFingerprint", "CurseForge match (fingerprint)", "CurseForge 命中(文件指纹)"),
("PackReasonNoRemoteMatch", "unknown to both catalogs, inlined", "两个目录都不认识,已内联"),
("PackReasonCurseOnly", "only CurseForge knows it, this format cannot use it, inlined", "只有 CF 认识,目标格式用不上,已内联"),
("PackReasonModrinthOnly", "only Modrinth knows it, the CF manifest cannot use it, inlined", "只有 Modrinth 认识,CF 清单用不上,已内联"),
("PackReasonMissingSha512", "the catalogue entry has no sha512 hash, inlined", "命中缺 sha512,已内联"),
("PackReasonMissingCurseIds", "the catalogue entry has no CurseForge ids, inlined", "命中缺 projectID/fileID,已内联"),
("PackReasonDisabled", "disabled file, this format cannot express it (.disabled kept)", "禁用文件,目标格式表达不了(保留 .disabled)"),
("PackReasonSymlink", "symbolic link, skipped", "符号链接,已跳过"),
("PackReasonUnsafePath", "path fails the pack path rules, skipped", "路径过不了包内规整,已跳过"),
("PackReasonUnreadable", "cannot read it, skipped", "读不出来,已跳过"),
// ── M114 账户页:追加在 main 的全部域之后(金表只追加不重排)
("AccountTitle", "Accounts", "账户"),
("AccountSubtitle", "Microsoft, third-party skin servers and local profiles", "微软正版、第三方皮肤站与本地档案"),
("AccountListTitle", "All accounts", "全部账户"),
("AccountAddedOn", "Added {date}", "添加于 {date}"),
("AccountActiveChip", "Active", "当前"),
("AccountSwitch", "Use for launch", "切换为启动账户"),
("AccountRelogin", "Sign in again", "重新登录"),
("AccountRemove", "Remove", "删除"),
("AccountKindMicrosoft", "Microsoft", "微软正版"),
("AccountKindAuthlib", "Third-party skin server", "第三方皮肤站"),
("AccountKindOffline", "Local profile", "本地档案"),
("AccountServer", "Server {server}", "服务器 {server}"),
("AccountEmptyTitle", "No accounts yet", "还没有账户"),
("AccountEmptyBody", "Add a Microsoft account, a third-party skin server account, or a local profile.", "添加微软正版账户、第三方皮肤站账户,或建一个本地档案。"),
("AccountEmptyAction", "Add an account", "添加账户"),
("AccountTrackMicrosoftTitle", "Microsoft account", "微软正版"),
("AccountTrackMicrosoftBody", "Sign in with a device code or in your browser. Online servers require this kind of account.", "用设备码或浏览器登录。联机服务器必须用这种账户。"),
("AccountTrackAuthlibTitle", "Third-party skin server", "第三方皮肤站"),
("AccountTrackAuthlibBody", "An authlib-injector compatible server (LittleSkin and friends) brings its own skins and capes.", "兼容 authlib-injector 的皮肤站(如 LittleSkin)自带皮肤与披风。"),
("AccountTrackOfflineTitle", "Local profile", "本地档案"),
("AccountTrackOfflineBody", "Local / isolated-network testing only — it cannot join servers that require a genuine Minecraft account.", "仅本地/隔离网络测试用,无法连接启用正版验证的服务器。"),
("AccountTrackOpen", "Sign in", "登录"),
("AccountTrackCreate", "Create profile", "创建档案"),
("AccountDialogClose", "Close", "关闭"),
("AccountOfflineNameLabel", "Profile name", "档案名"),
("AccountOfflineNameHint", "3–16 letters, digits or underscore", "3–16 位字母、数字或下划线"),
("AccountOfflineSubmit", "Create profile", "创建档案"),
("AccountOfflineWarning", "Local / isolated-network testing only — it cannot join servers that require a genuine Minecraft account.", "仅本地/隔离网络测试用,无法连接启用正版验证的服务器。"),
("AccountDeviceCodeLabel", "Enter this code", "输入这个用户码"),
("AccountDeviceCodeCopy", "Copy code", "复制用户码"),
("AccountDeviceLinkCopy", "Copy link", "复制链接"),
("AccountDeviceCountdown", "{time} left", "剩 {time}"),
("AccountDeviceExpired", "This code has expired. Start again for a fresh one.", "这个用户码已过期,重新开始换一个新的。"),
("AccountDeviceRetry", "Try again", "重试"),
("AccountDeviceCancel", "Cancel", "取消"),
("AccountDeviceBrowser", "Sign in with browser", "用浏览器登录"),
("AccountDeviceUseCode", "Use a device code instead", "改用设备码"),
("AccountServerLabel", "Server address", "服务器地址"),
("AccountServerHint", "API root, e.g. https://littleskin.cn/api/yggdrasil/", "API 根,例:https://littleskin.cn/api/yggdrasil/"),
("AccountServerProbe", "Check server", "校验服务器"),
("AccountLoginNameLabel", "Email or username", "邮箱或用户名"),
("AccountPasswordLabel", "Password", "密码"),
("AccountPasswordHint", "Used once for this sign-in. It is never stored.", "只在这次登录里用一次,不会保存。"),
("AccountAuthlibSubmit", "Sign in", "登录"),
("AccountAuthlibIdleHint", "The server is checked automatically when you sign in; Check server only does it up front.", "登录时会自动校验服务器;「校验服务器」只是提前跑一遍。"),
("AccountSkinTitle", "Skin", "皮肤"),
("AccountSkinNone", "No skin available", "没有可用皮肤"),
("AccountSkinHint", "Skins come from the account's own server; nothing is generated locally.", "皮肤来自账户自己的服务器,本地不生成任何假皮肤。"),
("AccountRailSignedOut", "Not signed in", "未登录"),
("AccountDeviceHint", "Open the link in your browser and enter the code above.", "在浏览器里打开链接,输入上面的用户码。"),
("AccountDeviceBrowserHint", "Finish the sign-in in the browser window we just opened; the link below also works.", "在我们刚打开的浏览器窗口里完成登录;下面的链接也能手动打开。"),
("AccountServerChecking", "Checking the server…", "正在校验服务器…"),
("AccountServerOk", "Server {server} is ready", "服务器 {server} 可用"),
("AccountLoginFailed", "Sign-in failed", "登录失败"),
("AccountCurrentTitle", "Current account", "当前账户"),
("AccountFailureCode", "Code: {code}", "代码:{code}"),
("AccountFailureDenied", "The server refused this sign-in (access denied).", "服务器拒绝了这次登录(拒绝访问)。"),
("AccountFailureWhitelist", "Microsoft has not approved this launcher's app registration yet. An administrator has to accept the app, then try again.", "微软还没批准本启动器的应用注册:需要管理员同意该应用后再试。"),
("AccountFailureUnreachable", "Could not reach the server. Check the network connection or the address, then try again.", "连不上服务器:检查网络或地址后重试。"),
("AccountFailureNotAuthlib", "This address does not look like an authlib-injector server (the API root usually ends with /api/yggdrasil/).", "这个地址不像 authlib-injector 服务器(API 根通常以 /api/yggdrasil/ 结尾)。"),
("AccountFailureBadCredentials", "The server rejected the username or password.", "服务器不认这个用户名或密码。"),
("AccountFailureNoProfile", "The account has no Minecraft profile on this server yet. Create the character on the server first.", "这个账号在该服务器上还没有角色:先在皮肤站里创建角色。"),
("AccountFailureStore", "Could not save the account to disk.", "账户没能写到磁盘上。"),
("AccountFailureOther", "The sign-in failed. The full reason is in the launcher log.", "登录失败,完整原因在启动器日志里。"),
("AccountLoginNotConfigured", "Microsoft sign-in is not configured", "微软登录未配置"),
("AccountFailureMsaNotConfigured", "This build has no Azure public client id, so Microsoft sign-in cannot start (the sign-in flow itself is implemented). Set the environment variable ULL_MSA_CLIENT_ID=<id> before starting the launcher, or build with ULL_MSA_CLIENT_ID=<id>. Then restart the launcher: a running process does not pick up a new environment variable.", "本启动器没有配置 Azure 公共客户端 id,微软登录无法开始(登录功能已实现,只差这一项配置)。启动前设置环境变量 ULL_MSA_CLIENT_ID=<id>,或构建时注入:ULL_MSA_CLIENT_ID=<id> cargo build。改完请重启启动器——已在运行的进程读不到新设的环境变量。"),
("AccountDeviceRequesting", "Contacting Microsoft…", "正在联系微软…"),
("AccountLoginSucceeded", "Signed in as {name}", "已登录 {name}"),
("AccountNoticeAdded", "Added {name}", "已添加 {name}"),
("AccountNoticeRemoved", "Removed {name}", "已删除 {name}"),
("AccountNoticeSwitched", "{name} will be used for the next launch", "{name} 将作为下次启动的账户"),
("AccountNoticeOfflineNameInvalid", "Profile names must be 3–16 letters, digits or underscores.", "档案名必须是 3–16 位字母、数字或下划线。"),
("AccountNoticeAccountExists", "An account with that name already exists.", "同名账户已经存在。"),
("AccountNoticeStoreFailed", "Could not save the account store. Check the disk and try again.", "账户库写不进去:检查磁盘后重试。"),
("AccountNoticeNotFound", "That account no longer exists.", "这个账户已经不在了。"),
("AccountNoticeOther", "The account action failed. The full reason is in the launcher log.", "账户操作失败,完整原因在启动器日志里。"),
("AccountNoticeDismiss", "Dismiss", "关闭"),
("AccountNoticeTitleFailed", "Account action failed", "账户操作失败"),
("AccountNoticeTitleDone", "Account updated", "账户已更新"),
("AccountHintAuthlibReauth", "Enter the password again for {server}.", "请输入 {server} 的密码。"),
("AccountHintOfflineNoRelogin", "Local profiles have no server account to sign in again — create a new profile instead.", "本地档案没有可重新登录的服务器账户,请新建一个档案。"),
("SettingsGroupUpdate", "Updates", "更新"),
("SettingsUpdateCurrent", "Current version", "当前版本"),
("SettingsUpdateChannel", "Channel", "更新渠道"),
("SettingsUpdateChannelStable", "Stable", "稳定版"),
("SettingsUpdateAutoCheck", "Check for updates on startup", "启动时检查更新"),
("SettingsUpdateCheckNow", "Check now", "立即检查"),
("SettingsUpdateChecking", "Checking…", "正在检查…"),
("SettingsUpdateNever", "Not checked yet", "还没检查过"),
("SettingsUpdateUpToDate", "You are on the latest version ({version})", "已是最新({version})"),
("SettingsUpdateAvailable", "Version {version} is available ({size})", "有新版本 {version}({size})"),
("SettingsUpdateMissingArtifact", "Version {version} is out, but there is no build for this platform yet.", "{version} 已发布,但还没有本平台的安装包。"),
("SettingsUpdateFailed", "Check failed: {reason}", "检查失败:{reason}"),
("SettingsUpdateApply", "Download and install", "下载并安装"),
("SettingsUpdateApplying", "Downloading and verifying…", "正在下载并校验…"),
("SettingsUpdateReady", "Version {version} is ready — restart to use it.", "版本 {version} 已就位,重启后生效。"),
("SettingsUpdateNotes", "Release notes: {notes}", "更新说明:{notes}"),
("SettingsUpdateForced", "This update is required", "这是一次强制更新"),
("SettingsUpdateLastChecked", "Last check", "上次检查"),
("SettingsUpdateHint", "Downloads are verified with SHA256 before they touch the launcher. The running copy stays as it is until you restart.", "更新包在落到启动器之前会做 SHA256 校验;正在运行的这一份在你重启之前不会变。"),
("UpdateBannerTitleAvailable", "Version {version} is available", "发现新版本 {version}"),
("UpdateBannerBodyAvailable", "Download size {size}", "下载体积 {size}"),
("UpdateBannerTitleReady", "Update ready", "更新已就位"),
("UpdateBannerBodyReady", "Version {version} will run after a restart.", "重启后运行版本 {version}。"),
("UpdateBannerTitleFailed", "Update failed", "更新失败"),
("UpdateBannerApplying", "Downloading the update…", "正在下载更新…"),
("UpdateBannerInstall", "Download and install", "下载并安装"),
("UpdateBannerDismiss", "Skip this version", "忽略这个版本"),
("UpdateBannerRestartNow", "Restart now", "立即重启"),
("UpdateBannerRetry", "Try again", "重试"),
];
+212
View File
@@ -0,0 +1,212 @@
//! 金表的第三段(`tail.rs` 之后,M161 拆:`tail.rs` 到 M157 已有 411 行、加自更新那几条就 423)。
//!
//! 口径与 `golden.rs` / `tail.rs` 完全一致:**纯搬移、一行不改**,顺序即 `Key::ALL` 的续段。
//! 拼装见 `golden.rs` 的 [`super::rows`]。
pub(super) const ROWS: &[(&str, &str, &str)] = &[
("PackInstanceName", "Instance name", "实例名"),
("PackStageLine", "Step {index}/{total} · {stage}", "步骤 {index}/{total} · {stage}"),
("PackStageProbe", "Reading the manifest", "读取清单"),
("PackStageExtract", "Unpacking overrides", "解包覆盖内容"),
("PackStageFetch", "Fetching missing files", "补下载文件"),
("PackStageCommit", "Writing files", "落地写盘"),
("PackStageRegister", "Registering the instance", "登记实例"),
("PackProbeTitle", "This pack is almost a known format", "这个包差一点就是已知格式"),
("PackProbeLooksLike", "Looks like {format}, but missing: {missing}", "看起来像 {format},但缺:{missing}"),
("PackProbeUnknown", "No known format claims this pack", "没有任何已知格式认领这个包"),
("PackProbeSaw", "Found in the pack: {saw}", "包里看到:{saw}"),
("PackProbeNothing", "nothing recognisable", "没有可识别的东西"),
("PackStatusSuccess", "Imported", "已导入"),
("PackStatusPartial", "Imported with gaps", "导入完成,但有缺口"),
("PackStatusFailed", "Import failed — rolled back", "导入失败 —— 已整包回滚"),
("PackReportWritten", "Files written: {count} · {bytes}", "{count} 个文件已写盘 · {bytes}"),
("PackReportMissing", "Could not fetch (tolerated): {count}", "有 {count} 个文件没搞到(可容忍)"),
("PackReportConflicts", "Conflicts: {count}", "冲突:{count} 个"),
("PackReportRejected", "The client does not support these: {count}", "这些组件客户端不支持:{count} 个"),
("PackReportRejectedNote", "not supported by the client", "客户端不支持"),
("PackCancelled", "Import keeps running in the background — this result is discarded. Files already written stay.", "导入会在后台继续跑完 —— 本次结果作废;已经写下的文件会留下。"),
("PackOverwriteAction", "Re-import, the pack wins", "以包为准重新导入"),
("PackOverwriteNote", "Keeping both (renamed) is not supported yet: for each existing file you pick either “keep” or “overwrite”.", "「两者都留(改名)」暂不支持:每个已存在的文件只能选「保留」或「覆盖」。"),
("PackMissingOffline", "offline import", "离线导入"),
("PackMissingNoSource", "no download source available yet", "暂时拿不到下载地址"),
("PackMissingFetchFailed", "download failed: {detail}", "下载失败:{detail}"),
("PackFatalTitle", "Rolled back — nothing was left behind", "已回滚 —— 目标目录零残留"),
("PackFatalHint", "What to try next", "下一步可以试"),
("PackConflictUserModified", "you changed it", "你改过"),
("PackConflictUserDeleted", "you deleted it", "你删过"),
("PackConflictPreExisting", "was already there", "本来就在"),
("PackChoiceKeepUser", "kept yours", "保留我的"),
("PackChoiceOverwrite", "pack version used", "用包里的"),
("PackConflictHashes", "pack {pack} · base {base} · disk {disk}", "包内 {pack} · 基线 {base} · 磁盘 {disk}"),
("PackConflictDetail", "Hashes", "三方哈希"),
("PackPickTitle", "Before importing: {count} files already exist with different content", "导入前:有 {count} 个文件已存在且内容不同"),
("PackPickSummary", "Keep {keep} · overwrite {overwrite} · overwriting discards {bytes}", "保留 {keep} · 覆盖 {overwrite} · 覆盖将丢弃 {bytes}"),
("PackPickKeepAll", "Keep all mine", "全部保留我的"),
("PackPickOverwriteAll", "Overwrite all", "全部覆盖"),
("PackPickRowKeep", "Keep", "保留"),
("PackPickRowOverwrite", "Overwrite", "覆盖"),
("PackPickPage", "Items {from}-{to} of {total}", "第 {from}-{to} 项,共 {total} 项"),
("PackPickPrev", "Previous", "上一页"),
("PackPickNext", "Next", "下一页"),
("PackPickConfirm", "Import with these choices", "按这些选择导入"),
("PackPickCancel", "Cancel import", "取消导入"),
("PackPickDefaultNote", "Anything you do not change stays as you have it: file content is only replaced where you pick “Overwrite”.", "没有改动的一律按「保留」:只有你点了「覆盖」的文件才会被包内内容替换。"),
("PackPickUnknownRemote", "{count} remote entries only learn their path after download; they follow “keep”.", "还有 {count} 条远端条目要下载后才知道路径,一律按「保留」处置。"),
("PackPickSourceOverrides", "in the pack (overrides/)", "包内 overrides/"),
("PackPickSourceClientOverrides", "in the pack (client-overrides/)", "包内 client-overrides/"),
("PackPickSourceManifest", "manifest files[]", "清单 files[]"),
("PackPickDisk", "yours: {size}", "你的:{size}"),
("PackPickIncoming", "pack: {size}", "包内:{size}"),
("PackFormatModrinth", "Modrinth .mrpack", "Modrinth 的 .mrpack"),
("PackFormatCurseforge", "CurseForge manifest", "CurseForge 清单"),
("PackFormatMultimc", "MultiMC / Prism instance", "MultiMC·Prism 实例"),
("PackExportTitle", "Export this instance", "导出这个实例"),
("PackExportOpen", "Export…", "导出…"),
("PackExportFormat", "Format", "格式"),
("PackExportName", "Pack name", "包名"),
("PackExportVersion", "Version", "版本"),
("PackExportOutput", "Save to", "保存到"),
("PackExportOutputPlaceholder", "empty = suggested path", "留空 = 自动给一个路径"),
("PackExportPrecheck", "Dry run", "预检"),
("PackExportConfirm", "Write the pack", "确认写盘"),
("PackExportAbort", "Back", "返回"),
("PackExportMultimcNote", "MultiMC/Prism can only be imported, not exported (by design).", "MultiMC·Prism 只能导入、不能导出(有意省略)。"),
("PackExportDone", "Wrote {path} · {bytes}", "已写出 {path} · {bytes}"),
("PackExportFailed", "Export failed: {reason}", "导出失败:{reason}"),
("PackExportPending", "Scanning the instance…", "正在扫描实例…"),
("PackPreviewHead", "Will inline {inline} files · cannot export: {skipped}", "将内联 {inline} 个文件 · 无法导出 {skipped} 项"),
("PackPreviewRemote", "{count} files can be referenced remotely", "{count} 个文件可走远程引用"),
("PackPreviewInlineBytes", "{bytes} copied into overrides/", "{bytes} 会原样拷进 overrides/"),
("PackPreviewInlineTitle", "Copied into overrides/ (first {shown}):", "原样拷进 overrides/(只列前 {shown} 个):"),
("PackPreviewSkippedTitle", "Not in the pack: {count}", "没进包:{count} 项"),
("PackPreviewNotes", "Known losses", "已知损失"),
("PackPreviewTarget", "Will be written to {path}", "将写到 {path}"),
("PackPreviewMore", "…and {count} more files (not shown here)", "…还有 {count} 个文件(这里不展开)"),
("PackPreviewComplete", "Nothing is left out", "没有遗漏任何文件"),
("PackPreviewIncomplete", "Some files will not be in the pack", "有文件不会进包"),
("PackReasonModrinthSha1", "Modrinth match (SHA-1)", "Modrinth 命中(SHA-1)"),
("PackReasonCurseFingerprint", "CurseForge match (fingerprint)", "CurseForge 命中(文件指纹)"),
("PackReasonNoRemoteMatch", "unknown to both catalogs, inlined", "两个目录都不认识,已内联"),
("PackReasonCurseOnly", "only CurseForge knows it, this format cannot use it, inlined", "只有 CF 认识,目标格式用不上,已内联"),
("PackReasonModrinthOnly", "only Modrinth knows it, the CF manifest cannot use it, inlined", "只有 Modrinth 认识,CF 清单用不上,已内联"),
("PackReasonMissingSha512", "the catalogue entry has no sha512 hash, inlined", "命中缺 sha512,已内联"),
("PackReasonMissingCurseIds", "the catalogue entry has no CurseForge ids, inlined", "命中缺 projectID/fileID,已内联"),
("PackReasonDisabled", "disabled file, this format cannot express it (.disabled kept)", "禁用文件,目标格式表达不了(保留 .disabled)"),
("PackReasonSymlink", "symbolic link, skipped", "符号链接,已跳过"),
("PackReasonUnsafePath", "path fails the pack path rules, skipped", "路径过不了包内规整,已跳过"),
("PackReasonUnreadable", "cannot read it, skipped", "读不出来,已跳过"),
("PackStatusFailedNotStarted", "Import failed — nothing was written", "导入失败 —— 还没写任何文件"),
("PackStatusFailedIncomplete", "Import failed — rollback did not finish", "导入失败 —— 回滚没做完"),
("PackFatalTitleNotStarted", "Preflight failed — nothing was written", "预检未通过 —— 一个字节都没写"),
("PackFatalTitleIncomplete", "Rollback did not finish — the target folder may differ", "回滚没做完 —— 目标目录可能与导入前不同"),
("AccountTitle", "Accounts", "账户"),
("AccountSubtitle", "Microsoft, third-party skin servers and local profiles", "微软正版、第三方皮肤站与本地档案"),
("AccountListTitle", "All accounts", "全部账户"),
("AccountAddedOn", "Added {date}", "添加于 {date}"),
("AccountActiveChip", "Active", "当前"),
("AccountSwitch", "Use for launch", "切换为启动账户"),
("AccountRelogin", "Sign in again", "重新登录"),
("AccountRemove", "Remove", "删除"),
("AccountKindMicrosoft", "Microsoft", "微软正版"),
("AccountKindAuthlib", "Third-party skin server", "第三方皮肤站"),
("AccountKindOffline", "Local profile", "本地档案"),
("AccountServer", "Server {server}", "服务器 {server}"),
("AccountEmptyTitle", "No accounts yet", "还没有账户"),
("AccountEmptyBody", "Add a Microsoft account, a third-party skin server account, or a local profile.", "添加微软正版账户、第三方皮肤站账户,或建一个本地档案。"),
("AccountEmptyAction", "Add an account", "添加账户"),
("AccountTrackMicrosoftTitle", "Microsoft account", "微软正版"),
("AccountTrackMicrosoftBody", "Sign in with a device code or in your browser. Online servers require this kind of account.", "用设备码或浏览器登录。联机服务器必须用这种账户。"),
("AccountTrackAuthlibTitle", "Third-party skin server", "第三方皮肤站"),
("AccountTrackAuthlibBody", "An authlib-injector compatible server (LittleSkin and friends) brings its own skins and capes.", "兼容 authlib-injector 的皮肤站(如 LittleSkin)自带皮肤与披风。"),
("AccountTrackOfflineTitle", "Local profile", "本地档案"),
("AccountTrackOfflineBody", "Local / isolated-network testing only — it cannot join servers that require a genuine Minecraft account.", "仅本地/隔离网络测试用,无法连接启用正版验证的服务器。"),
("AccountTrackOpen", "Sign in", "登录"),
("AccountTrackCreate", "Create profile", "创建档案"),
("AccountDialogClose", "Close", "关闭"),
("AccountOfflineNameLabel", "Profile name", "档案名"),
("AccountOfflineNameHint", "3–16 letters, digits or underscore", "3–16 位字母、数字或下划线"),
("AccountOfflineSubmit", "Create profile", "创建档案"),
("AccountOfflineWarning", "Local / isolated-network testing only — it cannot join servers that require a genuine Minecraft account.", "仅本地/隔离网络测试用,无法连接启用正版验证的服务器。"),
("AccountDeviceCodeLabel", "Enter this code", "输入这个用户码"),
("AccountDeviceCodeCopy", "Copy code", "复制用户码"),
("AccountDeviceLinkCopy", "Copy link", "复制链接"),
("AccountDeviceCountdown", "{time} left", "剩 {time}"),
("AccountDeviceExpired", "This code has expired. Start again for a fresh one.", "这个用户码已过期,重新开始换一个新的。"),
("AccountDeviceRetry", "Try again", "重试"),
("AccountDeviceCancel", "Cancel", "取消"),
("AccountDeviceBrowser", "Sign in with browser", "用浏览器登录"),
("AccountDeviceUseCode", "Use a device code instead", "改用设备码"),
("AccountServerLabel", "Server address", "服务器地址"),
("AccountServerHint", "API root, e.g. https://littleskin.cn/api/yggdrasil/", "API 根,例:https://littleskin.cn/api/yggdrasil/"),
("AccountServerProbe", "Check server", "校验服务器"),
("AccountLoginNameLabel", "Email or username", "邮箱或用户名"),
("AccountPasswordLabel", "Password", "密码"),
("AccountPasswordHint", "Used once for this sign-in. It is never stored.", "只在这次登录里用一次,不会保存。"),
("AccountAuthlibSubmit", "Sign in", "登录"),
("AccountAuthlibIdleHint", "The server is checked automatically when you sign in; Check server only does it up front.", "登录时会自动校验服务器;「校验服务器」只是提前跑一遍。"),
("AccountSkinTitle", "Skin", "皮肤"),
("AccountSkinNone", "No skin available", "没有可用皮肤"),
("AccountSkinHint", "Skins come from the account's own server; nothing is generated locally.", "皮肤来自账户自己的服务器,本地不生成任何假皮肤。"),
("AccountRailSignedOut", "Not signed in", "未登录"),
("AccountDeviceHint", "Open the link in your browser and enter the code above.", "在浏览器里打开链接,输入上面的用户码。"),
("AccountDeviceBrowserHint", "Finish the sign-in in the browser window we just opened; the link below also works.", "在我们刚打开的浏览器窗口里完成登录;下面的链接也能手动打开。"),
("AccountServerChecking", "Checking the server…", "正在校验服务器…"),
("AccountServerOk", "Server {server} is ready", "服务器 {server} 可用"),
("AccountLoginFailed", "Sign-in failed", "登录失败"),
("AccountCurrentTitle", "Current account", "当前账户"),
("AccountFailureCode", "Code: {code}", "代码:{code}"),
("AccountFailureDenied", "The server refused this sign-in (access denied).", "服务器拒绝了这次登录(拒绝访问)。"),
("AccountFailureWhitelist", "Microsoft has not approved this launcher's app registration yet. An administrator has to accept the app, then try again.", "微软还没批准本启动器的应用注册:需要管理员同意该应用后再试。"),
("AccountFailureUnreachable", "Could not reach the server. Check the network connection or the address, then try again.", "连不上服务器:检查网络或地址后重试。"),
("AccountFailureNotAuthlib", "This address does not look like an authlib-injector server (the API root usually ends with /api/yggdrasil/).", "这个地址不像 authlib-injector 服务器(API 根通常以 /api/yggdrasil/ 结尾)。"),
("AccountFailureBadCredentials", "The server rejected the username or password.", "服务器不认这个用户名或密码。"),
("AccountFailureNoProfile", "The account has no Minecraft profile on this server yet. Create the character on the server first.", "这个账号在该服务器上还没有角色:先在皮肤站里创建角色。"),
("AccountFailureStore", "Could not save the account to disk.", "账户没能写到磁盘上。"),
("AccountFailureOther", "The sign-in failed. The full reason is in the launcher log.", "登录失败,完整原因在启动器日志里。"),
("AccountLoginNotConfigured", "Microsoft sign-in is not configured", "微软登录未配置"),
("AccountFailureMsaNotConfigured", "This build has no Azure public client id, so Microsoft sign-in cannot start (the sign-in flow itself is implemented). Set the environment variable ULL_MSA_CLIENT_ID=<id> before starting the launcher, or build with ULL_MSA_CLIENT_ID=<id>. Then restart the launcher: a running process does not pick up a new environment variable.", "本启动器没有配置 Azure 公共客户端 id,微软登录无法开始(登录功能已实现,只差这一项配置)。启动前设置环境变量 ULL_MSA_CLIENT_ID=<id>,或构建时注入:ULL_MSA_CLIENT_ID=<id> cargo build。改完请重启启动器——已在运行的进程读不到新设的环境变量。"),
("AccountDeviceRequesting", "Contacting Microsoft…", "正在联系微软…"),
("AccountLoginSucceeded", "Signed in as {name}", "已登录 {name}"),
("AccountNoticeAdded", "Added {name}", "已添加 {name}"),
("AccountNoticeRemoved", "Removed {name}", "已删除 {name}"),
("AccountNoticeSwitched", "{name} will be used for the next launch", "{name} 将作为下次启动的账户"),
("AccountNoticeOfflineNameInvalid", "Profile names must be 3–16 letters, digits or underscores.", "档案名必须是 3–16 位字母、数字或下划线。"),
("AccountNoticeAccountExists", "An account with that name already exists.", "同名账户已经存在。"),
("AccountNoticeStoreFailed", "Could not save the account store. Check the disk and try again.", "账户库写不进去:检查磁盘后重试。"),
("AccountNoticeNotFound", "That account no longer exists.", "这个账户已经不在了。"),
("AccountNoticeOther", "The account action failed. The full reason is in the launcher log.", "账户操作失败,完整原因在启动器日志里。"),
("AccountNoticeDismiss", "Dismiss", "关闭"),
("AccountNoticeTitleFailed", "Account action failed", "账户操作失败"),
("AccountNoticeTitleDone", "Account updated", "账户已更新"),
("AccountHintAuthlibReauth", "Enter the password again for {server}.", "请输入 {server} 的密码。"),
("AccountHintOfflineNoRelogin", "Local profiles have no server account to sign in again — create a new profile instead.", "本地档案没有可重新登录的服务器账户,请新建一个档案。"),
("SettingsGroupUpdate", "Updates", "更新"),
("SettingsUpdateCurrent", "Current version", "当前版本"),
("SettingsUpdateChannel", "Channel", "更新渠道"),
("SettingsUpdateChannelStable", "Stable", "稳定版"),
("SettingsUpdateAutoCheck", "Check for updates on startup", "启动时检查更新"),
("SettingsUpdateCheckNow", "Check now", "立即检查"),
("SettingsUpdateChecking", "Checking…", "正在检查…"),
("SettingsUpdateNever", "Not checked yet", "还没检查过"),
("SettingsUpdateUpToDate", "You are on the latest version ({version})", "已是最新({version})"),
("SettingsUpdateAvailable", "Version {version} is available ({size})", "有新版本 {version}({size})"),
("SettingsUpdateMissingArtifact", "Version {version} is out, but there is no build for this platform yet.", "{version} 已发布,但还没有本平台的安装包。"),
("SettingsUpdateFailed", "Check failed: {reason}", "检查失败:{reason}"),
("SettingsUpdateApply", "Download and install", "下载并安装"),
("SettingsUpdateApplying", "Downloading and verifying…", "正在下载并校验…"),
("SettingsUpdateReady", "Version {version} is ready — restart to use it.", "版本 {version} 已就位,重启后生效。"),
("SettingsUpdateNotes", "Release notes: {notes}", "更新说明:{notes}"),
("SettingsUpdateForced", "This update is required", "这是一次强制更新"),
("SettingsUpdateLastChecked", "Last check", "上次检查"),
("SettingsUpdateHint", "Downloads are verified with SHA256 before they touch the launcher. The running copy stays as it is until you restart.", "更新包在落到启动器之前会做 SHA256 校验;正在运行的这一份在你重启之前不会变。"),
("UpdateBannerTitleAvailable", "Version {version} is available", "发现新版本 {version}"),
("UpdateBannerBodyAvailable", "Download size {size}", "下载体积 {size}"),
("UpdateBannerTitleReady", "Update ready", "更新已就位"),
("UpdateBannerBodyReady", "Version {version} will run after a restart.", "重启后运行版本 {version}。"),
("UpdateBannerTitleFailed", "Update failed", "更新失败"),
("UpdateBannerApplying", "Downloading the update…", "正在下载更新…"),
("UpdateBannerInstall", "Download and install", "下载并安装"),
("UpdateBannerDismiss", "Skip this version", "忽略这个版本"),
("UpdateBannerRestartNow", "Restart now", "立即重启"),
("UpdateBannerRetry", "Try again", "重试"),
];
+1 -1
View File
@@ -73,7 +73,7 @@ macro_rules! instances_entries {
InstancesIsolationShared => ("Shared", "共用目录"),
// ── 运行状态与启动阶段(M120;数字与分隔符不随语言变形)
InstancesRunning => ("Running · pid {pid}", "运行中 · pid {pid}"),
InstancesFailed => ("Launch failed · {reason}", "启动失败 · {reason}"),
InstancesFailedStage => ("Launch failed · {stage}", "启动失败 · {stage}"),
InstancesStageDownload => ("Downloading", "下载中"),
InstancesStageVerify => ("Verifying", "校验中"),
InstancesStageLaunch => ("Starting", "启动中"),
+11
View File
@@ -14,6 +14,17 @@ macro_rules! launch_entries {
"疑似静默失败:退出码 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 界面用)。