首页
/ Umi-OCR 国际化翻译全流程实战:lupdate 提取、Linguist 翻译与 lrelease 编译

Umi-OCR 国际化翻译全流程实战:lupdate 提取、Linguist 翻译与 lrelease 编译

2026-09-05 23:38:01作者:房伟宁

本篇指南完整拆解 Umi-OCR 的 Qt/QML 界面本地化(i18n)工作流:从克隆仓库、用 lupdate 提取待翻译字符串、在 linguist 中逐条翻译,到用 lrelease 编译出 .qm 二进制翻译包并放回工程目录,最后验证与提交贡献。读完本文,你可以独立为 Umi-OCR 翻译一门新语言,也能理解翻译文件是如何被程序加载、以及字体缩放系数如何适配不同语言文字长度的。

Umi-OCR 多语言界面示意:简体中文、繁体中文、日本語、English 四种语言下的全局设置/批量OCR页面

准备工作:环境、目录与语言标识符体系

环境要求与仓库准备

整个翻译流程依赖 Qt 官方工具(lupdate.exelinguist.exelrelease.exe,均已随仓库放在 dev-tools/i18n 目录中,并附带 Qt5Core.dll 等运行库),因此要求 Windows 系统

先 fork 或 clone 仓库。官方强烈建议只 clone 主分支,因为某些分支含体积很大的二进制库(如 OCR 引擎模型),全量下载会花费很长时间:

git clone --branch main --single-branch https://gitcode.com/GitHub_Trending/um/Umi-OCR

后文所有命令如无特别说明,都在工作目录 dev-tools/i18n 下执行。例如按 Win+R 输入 cmd 打开命令行后,跳转到工作目录(假设工程放在 D:\Projects\):

cd /d D:\Projects\Umi-OCR\dev-tools\i18n

注:早期文档中的工程目录名为 Umi-OCR_v2,当前仓库中对应的数据目录为 UmiOCR-data,下文均以当前仓库实际路径为准。

语言标识符表

本文假设目标语言为英语 en_US,若翻译其他语言,请将下文所有 en_US 替换为对应标识符。翻译流程最初支持的标识符全集如下:

标识符 语言
zh_CN 简体中文
zh_TW 繁體中文
en_US English
es_ES Español
fr_FR Français
de_DE Deutsch
ja_JP 日本語
ko_KR 한국어
ru_RU Русский
pt_BR Português
it_IT Italiano

对于语种相同但地区不同的语言(如 zh_HKen_GBen_CAes_MXfr_CAde_ATde_CHpt_PT),程序会应用最接近的翻译文件。这一映射关系就定义在 UmiOCR-data/py_src/utils/i18n_configs.pyLanguageCodes 字典中(L16-L43):每个语种组里只有第一个语言代码是有效的(对应一个 .qm 翻译文件),其余代码都映射到它,例如 zh_HKzh_TWen_CAen_US

从源码结构看,当前 LanguageCodes 中已启用的语言为 zh_CN(含 zh)、zh_TW(含 zh_HK/zh_MO/zh_SG)、en_US(含 en/en_GB/en_AU/en_CA)、ja_JPru_RU(含 ru)、pt(含 pt_BR/pt_PT)、ta(含 ta_TA);而 ko_KRfr_FRit_ITde_DEes_ESnb_NO 等仍处在“暂未启用”的注释块中(L45-L65)。因此,如果想添加一个不属于上述任何语种的翻译,需要在该源码文件中添加对应的标识符映射,或者寻求项目作者的帮助。

总体流程:三步完成一门语言翻译

Qt-Qml 框架的翻译工作流固定为 3 步(以翻译为英语 en_US 为例):

  1. 提取:从源代码中提取所有待翻译字符串,生成 en_US.ts 工程文件;
  2. 翻译:编辑 en_US.ts,把其中的文本逐条翻译成目标语言;
  3. 编译:把写好的 en_US.ts 编译为 en_US.qm 二进制文件。

完成上述工作后,将 en_US.qm 放入 Umi-OCR,即可在全局设置中把语言切换为 English

翻译文件最终由 Python 侧的 _I18n 类加载:i18n_configs.py 中,init() 会创建 QTranslator 实例并调用 installTranslator 安装;而 _getLangPath()L107-L143)会扫描 i18n 目录下所有 .qm 文件,以文件名(去掉后缀)作为语言代码建立可选语言列表,默认语言为 zh_CN(源码中 qsTr() 标记的原生语言,无翻译文件);若用户未设置过语言,程序会取系统默认 locale 尝试匹配,匹配失败则回落到简体中文。这也解释了为什么“放对文件名”如此重要——.qm 的文件名前缀就是语言标识符。

