diff --git a/src/i18n.c b/src/i18n.c index 7216675..120d069 100644 --- a/src/i18n.c +++ b/src/i18n.c @@ -43,13 +43,39 @@ int pmm_lang_load(const char *path) { return 0; } +/* Built-in fallback so PMM is usable even before any .pjson is installed. */ +static const char *kBuiltinZh = +"{\"help.usage\":\"用法:\",\"help.commands\":\"命令:\",\"help.options\":\"选项:\"," +"\"cmd.install\":\"install\",\"cmd.remove\":\"remove\",\"cmd.update\":\"update\"," +"\"cmd.upgrade\":\"upgrade\",\"cmd.mirror\":\"mirror\",\"cmd.search\":\"search\"," +"\"msg.looking-up\":\"在镜像 %s 中查找 %s\",\"msg.selected\":\"已选择 %s@%s (os=%s arch=%s)\"," +"\"msg.downloading\":\"下载 %s\",\"msg.downloaded\":\"已下载 %s\"," +"\"msg.hash-sha256\":\"sha256: %s\",\"msg.hash-sha1\":\"sha1: %s\"," +"\"msg.installing\":\"正在安装 %s ...\",\"msg.installed\":\"已安装 %s\"," +"\"msg.checksum-ok\":\"%s 校验 OK: %s\",\"msg.checksum-mismatch\":\"校验不匹配 (%s)!\"," +"\"msg.resolving-dep\":\"正在解析依赖 %s\",\"msg.registry-ok\":\"注册表 sha256 OK: %s\"," +"\"msg.path-exists\":\"PATH 已包含 PMM 目录\",\"msg.err.registry-not-found\":\"找不到软件包 '%s'\"," +"\"msg.err.usage\":\"用法\",\"msg.err.unknown-cmd\":\"未知命令 '%s' (试试 'pmm help')\"," +"\"msg.err.download-failed\":\"下载语言包 %s 失败\",\"msg.err.invalid-locale\":\"无效语言 %s\"," +"\"msg.err.not-found\":\"找不到软件包 '%s'\",\"msg.err.failed-install\":\"安装 %s 失败\"," +"\"msg.err.no-registry-mirror\":\"没有配置注册表镜像\",\"msg.err.cannot-write\":\"无法写入 %s\"," +"\"desc.install\":\"安装\",\"desc.remove\":\"卸载\",\"desc.update\":\"刷新索引\"," +"\"desc.upgrade\":\"升级\",\"desc.mirror\":\"镜像源\",\"desc.search\":\"搜索\"," +"\"desc.info\":\"详情\",\"desc.self-update\":\"更新自身\",\"desc.help\":\"帮助\"," +"\"opt.p-drive\":\"安装盘符\",\"opt.no-color\":\"禁用颜色\",\"opt.quiet\":\"静默\"," +"\"opt.verbose\":\"详情\"}"; + int pmm_lang_load_active(void) { char dir[1024]; pmm_config_dir(dir, sizeof(dir)); char path[1400]; snprintf(path, sizeof(path), "%s/lang/%s.pjson", dir, pmm_lang_locale()); if (pmm_lang_load(path) == 0) return 0; - return 1; /* no pack on disk */ + /* No pack on disk: fall back to the built-in zh-CN so output is readable + * instead of printing raw keys (msg.xxx). */ + JsonValue *root = json_parse(kBuiltinZh); + if (root) { if (g_lang) json_free(g_lang); g_lang = root; return 0; } + return 1; } const char *pmm_tr(const char *key) { diff --git a/src/main.c b/src/main.c index 1468e07..2961e88 100644 --- a/src/main.c +++ b/src/main.c @@ -934,8 +934,23 @@ static int cmd_setting(int argc, char **argv) { if (ml->items[i].registry && *ml->items[i].registry) { base = ml->items[i].registry; break; } if (!base) { pmm_error("%s", pmm_tr("msg.err.no-registry-mirror")); mirrors_free(ml); return 1; } + /* Language packs live under {host}/mirror/lang/, NOT under the registry + * base {host}/mirror/packages. Derive it by swapping the trailing + * "/packages" (if present) for "/lang". */ + char base2[2048]; + snprintf(base2, sizeof(base2), "%s", base); + { + size_t bl = strlen(base2); + static const char *pkgsuf = "/packages"; + size_t pl = strlen(pkgsuf); + if (bl >= pl && strcmp(base2 + bl - pl, pkgsuf) == 0) { + strcpy(base2 + bl - pl, "/lang"); /* .../mirror/packages -> .../mirror/lang */ + } else { + snprintf(base2 + bl, sizeof(base2) - bl, "/lang"); + } + } char url[2048]; - snprintf(url, sizeof(url), "%s/lang/%s.pjson", base, loc); + snprintf(url, sizeof(url), "%s/%s.pjson", base2, loc); mkdir_p_local(langdir); char out[1400]; snprintf(out, sizeof(out), "%s/%s.pjson", langdir, loc); @@ -1049,19 +1064,20 @@ int main(int argc, char **argv) { } } #endif - if (argc < 2) { print_help(); return 0; } - pmm_set_self_path(argv[0]); - argc = consume_drive_flag(argc, argv); - argc = consume_global_flags(argc, argv); - if (argc < 2) { print_help(); return 0; } - /* initialise i18n: use configured language (if any), then load its pack */ + /* initialise i18n BEFORE any output (so `pmm` bare help is localized too). + * Use the configured language (if any), then load its pack (or built-in). */ { PmmConfig cfg; load_config(&cfg); if (cfg.language && *cfg.language) pmm_lang_set_locale(cfg.language); free(cfg.registry_url); free(cfg.mirror_name); free(cfg.language); pmm_lang_load_active(); } + if (argc < 2) { print_help(); return 0; } + pmm_set_self_path(argv[0]); + argc = consume_drive_flag(argc, argv); + argc = consume_global_flags(argc, argv); + if (argc < 2) { print_help(); return 0; } if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { print_help(); return 0;