首页
/ Umi-OCR 多语言翻译工作流:面向非程序员的 .ts 翻译、.qm 编译与语言切换实战

Umi-OCR 多语言翻译工作流:面向非程序员的 .ts 翻译、.qm 编译与语言切换实战

2026-09-05 17:25:43作者:牧宁李

本文以 Umi-OCR 仓库的 dev-tools/i18n/翻译步骤(简易).md 为主体,完整讲解非程序员译者从获取代码、用 Qt Linguist 翻译 .ts 工程文件,到编译 .qm 二进制包并在软件全局设置中验证语言的端到端流程。同时结合 UmiOCR-data/py_src/utils/i18n_configs.py 的语言加载源码与仓库内批处理脚本,补充"区域语言代码如何自动映射到最接近的翻译文件"等底层机制,读完即可独立为 Umi-OCR 贡献一种语言的 UI 翻译。

Umi-OCR 全局设置中切换界面语言的界面示意(简体中文、繁体中文、日语、英文窗口并排)

1. 翻译管线总览:为什么只需编辑一个文本文件

Umi-OCR 的界面基于 Qt-Qml 框架,其本地化(i18n)遵循 Qt 标准的三段式管线:

  1. 提取:用 lupdate 从源代码中扫描所有待翻译字符串,生成某个语言的 .ts 工程文件(XML 格式);
  2. 翻译:用 Qt 的图形化工具 linguist 打开 .ts 文件,逐条填写译文;
  3. 编译:用 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

  1. 在代码托管平台 fork 本项目;
  2. 下载本项目的 zip 包:进入项目主页 → 绿色 Code 按钮 → Download ZIP
  3. 解压后直接进行翻译工作。

两种方式的后续操作完全一致,唯一差别在第 10 节"提交贡献"环节。

3. 认识翻译工程文件:一种语言一个 .ts 文件

翻译工作全部集中在仓库的 dev-tools/i18n 目录(相对仓库根目录)。该目录下已内置整套 Qt 工具链与依赖,无需自行安装:

  • linguist.exe:可视化翻译编辑器(本流程的核心工具);
  • lupdate.exe / pyside2-lupdate.exe:从源代码提取待翻译字符串;
  • lrelease.exe:命令行编译 .qm
  • Qt5Core.dllQt5Gui.dllQt5PrintSupport.dllQt5Widgets.dllQt5Xml.dllplugins/ 子目录: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(阿拉伯语)、esfa(波斯语)、he(希伯来语)、kabuz(乌兹别克语)、vi(越南语)等,译者可以比上表选择更宽。

如果没有找到对应语言的文件,请参考 翻译步骤(完整).mdlupdate 从零生成;单个文件的生成命令形如:

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 的用法很简单,下面介绍基础用法:

  1. 左侧 Context:表示待翻译的源代码文件,以及每个文件的文本条数。如 BatchOCR 18/19 表示源代码 BatchOCR 一共有 19 条文本,其中 18 条已完成翻译。
  2. 中上 Strings:表示当前源代码文件的每一条文本。图标 / 表示未翻译或未检查, 表示已翻译。每翻译一条文本,记得点击该图标,将它转为 ,这是进度统计的关键操作。
  3. 右侧 Sources and Forms:表示该文本在源代码中的位置。可以结合代码中的注释来进行翻译。
  4. 中心栏:进行翻译。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 toolslanguageScale (textScale),调整该数字可实时预览字体缩放;确认合适的数值后再回填到翻译文件中。

5. 编译二进制包:File → Release

完成翻译与校验后,在 linguist 内点击菜单 FileRelease,即可在本目录下编译生成 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.qmja_JP.qmzh_TW.qmru_RU.qmpt.qmta.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_KRfr_FRit_ITde_DEes_ES 等"暂未启用的语言"——从源码结构看,这与简易版文档语言表中列出的部分语言(如德语、意大利语、韩语)当前尚无对应 .qm 进入正式语言表的情况相互印证;若新增一种未登记语种,需要在该文件中补充标识符映射。

区域代码的自动映射。 LanguageCodes 采用"同语种多个代码、第一个有效"的组织方式,例如:

  • zh_HKzh_MOzh_SGzh_TW(繁体中文)
  • en_GBen_AUen_CAen_US(英语)
  • pt_BRpt_PTpt
  • ta_TAta

注释明确说明:每个语种只有第一个语言代码是有效的(对应到翻译文件 .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_USzh_TWja_JPfr_FRptru_RUuzvita),对每种语言执行(第 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.tsen_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

  1. 找到你翻译好的 xxx.ts 文件,用记事本打开,复制全部文本;
  2. 在代码托管平台找到你 fork 出来的仓库(你账号下的仓库),打开相同的 xxx.ts
  3. 点击右上角的铅笔图标 Edit,清空原有内容,将复制的文本粘贴进去;
  4. 点击右上角 Commit changes
  5. 找到 Create pull request 按钮,向本仓库提交 PR。

小结

Umi-OCR 的翻译贡献被设计成"非程序员友好"的两步操作:用 linguist 编辑现成的 .ts 工程文件,再用 File → Release 编译出 .qm 投放到 UmiOCR-data/i18n 目录——语言发现、区域代码映射、加载与回退全部由 i18n_configs.py 自动完成,译者无需改动任何源代码。配合 release/ 目录中已有的 15 个语言工程文件与批量脚本,这条管线既能支撑单人手工精修,也能承载机器翻译初稿 + 人工校对的规模化流程。

登录后查看全文
热门项目推荐
相关项目推荐