第 1 步:用 lupdate 提取待翻译字符串

方法一:生成/刷新单个语言的 ts 工程文件

使用 Qt 工具 lupdate.exe,在 dev-tools/i18n 目录下执行:

lupdate.exe "../../UmiOCR-data/qt_res/qml" -recursive -ts "en_US.ts"
  • 第一个参数 ../../UmiOCR-data/qt_res/qml 是 QML 源代码目录,-recursive 表示递归扫描;
  • -ts "en_US.ts" 指定输出的翻译工程文件名。

如果提示“无法将‘lupdate.exe’项识别为……”,则在指令最前面加上 ./

./lupdate.exe "../../UmiOCR-data/qt_res/qml" -recursive -ts "en_US.ts"

执行成功时,应输出类似:

Scanning directory '../../UmiOCR-data/qt_res/qml'...
Updating 'en_US.ts'...
    Found 307 source text(s) (140 new and 167 already existing)
    Kept 42 obsolete entries
    Same-text heuristic provided 21 translation(s)

如果已经开始编辑 ts 文件,重新调用 lupdate.exe安全的——它会保留已有的译文,只新增或更新条目(当然,建议多备份)。

方法二:用 lupdate_all.py 刷新所有语言

当你修改了源代码、添加了新文本,需要批量刷新所有语言的 ts 文件时,运行本目录下的 lupdate_all.py。从源码可以看到它的工作方式:

  1. 脚本内维护一个 LangList 语言列表(L9-L25),当前启用 en_USzh_TWja_JPfr_FRptru_RUuzvita 共 9 种,另有 nb_NOit_ITes_ESde_DEko_KRpt_BR 被注释暂不处理;
  2. 对每种语言调用 lupdate.exe 扫描 UmiOCR-data/qt_res/qml,参数为 -no-obsolete -source-language "zh_CN" -target-language "{l}" -ts "release/{l}.ts",即产物统一写入 dev-tools/i18n/release 目录(该目录中现存的 ja_JP.tsen_US.ts 等文件即由此生成);
  3. 脚本后半段还预留了“扫描 Python 源文件(UmiOCR-data/py_src)→ 用 pyside2-lupdate.exe 与临时 .pro 工程文件生成 *_2.ts → 再按 <context> 合并回主 ts 文件”的完整逻辑(L44-L107),不过当前以 sys.exit() 提前结束(注释标注“Py翻译的部分 待定”),实际只执行 QML 部分。

第 2 步:用 linguist 进行翻译

使用 Qt 工具 linguist.exe 可视化翻译:

linguist.exe "en_US.ts"

或者在文件管理器中直接把 en_US.ts 拖到 linguist.exe 图标上。linguist 会打开一个可视化窗口,在上面进行翻译或检查。

如果是首次打开该 ts 文件,linguist 会弹窗询问源语言和目标语言:源语言 Source language 选择 Chinese (简体中文)(因为 Umi-OCR 的原生语言是中文),目标语言自定,Country 一般选 Any Country 即可。

基础用法四要点:

  1. 左侧 Context 栏表示待翻译的源代码文件及每个文件的文本条数。如 BatchOCR 18/19 表示源代码 BatchOCR 一共有 19 条文本,其中 18 条已完成翻译;
  2. 中上 Strings 栏表示当前源代码文件的每一条文本。图标 / 表示未翻译或未检查, 表示已翻译。每翻译一条文本,记得点击该图标将它转为
  3. 右侧 Sources and Forms 栏表示该文本在源代码中的位置,可以结合代码中的注释来翻译;
  4. 中心栏进行翻译:Source text 为原文本,Translation to XXX 填写译文,Translator comments for XXXX 可以不用写。

翻译中的四条硬性注意事项

进行翻译工作前,务必阅读 翻译注意事项,其核心规则有四条:

(1)换行符用直接回车,不要写 \n 源代码中以 \n 表示的换行,在 linguist 中会显示为直接换行(行尾符号类似音符)。翻译时也应该直接回车,而不是输入字面量 \n

这是第一行\n这是第二行          (源码)

错误翻译:

This is the first line\nThis is the second line

正确翻译:

This is the first line
This is the second line

(2)保留 %数字 占位符。 待翻译文本中可能含 %1%2 等占位符,翻译时必须原样保留:

原端口号%1被占用,\n切换为新端口号%2。

正确翻译:

The original port number %1 is occupied.
Switching to the new port number %2.

(3)保留 Markdown 格式与特殊字符。 部分源文件(如 PagesManager)含 markdown 格式的长字符串,翻译必须遵照原文格式,保留 #  (1 个全角空格 + 2 个半角空格,用于让 QML 的 md 解析器空出一行)等特殊字符。

