为 TTPlayer 重建版提供可选的 gettext 翻译支持。本目录保存 DLL 源码、翻译文件和提取工具,
通过 api.h 中带版本号的 C ABI 与播放器交互。
实现为项目自有代码,不依赖 libintl.dll 或 libiconv.dll。
gettext 和 rebuild 分别构建、分别发布,通过版本化 C ABI 在运行时交互。
本仓库包含自己的接口头文件、兼容运行库配置、导入审计和依赖许可,可单独克隆构建。
在本仓库根目录执行:
./build.ps1 -PackageDLL 和翻译分别输出到 build/Release/AddIn/ttp_i18n.dll 和 build/Release/i18n。
只修改翻译文件后,重新构建也会复制更新的文件。
如果使用包含 gettext、rebuild 两个目录的本地工作区,也可在工作区根目录执行:
cmake -S gettext -B gettext/build -G "Visual Studio 18 2026" -A Win32
cmake --build gettext/build --config Release --target ttp_i18nDLL 和翻译目录分别输出到 gettext/build/Release/AddIn/ttp_i18n.dll 和
gettext/build/Release/i18n。
普通版和 XP/Win7 兼容版共用同一份 x86 ttp_i18n.dll。
DLL 始终使用 VC-LTL 的 XP 运行库和 YY-Thunks 系统 API 适配,
并自动检查 XP/Win7 导入兼容性,不需要分别维护两个版本。
播放器构建独立完成,不编译本仓库,也不复制本仓库的翻译文件。
DLL 的 Debug 配置也使用兼容运行库,保留调试符号;发布时使用 Release。
首次构建会下载固定版本并校验哈希的 VC-LTL 和 YY-Thunks,需要 MSVC、Win32 工具链
及 Python 3。审计报告输出为 i18n-legacy-imports.json,依赖许可输出到 licenses,
这些文件保留在构建目录。
在本仓库的 Actions → Manual i18n Windows Build → Run workflow 手动运行
构建工作流。configuration 可选择
Release(默认)、RelWithDebInfo 或 Debug。
勾选 Release a Version (GitHub) 后,构建和导入审计通过时自动创建 GitHub Release;
发布必须选择 Release 配置。默认不勾选,仅生成 Actions 构建产物。
工作流使用 GitHub 官方 Windows Server 2025/VS 2026 镜像, 构建 x86 DLL,并检查 DLL 的 XP/Win7 静态导入;测试仅在本地运行。 ABI、兼容构建脚本、导入检查脚本和所需许可均随本仓库提供。
成功后,在该次运行的 Artifacts 下载 ttp_i18n-Windows-x86-配置-运行编号。
其中的 ttp_i18n-x86-YYYY.MM.DD.zip 使用构建开始时捕获的北京时间日期,仅包含:
AddIn/ttp_i18n.dll,由两版播放器共用。i18n下的简体、繁体、英文翻译及模板。SHA256SUMS.txt,记录 DLL 和i18n目录内各文件的校验值。
ZIP 的 SHA-256 清单及用于核对构建来源的 build-info.json 随 Actions 产物提供,
构建信息不放入 ZIP;Release 不生成 PDB,调试配置可保留符号。产物保留 14 天,
失败时上传配置/导入审计诊断并保留 7 天。构建和发布准备只使用仓库读取权限,
仅 GitHub Release 发布任务使用 contents: write,通过内置 GITHUB_TOKEN 发布。
导入检查用于验证加载依赖,旧系统上的实际行为仍需在对应系统中测试。
版本号沿用 rebuild 的规则,但在本仓库独立计算:当天首次发布为 YYYY.MM.DD,
当天已有版本则使用 YYYY.MM.DDp1、YYYY.MM.DDp2 等,按已有最大补丁号递增。
工作流分页读取本仓库的标签和 Release,草稿 Release 也占用版本号;
发布运行共用一个并发组,覆盖构建、版本分配和发布,普通构建可独立运行。
日期在构建开始时确定,即使构建跨过北京时间午夜,发布仍使用该日期。
发布按“确定版本并构建 → 准备发布 → GitHub Release”进行。准备和发布时均核对提交、
配置及 ZIP 的 SHA-256。最终附件为 ttp_i18n-x86-版本号.zip 和 SHA256SUMS.txt,
最终补丁号在编译前分配并写入 DLL;准备发布阶段只验证并转交该版本的发行包。
Release 标题和标签均为版本号,标签指向本次构建提交;说明包含完整更新日志链接和安装步骤。
已有版本不会被覆盖,重新完整运行工作流时会根据当时已占用的版本号重新分配。
本地打包可在本仓库根目录执行:
./tools/package.ps1 -BuildDirectory build -Configuration Release -Destination artifact打包脚本会检查 DLL 与兼容审计报告的 SHA-256 一致,并检查翻译齐全。
本地不传版本号时使用北京时间日期;若 DLL 已使用指定版本构建,打包时必须传入相同
-PackageVersion。脚本会检查 DLL 的文件版本和固定数字版本,防止只改 ZIP 名称。
推荐使用 ./build.ps1 -Package 连续完成版本确定、构建、审计和打包。
本次日期/补丁分配回归测试位于本地 rebuild/tests/dll_size_versions,使用模拟 API,不创建远程 Release。
将 DLL 放入播放器的 AddIn 目录,翻译文件放入播放器旁的 i18n/<语言> 目录:
TTPlayerRebuild.exe
ttpcomm.dll
ttpres.dll
AddIn/
ttp_i18n.dll
i18n/
chs/
ttplayer.po # 简体中文
cht/
ttplayer.po # 繁體中文
en_US/
ttplayer.po
ttplayer.mo # 可选
在“选项 → 常规 → 选项”的“界面语言”下拉框中选择语言,重启后生效。设置保存在
TTPlayerRebuild.xml 的 General/@Language:auto 跟随系统界面语言,
source 使用原始文本,也可指定 chs、cht、en_US 等语言标识。
简体中文的 zh_CN、zh_SG、zh-Hans、zh_CHS 会查找 chs;
繁体中文的 zh_TW、zh_HK、zh_MO、zh-Hant、zh_CHT 会查找 cht。
加载顺序为具体语言及其父级目录、chs/cht 别名目录、通用 zh;
显式脚本标识优先于地区,例如 zh-Hant-CN 使用 cht。
系统自动语言和旧配置中的 zh_CN/zh_TW 因此无需改名即可使用中文 PO。
同一语言存在有效的 ttplayer.mo 时优先读取 MO;MO 缺失或无效时读取 PO。
有效 MO 缺少某个词条时,不再读取同语言的 PO,而是尝试父语言,然后回退原文。
修改 PO 后应重新生成或移除旧 MO,并重启播放器。只有 PO 也能运行,无需安装 gettext 工具。
PO 使用 UTF-8,支持 BOM、多行字符串、C 转义、msgctxt 和复数形式;
MO 支持版本 0 的大小端格式。空译文、模糊(fuzzy)条目和废弃条目不参与翻译。
格式不兼容的译文也会回退。没有 DLL、DLL 接口不兼容或没有可用翻译时,
播放器继续使用 ttpres.dll 资源及重建版自建文本。
播放器直接读取 ttpres.dll 和 EXE 的字符串表、菜单及对话框原文,不再编译
resource_messages.inc 文本副本。DLL 加载 PO/MO 时为 ttpres/、exe/ 下的
字符串、菜单和对话框词条建立资源上下文索引:优先精确匹配 msgctxt + msgid,
原文语言不同时使用唯一的资源上下文匹配。上下文对应多个有效原文时不猜测译文。
格式占位符、分隔符和过滤模式按当前加载资源校验;缺词或校验失败即显示该资源原文。
资源本身不存在时返回空文本。自建文本和复数仍按原有 gettext 键精确匹配。
接口继续兼容 ABI v1;部署时同时更新 EXE 和 DLL,可获得上述跨资源语言匹配能力。 旧 DLL 仍可加载,但它只能按实际资源原文精确查找,未命中时显示资源原文。
正常播放器启动时,先尝试加载 EXE 目录下的 AddIn/ttp_i18n.dll,再主动加载并初始化
ttpcomm.dll。此时只读取配置中的语言并初始化翻译,完整设置和皮肤仍在后续阶段加载,
DLL 保持到会话结束。因此启动阶段的错误弹窗也可以使用所选语言。
私有插件工作进程沿用原有启动流程。
音频插件扫描会跳过 ttp_i18n.dll,不会将它列为音频插件或插件加载错误。
MessageBox 的正文和标题使用同一套翻译:资源提示按 msgctxt 查找,
代码中的固定提示使用 app 上下文。包含文件路径、曲目名或错误码的提示,
先翻译固定文本,再填入实际数据;缺少译文时继续显示原文。
XP/Win7 兼容版有一项例外:为保证 XP 上 ttpcomm.dll 的静态线程局部存储(TLS)正常,
EXE 保留了对它的启动导入,因此 Windows 会在入口函数运行前加载它。
该版本只保证程序主动加载阶段先处理 i18n,不能保证系统加载器实际先映射 ttp_i18n.dll。
ttp_i18n.dll 始终是可选组件,不会成为 EXE 的强制导入依赖。
翻译模板位于 i18n/ttplayer.pot。语言文件分别为
简体中文、繁體中文
和 English。简繁中文已补齐当前模板;英文仍为部分翻译。
各 PO 按自建文本、重建版资源、ttpres 字符串表、菜单及对话框分节,使用相同的
msgctxt 和 msgid,便于维护同一套模板。资源原文语言差异由 DLL 的资源上下文索引处理。
新增语言采用相同目录结构。
请保留 msgctxt、格式占位符(如 %d、%s、%(Title))、结构化字符串的
| 和换行分隔符,以及文件过滤模式。
从工作区根目录更新模板:
python gettext/tools/extract_catalog.py脚本扫描重建版代码,并复用现有 gettext/i18n/ttplayer.pot 中的资源词条,
将模板写回 POT,不生成主程序文本表。需要重新提取原始资源时,可传入
--ttpres ttpres.dll --exe TTPlayer.exe;提取二进制资源需要 Windows。
--rebuild 可指定重建版源码目录,--output 可指定模板输出文件,
--resource-template 可指定用于复用资源词条的 POT。构建 DLL 和播放器、运行播放器均无需 POT。
已有 ttpres/chs/texts.json 和 ttpres/cht/texts.json 导出文件时,可按资源 ID
补充新增字符串,并同步三个语言目录:
python gettext/tools/extract_catalog.py --resource-texts ttpres/chs/texts.json --resource-texts ttpres/cht/texts.json
python gettext/tools/sync_catalogs.py
python gettext/tools/sync_catalogs.py --check--resource-texts 只补充缺失的字符串表 ID,保持已有资源原文稳定。本次繁体资源中
独有的 ttpres/string/136 更新提示以繁体原文作为 msgid,简体 PO 提供对应译文。
重新从 DLL 提取资源时也应带上这两个参数,以保留另一个版本新增的字符串。
同步脚本按上下文匹配 ttpres 导出的菜单、对话框和字符串表,只填充空译文,
保留已有人工修改和模糊标记,将退出模板的条目保留为废弃条目。
字体、控件实现标签、URL、版本信息及嵌入文件不纳入界面翻译。
重建版自建文本直接在 PO 中维护。繁体资源的一处格式说明保留了原文占位符
%(字段名),其余内容采用提供的繁体资源文本。若当前资源将此占位符写为其他文字,
该条会因格式不匹配而回退为当前资源中的说明。
--check 只检查同步状态,不写入文件;脚本不生成 MO。
如已安装 GNU gettext 工具,可在工作区根目录生成 MO:
msgfmt --check --check-format -o gettext/i18n/en_US/ttplayer.mo gettext/i18n/en_US/ttplayer.po本仓库构建时启用 BUILD_TESTING=ON,然后运行翻译解析和目录校验:
cmake --build build --config Release --target ttp_i18n ttp_i18n_catalog_tests --parallel 4
ctest --test-dir build -C Release --output-on-failure在含两个仓库的本地工作区中,需要播放器界面和启动弹窗集成测试时,可将已经构建好的
DLL 绝对路径传入播放器的 TTPLAYER_I18N_TEST_DLL,再构建和运行播放器测试:
cmake -S rebuild -B rebuild/build -G "Visual Studio 18 2026" -A Win32 -DBUILD_TESTING=ON -DTTPLAYER_STAGE_RUNTIME=OFF "-DTTPLAYER_I18N_TEST_DLL=$((Resolve-Path gettext/build/Release/AddIn/ttp_i18n.dll).Path)"
cmake --build rebuild/build --config Release --target i18n_ui_tests --parallel 4
ctest --test-dir rebuild/build -C Release -R "^(i18n_ui_tests|i18n_startup_tests)$" --output-on-failure翻译校验会检查简繁中文的模板覆盖、占位符、分隔符及过滤模式,并验证资源导入和
重复同步不会覆盖人工修改。独立执行:python gettext/tests/translation_tests.py。
DLL 的文件版本和产品版本使用北京时间 yyyy.MM.dd,同日发布补丁使用 pN;
例如 2026.10.06p1 对应固定数字版本 2026.10.6.1。Actions 在编译前确定最终版本,
DLL、发行包和发布标签使用同一版本。各项目继续独立构建。
Release 的统一配置见 cmake/size_release.cmake:
/O1 /Os /Gy /Gw /GF、跨模块优化和链接去除未引用代码/折叠相同代码,关闭 Release 调试信息。
本项目经 /Ob0、/Ob1、/Ob2 对比,默认选择 /Ob2;
可用 -DTTP_SIZE_INLINE_LEVEL=0|1|2 重新测量不同内联策略。
保留正常浮点语义、异常处理及 VC-LTL/YY-Thunks 的 XP/Win7 兼容配置。
Actions 不编译、不运行测试;本次新增的测试仅位于本地 rebuild/tests/dll_size_versions,不进入发行包。
本地构建、补丁号分配及版本资源说明见 日期版本构建。