From 95c265cab93f3db172d87bba603744d915f7f29b Mon Sep 17 00:00:00 2001 From: JGZYES Date: Fri, 4 Sep 2026 22:36:58 +0800 Subject: [PATCH] i18n: fix arg/fmt mismatches + standardise help/banner/docs Audit found pmm_tr_fmt calls whose arg count didn't match the language pack's %i placeholders, and a few leftover logic errors: - main.c selected() stray trailing arg; legacy branch passes os+''. - install.c checksum-mismatch passed a template string as the first arg. - bad-entry vs bad-registry-entry split (1-arg vs 2-arg semantics). - pdm.c checksum-mismatch used the 3-arg key with 2 args -> dedicated checksum-mismatch-file key. - pmm.c removed used the pdm remove key -> unregistered key. - sha256/sha1 split into inline (1 arg) vs verify (2 arg) keys; downloading and lang packs aligned to 2 placeholders. - Removed duplicate lang keys; STANDARD.md %placeholder docs updated to the actual %s convention. Result: audit ALL MATCH, both packs valid (124 keys) with no duplicates, all 100 used keys present, bilingual smoke tests clean (no key fallback). --- docs/STANDARD.md | 8 ++++---- src/install.c | 11 +++++------ src/main.c | 2 +- src/pdm.c | 2 +- src/pmm.c | 2 +- web/mirror/lang/en-US.pjson | 15 +++++++++++---- web/mirror/lang/zh-CN.pjson | 15 +++++++++++---- 7 files changed, 34 insertions(+), 21 deletions(-) diff --git a/docs/STANDARD.md b/docs/STANDARD.md index 7518d23..24dc138 100644 --- a/docs/STANDARD.md +++ b/docs/STANDARD.md @@ -112,12 +112,12 @@ web/mirror/lang/.pjson ``` { - "help.banner": "PMM {ver} ({arch})", + "help.banner": "PMM %s (%s)", "cmd.list": "list", "cmd.info": "info", "desc.list": "根据名称列出软件包", - "msg.installed": "已安装 {name}", - "msg.err.notfound": "未找到软件包 {name}" + "msg.installed": "已安装 %s", + "msg.err.notfound": "未找到软件包 %s" } ``` @@ -134,7 +134,7 @@ web/mirror/lang/.pjson | `opt.` | 选项说明 | | `cfg.` | 配置项名 | -占位符用 `{name}`、`{ver}`、`{arch}` 等(花括号 + 小写字段名),渲染时替换。 +占位符用 C `printf` 风格的 `%s` / `%d`(与源码调用 `pmm_tr_fmt("key", args...)` 的参数一一对应),渲染时由 `pmm_tr_fmt` 替换。 键**不得**含空格 / 大写,语义词用小写连字符(如 `msg.err.not-found`)。 ## 6. 提交 / PR 约定 diff --git a/src/install.c b/src/install.c index 6f1c3cc..24af90c 100644 --- a/src/install.c +++ b/src/install.c @@ -437,9 +437,9 @@ int install_file(const char *url, const char *name) { /* integrity: sha256 + sha1, verified against sidecar checksums when present */ char hex[128]; if (pmm_sha256_file(path, hex) == 0) - pmm_info("%s", pmm_tr_fmt("msg.sha256", hex)); + pmm_info("%s", pmm_tr_fmt("msg.hash-sha256", hex)); if (pmm_sha1_file(path, hex) == 0) - pmm_info("%s", pmm_tr_fmt("msg.sha1", hex)); + pmm_info("%s", pmm_tr_fmt("msg.hash-sha1", hex)); if (verify_checksums(url, path, name) != 0) { pmm_error(pmm_tr("msg.err.checksum-refuse")); remove(path); @@ -831,7 +831,7 @@ int install_from_registry(const char *name, const char *spec, const char *mirror JsonValue *meta = json_parse(body); free(body); if (!meta || meta->type != JSON_OBJECT) { - pmm_error("%s", pmm_tr_fmt("msg.err.bad-entry", name, used_base)); + pmm_error("%s", pmm_tr_fmt("msg.err.bad-registry-entry", name, used_base)); json_free(meta); mirrors_free(ml); return -1; @@ -878,7 +878,7 @@ int install_from_registry(const char *name, const char *spec, const char *mirror /* legacy single-platform entry */ dl = json_str(meta, "url"); file = json_str(meta, "file"); const char *s = json_str(meta, "sha256"); want_sha = s ? strdup(s) : NULL; - pmm_info("%s", pmm_tr_fmt("msg.selected", name, json_str(meta, "version")), osn); + pmm_info("%s", pmm_tr_fmt("msg.selected", name, json_str(meta, "version"), osn, "")); } if (!dl) { pmm_error("%s", pmm_tr_fmt("msg.err.registry-entry-no-url", name)); @@ -897,8 +897,7 @@ int install_from_registry(const char *name, const char *spec, const char *mirror snprintf(path, sizeof(path), "%s/%s", cache, file_cp); if (pmm_sha256_file(path, hex) == 0) { if (strcasecmp(want_sha, hex) != 0) { - pmm_error("%s", pmm_tr_fmt("msg.checksum-mismatch", - " expected: %s\n actual: %s\n", name, want_sha, hex)); + pmm_error("%s", pmm_tr_fmt("msg.checksum-mismatch", name, want_sha, hex)); remove(path); rc = -1; } else { diff --git a/src/main.c b/src/main.c index f59a334..416bebd 100644 --- a/src/main.c +++ b/src/main.c @@ -598,7 +598,7 @@ static int cmd_install_git(int argc, char **argv, const char *flag) { "(tried gitea/gitlab/github shapes)\n", repo); if (!asset) { if (host != HOST_AUTO) - pmm_error("%s", pmm_tr_fmt("msg.no-suitable-asset", pmm_os_name(os)), repo); + pmm_error("%s", pmm_tr_fmt("msg.err.no-suitable-asset", pmm_os_name(os), repo)); repo_close(ctx); return 1; } diff --git a/src/pdm.c b/src/pdm.c index 6c520d3..6417fb7 100644 --- a/src/pdm.c +++ b/src/pdm.c @@ -422,7 +422,7 @@ int pdm_install_file(const char *pdmfile) { char mp[1200]; snprintf(mp, sizeof(mp), "installed/.stage/%s", fname); if (pmm_sha256_file(mp, hex) != 0 || strcasecmp(hex, expect) != 0) { - pmm_error("%s", pmm_tr_fmt("msg.checksum-mismatch", fname, pdmfile)); + pmm_error("%s", pmm_tr_fmt("msg.err.checksum-mismatch-file", fname, pdmfile)); fclose(sf); chdir_restore(); remove(tmpname); return -1; } } diff --git a/src/pmm.c b/src/pmm.c index 0cf4ead..33963d6 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -532,6 +532,6 @@ void pmm_reg_uninstall_clear(const char *pkg) { "%%SystemRoot%%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NoProfile -Command \"Remove-Item -Path 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s' -Recurse -Force -ErrorAction SilentlyContinue\" 2>nul", pkg); system(cmd); - pmm_success("%s", pmm_tr_fmt("msg.removed", pkg)); + pmm_success("%s", pmm_tr_fmt("msg.unregistered", pkg)); #endif } diff --git a/web/mirror/lang/en-US.pjson b/web/mirror/lang/en-US.pjson index ceb4409..d9a6a30 100644 --- a/web/mirror/lang/en-US.pjson +++ b/web/mirror/lang/en-US.pjson @@ -32,10 +32,12 @@ "opt.verbose": "print extra detail", "msg.looking-up": "looking up %s in mirror %s", "msg.selected": "selected %s@%s (os=%s arch=%s)", - "msg.downloading": "downloading %s", + "msg.downloading": "downloading %s%s", "msg.downloaded": "downloaded %s", - "msg.sha256": "sha256: %s", - "msg.sha1": "sha1: %s", + "msg.hash-sha256": "sha256: %s", + "msg.hash-sha1": "sha1: %s", + "msg.sha256": "sha256: %s %s", + "msg.sha1": "sha1: %s %s", "msg.installing": "installing %s ...", "msg.installing-file": "installing local file %s", "msg.installed": "installed %s", @@ -50,6 +52,7 @@ "msg.upgrading": "%s: %s -> %s", "msg.upgraded": "upgraded %d package(s).", "msg.no-installed": "no installed packages.", + "msg.registry-empty": "registry index is empty.", "msg.registry-updated": "updated registry index: %d/%d packages cached.", "msg.skipping-no-registry": "skipping %s: no registry entry", "msg.no-match": "no package matches '%s'", @@ -73,6 +76,9 @@ "msg.err.usage": "usage:", "msg.err.not-found": "package '%s' not found", "msg.err.not-installed": "package '%s' is not installed", + "msg.err.empty-path": "empty file path", + "msg.err.registry-not-found": "package '%s' not found in any registry mirror", + "msg.err.no-suitable-asset": "no suitable %s asset found in latest release of %s", "msg.err.unknown-cmd": "unknown command '%s' (try 'pmm help')", "msg.err.failed-install": "failed to install %s", "msg.err.cannot-write": "cannot write %s", @@ -86,6 +92,8 @@ "msg.err.no-registry-index": "no registry index (packages.json) available", "msg.err.bad-registry-index": "bad registry index", "msg.err.bad-entry": "bad registry entry '%s'", + "msg.err.bad-registry-entry": "bad registry entry for '%s' (%s)", + "msg.err.checksum-mismatch-file": "checksum mismatch for %s in %s", "msg.err.no-control": "%s has no pdm-control file", "msg.err.no-package": "pdm-control missing 'Package:' field", "msg.err.tar-control": "tar (control) failed", @@ -98,7 +106,6 @@ "msg.err.oom": "out of memory", "msg.err.json-parse": "JSON parse error: %s", "msg.err.unknown-host": "unknown host '%s'", - "msg.err.no-suitable-asset": "no suitable %s asset found in latest release of %s", "msg.err.checksum-refuse": "refusing to install: checksum verification failed", "msg.err.registry-entry-no-url": "registry entry for '%s' has no url", "msg.err.rpm-stage": "cannot create rpm stage dir: %s", diff --git a/web/mirror/lang/zh-CN.pjson b/web/mirror/lang/zh-CN.pjson index 875e3d2..8b135e8 100644 --- a/web/mirror/lang/zh-CN.pjson +++ b/web/mirror/lang/zh-CN.pjson @@ -32,10 +32,12 @@ "opt.verbose": "打印更多细节", "msg.looking-up": "在镜像 %s 中查找 %s", "msg.selected": "已选择 %s@%s (os=%s arch=%s)", - "msg.downloading": "下载 %s", + "msg.downloading": "下载 %s%s", "msg.downloaded": "已下载 %s", - "msg.sha256": "sha256: %s", - "msg.sha1": "sha1: %s", + "msg.hash-sha256": "sha256: %s", + "msg.hash-sha1": "sha1: %s", + "msg.sha256": "sha256: %s %s", + "msg.sha1": "sha1: %s %s", "msg.installing": "正在安装 %s ...", "msg.installing-file": "正在安装本地文件 %s", "msg.installed": "已安装 %s", @@ -50,6 +52,7 @@ "msg.upgrading": "%s: %s -> %s", "msg.upgraded": "已升级 %d 个软件包。", "msg.no-installed": "没有已安装的软件包。", + "msg.registry-empty": "注册表索引为空。", "msg.registry-updated": "注册表索引已更新: %d/%d 个软件包已缓存。", "msg.skipping-no-registry": "跳过 %s: 没有注册表条目", "msg.no-match": "没有匹配 '%s' 的软件包", @@ -73,6 +76,9 @@ "msg.err.usage": "用法:", "msg.err.not-found": "找不到软件包 '%s'", "msg.err.not-installed": "软件包 '%s' 未安装", + "msg.err.empty-path": "文件路径为空", + "msg.err.registry-not-found": "在任一注册表镜像中找不到软件包 '%s'", + "msg.err.no-suitable-asset": "在最新发布中找不到适用于 %s 的资源 %s", "msg.err.unknown-cmd": "未知命令 '%s'(试试 'pmm help')", "msg.err.failed-install": "安装 %s 失败", "msg.err.cannot-write": "无法写入 %s", @@ -86,6 +92,8 @@ "msg.err.no-registry-index": "没有可用注册表索引 (packages.json)", "msg.err.bad-registry-index": "注册表索引格式错误", "msg.err.bad-entry": "软件包 '%s' 的注册表条目错误", + "msg.err.bad-registry-entry": "软件包 '%s' 的注册表条目错误 (%s)", + "msg.err.checksum-mismatch-file": "文件 %s 与 %s 校验不匹配", "msg.err.no-control": "没有 pdm-control 文件: %s", "msg.err.no-package": "pdm-control 缺少 'Package:' 字段", "msg.err.tar-control": "tar(control)失败", @@ -98,7 +106,6 @@ "msg.err.oom": "内存不足", "msg.err.json-parse": "JSON 解析错误: %s", "msg.err.unknown-host": "未知的主机 '%s'", - "msg.err.no-suitable-asset": "在最新发布中找不到适用于 %s 的资源 %s", "msg.err.checksum-refuse": "拒绝安装: 校验和验证失败", "msg.err.registry-entry-no-url": "软件包 '%s' 的注册表条目没有 url", "msg.err.rpm-stage": "无法创建 rpm 解包目录: %s",