fix(i18n): 全局复查修复——多行调用点漏替换、动态 label 回归与死键清理

复查发现(audit 脚本 + 修正后的单测扫描器):
- 27 处多行 tf("中文") 调用点未被键迁移的单行替换覆盖,英文模式下
  回退显示中文;正则补丁全部换为语义键
- DirFilter/DetailFormat::label() 仍返回中文常量,t() 动态查键必然
  miss(英文模式方向过滤/格式按钮显示中文);label() 改返回
  common.all/dir.*、common.auto/text(Hex/Base64 语言中性字面量)
- 单测扫描器与 audit 脚本的共同盲区:t(/tf( 与引号之间的空白换行
  不被匹配;扫描器改为跳过空白后取字面量,多行调用纳入强制覆盖
- 6 处 UI 直写补翻:连接测试成功通知、复制连接"(copy)"后缀、
  rfd 导入/导出对话框标题、设置对话框标题、订阅标识符字段标签
- store 导入/导出错误与 PayloadFormat 编码错误(均经 Notification
  展示)key 化,共 14 条新词条
- 删除 10 个真死键;mqtt/tls/update 层诊断错误维持中文(技术诊断
  流,不进 UI 渲染路径),边界记录于模块文档

语言包现状:354 键、en/zh-CN 双语并排、零死键、零 UI 中文直写;
42 测试全绿;英文模式实机截图复核(含回归点)通过。
This commit is contained in:
2026-10-04 23:49:28 +08:00
parent 35e2b6fb60
commit 5db0972263
18 changed files with 101 additions and 90 deletions
+5 -5
View File
@@ -53,23 +53,23 @@ impl PayloadFormat {
use base64::Engine as _;
base64::engine::general_purpose::STANDARD
.decode(text.trim())
.map_err(|e| format!("Base64 解码失败: {e}"))
.map_err(|e| crate::ui::i18n::tf("encode.base64_failed", &[("e", &e.to_string())]))
}
Self::Hex => {
let cleaned: String = text.chars().filter(|c| !c.is_whitespace()).collect();
if !cleaned.len().is_multiple_of(2) {
return Err("Hex 长度必须为偶数(每两个字符一个字节)".into());
return Err(crate::ui::i18n::t("encode.hex_odd").into());
}
// 必须先做全字节校验:长度检查按字节计数,多字节字符(如中文)
// 可凑成偶数字节,直接按字节索引切片会落在字符边界内而 panic。
if !cleaned.bytes().all(|b| b.is_ascii_hexdigit()) {
return Err("Hex 解码失败: 含非十六进制字符".into());
return Err(crate::ui::i18n::t("encode.hex_invalid").into());
}
(0..cleaned.len())
.step_by(2)
.map(|i| {
u8::from_str_radix(&cleaned[i..i + 2], 16)
.map_err(|e| format!("Hex 解码失败: {e}"))
.map_err(|e| crate::ui::i18n::tf("encode.hex_failed", &[("e", &e.to_string())]))
})
.collect()
}
@@ -154,7 +154,7 @@ pub fn compute_preview(payload: &str) -> String {
}
};
if payload.contains('\u{FFFD}') {
out.push_str("(非文本,详情可切 Hex)");
out.push_str(crate::ui::i18n::t("msg.binary_hint"));
}
out
}