(4)调整字体缩放系数。 Umi-OCR 的 UI 组件尺寸与行高绑定(如按钮宽 5 倍行高、高 1.5 倍行高),这些系数以中文为基准。相同内容在不同语言中占地不同(如 截屏 vs Screenshot),因此需要“行高不变、调整文字大小”。具体做法见下文“字体缩放系数”一节。

进阶:转纯文本批量处理 / 机器翻译

如果本地已安装 Python,可以把 ts 文件拖到 convert_ts_txt.py 上,或用命令行:

convert_ts_txt.py en_US.ts

结果:en_US.tsen_US.txt,每行对应一条原文本。从 convert_ts_txt.py 源码 看,它解析 ts 的 XML 结构、遍历所有 <message><source> 节点逐行写出,并在此阶段把真实换行暂时转写为 \n

这样就能用自动化手段(例如调用大语言模型作为翻译器)处理 en_US.txt,提示词中要求“保留原文的换行、% 开头标识符、markdown 等格式”。翻译完成后:

  1. 将译文覆盖写回 en_US.txt(先备份),用带行号的编辑器逐行核对译文与原文一一对应;
  2. en_US.txt 拖入 convert_txt_ts.py,它会以原 ts 为模板、按顺序把 txt 各行写回 <translation> 节点(同时把 \n 还原为真实换行,见 convert_txt_ts.py#L22),生成 en_US.txt.ts(覆盖前请先备份原 ts);
  3. linguist 打开 en_US.txt.ts 检查、校对,编译为 en_US.txt.qm,重命名为 en_US.qm 即可导入 Umi-OCR 测试。

第 3 步:用 lrelease 编译二进制包

方法一:在 linguist.exe,点击菜单 FileRelease,即可在当前目录生成 en_US.qm

方法二:命令行

lrelease.exe "en_US.ts"

如果是批量刷新全部语言,运行 lrelease_all.py:它遍历 release 目录下所有 .ts 文件,逐个调用 lrelease.exe 编译为同名 .qm(与 README 中“开发者维护流程”一致:lrelease_all.py 生成 → 把 release/ 下的 .qm 拷贝到 UmiOCR-data/i18n)。

放置翻译文件与效果验证

将编译好的 en_US.qm 拷贝到:

UmiOCR-data/i18n

当前仓库该目录已随包内置 6 个翻译包(UmiOCR-data/i18n):en_US.qmja_JP.qmpt.qmru_RU.qmta.qmzh_TW.qm。启动 Umi-OCR 后,即可在全局设置(语言 / Language 项)中切换语言。请仔细检查翻译文本是否正确、尺寸是否合适。

字体缩放系数 languageScale 的实现

针对“同一行高下不同语言文字长度差异”问题,Umi-OCR 内置了语言级字体缩放机制。在 Size_.qml 中:

// 语言缩放系数
// 在相同的行高内,有些语言经过缩放可以表现更好。如英文可以比汉字的字号更小。
// 通过在翻译文件中定义 languageScale 可以单独修改这种语言的缩放。
property string languageScale: qsTr("1.0")

Component.onCompleted: {
    const s = parseFloat(languageScale)
    if(!isNaN(s)) {
        textScale = s
    }
    ...
}

要点:languageScale 本身是一条可翻译文本qsTr("1.0"))。也就是说,在你的 .ts 文件里有一个 Context 为 Size_ 的词条,原文是 1.0——把它翻译成比如 0.92Component.onCompleted 解析后就会让 textScale = 0.92,从而缩小该语言下所有文字尺寸(textsmallTextlargeText 均为“行高 × textScale”),而行高保持不变,正好适配英文等横向较长的文字。

调参技巧:先打开 Umi-OCR 全局设置 标签页,勾选 高级,拉到最底下 developer toolslanguageScale (textScale)(对应 GlobalConfigs.qml#L286 处的开发者选项)。调整该数字可实时预览字体缩放,确定合适数值后再填入翻译文件。

提交贡献

翻译步骤(完整) 的要求:

  • 翻译好的 .ts 文件放在 dev-tools/i18n 目录下(批量流程中则位于其 release/ 子目录,与现有 ja_JP.tsen_US.ts 等保持一致);
  • .qm 文件放在 UmiOCR-data/i18n
  • 不要包含其它无关文件,然后提交 PR。

也可以前往 README 中提及的 Weblate 在线平台补充、订正现有语言翻译或创建新语言(见 dev-tools/i18n/README.md)。更简化的流程可参考同目录下的 翻译步骤(简易),本文则为完整本地化流程的权威说明。

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