Umi-OCR 多语言翻译工作流:面向非程序员的 .ts 翻译、.qm 编译与语言切换实战
本文以 Umi-OCR 仓库的 dev-tools/i18n/翻译步骤(简易).md 为主体,完整讲解非程序员译者从获取代码、用 Qt Linguist 翻译 .ts 工程文件,到编译 .qm 二进制包并在软件全局设置中验证语言的端到端流程。同时结合 UmiOCR-data/py_src/utils/i18n_configs.py 的语言加载源码与仓库内批处理脚本,补充"区域语言代码如何自动映射到最接近的翻译文件"等底层机制,读完即可独立为 Umi-OCR 贡献一种语言的 UI 翻译。
1. 翻译管线总览:为什么只需编辑一个文本文件
Umi-OCR 的界面基于 Qt-Qml 框架,其本地化(i18n)遵循 Qt 标准的三段式管线:
- 提取:用
lupdate从源代码中扫描所有待翻译字符串,生成某个语言的.ts工程文件(XML 格式); - 翻译:用 Qt 的图形化工具
linguist打开.ts文件,逐条填写译文; - 编译:用
lrelease(或 linguist 菜单)把.ts编译为运行时加载的二进制文件.qm。
所谓"简易流程",就是针对第 1 步已经完成的情形:仓库中已经为每种语言维护好了 .ts 工程文件(内含机器翻译或其他译者的既有进度),译者只需完成第 2、3 步。这也是"简易"版文档与完整版文档的分工——本文主体覆盖简易版全部内容,凡涉及"从零生成 .ts"或"批量刷新所有语言"的场景,再引向 翻译步骤(完整).md。
2. 获取代码:Git 用户与不用 Git 用户的两条路径
2.1 会用 Git
请先 fork 或 clone 本仓库。强烈建议只 clone 主分支,因为某些分支含有体积很大的二进制库,会让下载花费很长时间:
git clone --branch main --single-branch https://gitcode.com/GitHub_Trending/um/Umi-OCR
--branch main --single-branch 的作用是只取主分支的提交历史与文件,跳过其它分支,避免拉取到携带大体积二进制依赖的分支。
2.2 不会用 Git
- 在代码托管平台 fork 本项目;
- 下载本项目的 zip 包:进入项目主页 → 绿色
Code按钮 →Download ZIP; - 解压后直接进行翻译工作。
两种方式的后续操作完全一致,唯一差别在第 10 节"提交贡献"环节。
3. 认识翻译工程文件:一种语言一个 .ts 文件
翻译工作全部集中在仓库的 dev-tools/i18n 目录(相对仓库根目录)。该目录下已内置整套 Qt 工具链与依赖,无需自行安装:
linguist.exe:可视化翻译编辑器(本流程的核心工具);lupdate.exe/pyside2-lupdate.exe:从源代码提取待翻译字符串;lrelease.exe:命令行编译.qm;Qt5Core.dll、Qt5Gui.dll、Qt5PrintSupport.dll、Qt5Widgets.dll、Qt5Xml.dll及plugins/子目录:linguist 等 Qt 工具在 Windows 上运行所需的运行时库与平台插件;release/子目录:各语言.ts工程文件的集中存放处。
当前目录下有多个翻译工程文件,文件名与对应语言如下(继承自简易版文档的对照表):
| 文件 | 语言 |
|---|---|
zh_CN.ts |
简体中文 |
zh_TW.ts |
繁體中文 |
en_US.ts |
English |
es_ES.ts |
Español |
fr_FR.ts |
Français |
de_DE.ts |
Deutsch |
ja_JP.ts |
日本語 |
ko_KR.ts |
한국어 |
ru_RU.ts |
Русский |
pt_BR.ts |
Português |
it_IT.ts |
Italiano |
这些文件中已经记录了部分工作进度(机器翻译,或者其他译者的工作),不是空白文件。你擅长哪种语言,就打开对应的文件,修改原有翻译或补充新的翻译即可。
从仓库现状看,dev-tools/i18n/release 目录中实际已维护了 15 个语言的 .ts 文件,包括上表之外的 ar(阿拉伯语)、es、fa(波斯语)、he(希伯来语)、kab、uz(乌兹别克语)、vi(越南语)等,译者可以比上表选择更宽。
如果没有找到对应语言的文件,请参考 翻译步骤(完整).md 用 lupdate 从零生成;单个文件的生成命令形如:
lupdate.exe "../../UmiOCR-data/qt_res/qml" -recursive -ts "en_US.ts"
即递归扫描 Qml 源码目录 UmiOCR-data/qt_res/qml,输出/刷新指定语言的 .ts。如果命令行提示无法识别 lupdate.exe,在指令最前面加 ./ 即可。文档还指出:如果已经开始编辑 .ts 文件,重新调用 lupdate 是安全的,不会丢失已编辑的进度(当然建议多备份)。
4. 用 linguist 翻译:四个功能区速查
将对应的 .ts 文件拖入本目录的 linguist.exe 图标上即可打开翻译窗口(也可以双击 linguist.exe 后打开文件)。linguist 的用法很简单,下面介绍基础用法:
- 左侧
Context栏:表示待翻译的源代码文件,以及每个文件的文本条数。如BatchOCR 18/19表示源代码BatchOCR一共有 19 条文本,其中 18 条已完成翻译。 - 中上
Strings栏:表示当前源代码文件的每一条文本。图标?/!表示未翻译或未检查,√表示已翻译。每翻译一条文本,记得点击该图标,将它转为√,这是进度统计的关键操作。 - 右侧
Sources and Forms栏:表示该文本在源代码中的位置。可以结合代码中的注释来进行翻译。 - 中心栏:进行翻译。
Source text为原文本,Translation to XXX填写翻译文本,Translator comments for XXX可以不用写。
首次打开某个 .ts 文件时,linguist 会弹窗询问源语言和目标语言:源语言选择 Chinese (简体中文)(Umi-OCR 的原生语言),目标语言按自己负责的语言选择,Country 一般选 Any Country 即可。
开始工作前,请务必阅读 翻译注意事项.md,其中有四条对翻译正确性至关重要的规则,摘录如下。
4.1 换行符:用直接换行,不要输入 \n
源代码中以 \n 表示的换行符,在 linguist 中会转换为直接换行(结尾显示为类似音符的符号)。翻译时也应该直接回车换行,而不是插入字面的 \n。例如源文本 这是第一行\n这是第二行,正确译文是两行物理换行,而不是 This is the first line\nThis is the second line。
4.2 占位符 %1 必须原样保留
待翻译文本中可能含有 %数字 格式的占位符(运行时会被替换为动态内容,如端口号)。翻译时须保留所有占位符。例:原端口号%1被占用,\n切换为新端口号%2。 应译为同时包含 %1 与 %2 的英文句子,不能删除或调换其相对含义。
4.3 Markdown 长文本:保留 # 与全角空格
部分源文件(如 PagesManager)含 Markdown 格式的长字符串。务必遵照原文格式编写译文,保留 # 以及 (1 个全角空格 + 2 个半角空格)这类特殊字符——这段"特殊字符"的作用是让 Qml 的 Markdown 解析器空出一行,直接复制原文中的该片段即可。
4.4 字体缩放系数:行高不变,调文字大小
Umi-OCR 界面中很多 UI 组件的尺寸与行高绑定(例如按钮宽度为 5 倍行高、高度为 1.5 倍行高),这些系数以中文为基准设定。相同句子在不同语言中占地并不相同(如 截屏 vs Screenshot),因此使用其它语言 UI 时需要适当缩小文字尺寸:行高不变,调整文字大小。
实现方式是翻译文件中 Size_ 上下文里的一条数字文本 1.0,对应源码中的 property string languageScale: qsTr("1.0")。把它改为 0.92 之类的小数值即可调整该语言的字体缩放。便捷测试办法:打开 Umi-OCR 的"全局设置"页,勾选"高级",拉到最底部 developer tools → languageScale (textScale),调整该数字可实时预览字体缩放;确认合适的数值后再回填到翻译文件中。
5. 编译二进制包:File → Release
完成翻译与校验后,在 linguist 内点击菜单 File → Release,即可在本目录下编译生成 en_US.qm(假设工程文件为 en_US.ts)。
除了图形界面,也可在 dev-tools/i18n 目录下用命令行完成同样的事:
lrelease.exe "en_US.ts"
6. 放置翻译文件并在软件中验证
将编译好的 .qm 文件拷贝到仓库根目录下的 UmiOCR-data/i18n 目录(简易版文档中写作 Umi-OCR_v2/UmiOCR-data/i18n,是相对于 clone 出的工程根目录的路径,含义相同)。
该目录当前已存放若干语言包,例如 en_US.qm、ja_JP.qm、zh_TW.qm、ru_RU.qm、pt.qm、ta.qm,新语言的 .qm 与之并列即可被软件发现。
启动 Umi-OCR,即可在全局设置页面切换到该语言(如上图所示,界面和外观分组下提供"语言 / Language"选项)。请仔细检查翻译文本是否正确、尺寸是否合适;如果英文等长文本出现挤压或截断,按第 4.4 节的方法调整字体缩放系数。
7. 源码解析:Umi-OCR 如何发现并加载 .qm 文件
上面"放到 i18n 目录就能被切换"并不是巧合,其机制可以在 i18n_configs.py 中得到完整印证。
语言表与默认语言。 文件开头定义:
I18nDir = "i18n" # 翻译文件 目录
DefaultLang = "zh_CN" # 默认语言,项目中qsTr()标记的原生语言,无翻译文件
LanguageCodes 字典(第 16~43 行)登记了当前启用的语言及其显示名:简体中文 zh_CN、繁體中文 zh_TW、English en_US、日本語 ja_JP、Русский ru_RU、Português pt、தமிழ் ta。同时注释块中保留了 ko_KR、fr_FR、it_IT、de_DE、es_ES 等"暂未启用的语言"——从源码结构看,这与简易版文档语言表中列出的部分语言(如德语、意大利语、韩语)当前尚无对应 .qm 进入正式语言表的情况相互印证;若新增一种未登记语种,需要在该文件中补充标识符映射。
区域代码的自动映射。 LanguageCodes 采用"同语种多个代码、第一个有效"的组织方式,例如:
zh_HK、zh_MO、zh_SG→zh_TW(繁体中文)en_GB、en_AU、en_CA→en_US(英语)pt_BR、pt_PT→ptta_TA→ta
注释明确说明:每个语种只有第一个语言代码是有效的(对应到翻译文件 .qm),其余语言代码会映射到第一个。这就是"语种相同但地区不同的系统会自动应用最接近的翻译文件"的实现来源。
扫描目录生成语言列表。 _getLangPath()(第 107 行起)遍历 i18n 目录,把每一个 .qm 文件的文件名(去掉扩展名)作为语言代码登记进 langDict,显示名优先取 LanguageCodes 的映射,未登记时直接以代码作为显示文本。由此可以推断:语言下拉列表是由目录中实际存在的 .qm 文件动态生成的,这也解释了为何新增语言只需投放文件而无需改主程序。
加载与安装翻译器。 init()(第 69 行起)创建 QTranslator,用 translator.load(path) 加载 .qm,再经 qtApp.installTranslator(translator) 安装到 Qt 应用上;任一环节失败都会记录日志并弹窗告警。加载成功后日志输出 i18n file loaded successfully. {langCode} - {语言名}。此外还会调用 setLangCode(self.langCode) 同步设置插件的翻译语言——Umi-OCR 的插件(如 OCR 引擎组件)使用另一套轻量翻译机制,由 plugin_i18n 模块负责,与主界面的 Qt 翻译并行生效。
语言选择的持久化与回退。 setLanguage(code) 校验代码存在于 langDict 后,通过 pre_configs.setValue("i18n", code) 写入预配置项,下次启动沿用。若预配置为空,程序会读取系统默认 locale(locale.getdefaultlocale()),按 LanguageCodes 做首段代码映射后尝试写入;若系统语言没有对应翻译文件,则回退到默认语言 zh_CN 并记录 warning 日志。这解释了为什么中文系统开箱即用,而其它系统语言用户会自动进入对应语言。
8. 进阶:仓库内置的批量脚本与机器翻译辅助
简易版文档面向单人单语言,而 dev-tools/i18n 目录还配套了几个批处理脚本,译者若想扩展工作可以了解:
lupdate_all.py:一次性刷新所有语言的 .ts。脚本内置 LangList 语言列表(en_US、zh_TW、ja_JP、fr_FR、pt、ru_RU、uz、vi、ta),对每种语言执行(第 31~39 行):
lupdate.exe "../../UmiOCR-data/qt_res/qml" -recursive -no-obsolete \
-source-language "zh_CN" -target-language "{语言}" -ts "release/{语言}.ts"
注意它显式声明 -source-language "zh_CN",并输出到 release/ 子目录。脚本后续部分还准备了"扫描 Python 源码生成第二份 .ts 再合并"的逻辑(用 pyside2-lupdate.exe),但当前在第 41 行 sys.exit() 处提前结束,注释标明"Py翻译的部分 待定",说明该阶段尚未启用。
lrelease_all.py:遍历 release/ 目录中所有 .ts 文件,逐个调用 lrelease.exe 批量编译为 .qm。配合 dev-tools/i18n/README.md 的说明:维护者 git push 后由 Weblate 在线平台同步更新翻译,本地则运行 lupdate_all.py 生成/更新 .ts、运行 lrelease_all.py 生成二进制包,再把 release/ 下的 .qm 拷贝到 Umi-OCR/UmiOCR-data/i18n。
纯文本转换 + 机器翻译流水线。 convert_ts_txt.py 把 .ts 转为纯文本 txt,每行对应一条原文本(换行暂时以字面 \n 表示),命令形如 convert_ts_txt.py en_US.ts,结果 en_US.ts → en_US.txt。此后可以把 txt 交给自动化工具批量翻译,再用 convert_txt_ts.py 覆盖写回 .ts(换行会被自动还原),最后仍需用 linguist 打开逐条检查、校对并编译。使用机器翻译时务必遵守 4.1~4.3 节的格式规则,否则占位符丢失或换行错乱会直接导致运行时显示异常。
9. 提交贡献
9.1 会用 Git
将翻译好的 .ts 文件放在 dev-tools/i18n 本目录下,.qm 文件放在 UmiOCR-data/i18n。不要包含其它无关文件。然后提交 PR。
9.2 不会用 Git
- 找到你翻译好的
xxx.ts文件,用记事本打开,复制全部文本; - 在代码托管平台找到你 fork 出来的仓库(你账号下的仓库),打开相同的
xxx.ts; - 点击右上角的铅笔图标
Edit,清空原有内容,将复制的文本粘贴进去; - 点击右上角
Commit changes; - 找到
Create pull request按钮,向本仓库提交 PR。
小结
Umi-OCR 的翻译贡献被设计成"非程序员友好"的两步操作:用 linguist 编辑现成的 .ts 工程文件,再用 File → Release 编译出 .qm 投放到 UmiOCR-data/i18n 目录——语言发现、区域代码映射、加载与回退全部由 i18n_configs.py 自动完成,译者无需改动任何源代码。配合 release/ 目录中已有的 15 个语言工程文件与批量脚本,这条管线既能支撑单人手工精修,也能承载机器翻译初稿 + 人工校对的规模化流程。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
