概述

Qt 为将 Qt C++ 和 Qt Quick 应用程序翻译成当地语言提供了出色的支持。发布经理、翻译和开发人员可以使用 Qt 工具来完成他们的任务。

  • 发布经理对应用程序的发布负总责。通常,他们负责协调开发人员和翻译人员的工作。他们可以使用 lupdate 工具同步源代码和翻译,并使用 lrelease 工具创建运行时翻译文件,供发布的应用程序使用。
  • 翻译人员翻译人员翻译人员可以使用 Qt Linguist 工具翻译应用程序中的文本。除了启动程序和使用文本编辑器或文字处理器的能力外,不需要任何计算机知识。
  • 开发人员必须创建能够使用翻译文本的 Qt 应用程序。他们还应该帮助翻译人员识别短语出现的上下文。开发人员可以使用教程来了解他们的任务。

有关支持的语言和书写系统的更多信息,请参阅 Qt 的国际化

发布经理

布管理器有两个工具:lupdate 和 lrelease。这些工具可以处理 qmake 项目文件,也可以直接在文件系统上运行。

创建翻译文件

翻译文件包含应用程序中所有用户可见的文本和 Ctrl 键加速符,以及这些文本的翻译。

创建翻译文件:

  1. 运行 lupdate 生成第一套翻译源 (TS) 文件,其中包含所有用户可见文本,但没有翻译。
  2. 将 TS 文件交给译员,译员使用 Qt Linguist 添加翻译。Qt 语言学家会处理任何更改或删除的源文本。
  3. 运行 lupdate,将添加到应用程序中的任何新文本纳入其中。lupdate 会将应用程序中用户可见的文本与翻译同步。它不会破坏任何数据。
  4. 要释放应用程序,请运行 lrelease 来读取 TS 文件,并生成应用程序在运行时使用的 QM 文件。

要让 lupdate 成功运行,它必须知道要生成哪些翻译文件。这些文件列在应用程序的 .pro Qt 项目文件中。

使用 lupdate

使用方法:lupdate myproject.pro lupdate 命令行工具在指定的源代码、头文件和 Qt Designer 界面文件中查找可翻译的字符串,并生成或更新 .ts 翻译文件。 要处理的文件和要更新的文件可以在命令行中设置,也可以在作为命令行参数指定的 .pro 文件中提供。

您可按以下方式为单个 QML 文件生成翻译文件:

lupdate main.qml -ts main_en.ts

要制作另一种语言(如法语)的翻译文件,可将 main_en.ts 复制到 main_fr.ts,然后翻译法语 TS 文件中的字符串。lupdate 会处理 .qrc 文件中列出的 QML 文件:

RESOURCES += qml.qrc

让 lupdate 处理所有 QML 文件:

lupdate application.qrc -ts myapp_en.ts

您还可以处理所有 QML 文件,而无需使用 .qrc 文件:

lupdate -extensions qml -ts myapp_en.ts

如果您主要处理 QML 文件,但也有包含要翻译的字符串的 C++ 代码,您可以将其添加到同一命令中:

lupdate qml.qrc filevalidator.cpp -ts myapp_en.ts

翻译文件可以在 .pro 文件中提及,但也可以不提及,只在命令行中指定翻译文件。 例如,生成用于英语和法语的 .ts 文件:

lupdate qml.qrc filevalidator.cpp -ts myapp_en.ts myapp_fr.ts

生成的翻译文件交给翻译人员,翻译人员使用 Qt Linguist 阅读文件并插入译文。

内部有翻译人员的公司可能会发现,随着应用程序的开发,定期运行 lupdate(也许每月运行一次)是非常有用的。这将使翻译工作量在项目生命周期内平均分配,并允许翻译人员同时支持多个项目。

根据需要聘用翻译的公司可能更倾向于在应用程序生命周期内只运行几次 lupdate。第一次可能是在第一个测试阶段之前。这将为译员提供大量的单块工作,而且译员发现的任何错误都可以很容易地与在初始测试阶段发现的错误混在一起。第二次和任何后续的 lupdate 运行可能会在最终测试阶段进行。

lupdate 还可以处理本地化交换文件格式(XLIFF)格式的文件;这种格式的文件通常以 .xlf 后缀结尾。

注意:XLIFF 格式文件的最低支持版本为 1.1。不支持 XLIFF 1.0 版本的文件。

向 lupdate 传递 -help 选项可查看支持的选项。

Qt Linguist 还能导入和导出 XLIFF 文件。更多信息,请参阅 “翻译器 ”部分。

使用 lrelease

使用方法: lrelease myproject.pro

lrelease 命令行工具可从 TS 文件生成 QM 文件。QM 文件格式是一种紧凑的二进制格式,供本地化应用程序使用。它能为翻译提供极快的查找速度。lrelease 处理的 TS 文件可以在命令行中指定,也可以通过 Qt .pro 项目文件间接提供。

从初始测试版本到最终发布版本,只要应用程序要发布,就会运行该工具。如果没有创建 QM 文件,例如因为在进行任何翻译之前需要发布 alpha 版本,那么应用程序将完全可以使用开发人员在源文件中放置的文本运行。一旦有了 QM 文件,程序就会自动检测并使用它们。

lrelease 也可以在不指定 .pro 文件的情况下运行:

lrelease.exe main_en.ts languages\main_fr.ts

向 lrelease 传递 -help 选项可查看支持的选项。

缺失翻译

lupdate 和 lrelease 均可用于不完整的 TS 翻译源文件。 缺失的翻译将在运行时用母语短语替换。

开发人员

在 Qt 应用程序中,对多语言的支持非常简单,几乎不会增加开发人员的工作量。

Qt 在创建每个窗口时都会为其翻译短语,从而将使用翻译的性能成本降至最低。在大多数应用程序中,主窗口只创建一次。对话框通常只创建一次,然后根据需要显示或隐藏。一旦完成初始翻译,翻译后的窗口就不会再有运行时开销。只有那些创建、销毁和后续创建的窗口才会产生翻译性能成本。

使用 Qt 可以创建可在运行时切换语言的应用程序,但需要一定的开发人员干预,当然也会产生一些运行时性能成本。

在 Qt 项目文件中指定翻译源

要使发布管理器能使用 lupdate 和 lrelease,请指定一个 .pro Qt 项目文件。在项目文件的 TRANSLATIONS 部分,必须为母语之外的每种语言指定一个条目。典型的条目如下:

TRANSLATIONS = arrowpad_fr.ts \
               arrowpad_nl.ts

在翻译文件名中使用本地语言有助于确定在运行时加载哪种语言。 更多信息,请参阅 QLocale。 lupdate 工具可从应用程序中提取用户界面字符串。 它读取应用程序的 .pro 文件,以确定哪些源文件包含要翻译的文本。 这意味着您的源文件必须列在 .pro 文件的 SOURCES 或 HEADERS 项中,或者列在 RESOURCE 项中的资源文件中。 如果您的文件没有列出,其中的文本将无法找到。 包含四个翻译源文件的完整 .pro 文件示例:

HEADERS         = main-dlg.h \
                  options-dlg.h
SOURCES         = main-dlg.cpp \
                  options-dlg.cpp \
                  main.cpp
FORMS           = search-dlg.ui
TRANSLATIONS    = superapp_dk.ts \
                  superapp_fi.ts \
                  superapp_no.ts \
                  superapp_se.ts

lupdate 默认将所有源代码编码为 UTF-8。 有 BOM(字节序标记)的文件也可以用 UTF-16 或 UTF-32 编码。 将 qmake 变量 CODECFORSRC 设为 UTF-16,可将无 BOM 的文件解析为 UTF-16。 不过,有些编辑器(如 Visual Studio)默认使用不同的编码。 避免编码问题的方法之一是将源代码限制为 ASCII 编码,并对包含其他字符的可翻译字符串使用转义序列:

label->setText(tr("F\374r \310lise"));

应用程序国际化

设计您的应用程序时,应使其能适应各种语言和地区,而无需进行工程修改。Qt 试图让您尽可能轻松地实现国际化。Qt 中的所有输入控件和文本绘制方法都为所有支持的语言提供内置支持。但在为应用程序编写源代码时,您仍需注意以下事项:

  • 让您的应用程序查找并加载相应的翻译文件。
  • 将用户可见文本和 Ctrl 键盘加速器标记为翻译目标。
  • 为要翻译的文本提供上下文。
  • 消除相同文本的歧义。
  • 使用编号参数 (%n) 作为参数占位符,在运行时用文本或数字替换。
  • 将数字、日期、时间和货币国际化。
  • 标记函数外的可翻译数据文本字符串。

您可以开发在同一应用程序中同时使用 C++ 和 QML 源的应用程序,甚至在两种源中都有用户界面字符串。这些工具会创建一个合并的翻译文件,而 C++ 和 QML 都能访问这些字符串。

支持 Qt 应用程序国际化的类请参阅《Qt 的国际化》。使源代码可翻译的过程在《编写用于翻译的源代码》和《Qt Quick 的国际化和本地化》中有描述。

每个需要翻译的文本都需要上下文,以帮助译员确定文本在程序中的位置。如果多个相同的文本需要不同的翻译,译员还需要一些信息来消除源文本的歧义。标记要翻译的文本将自动导致类名被用作基本的上下文信息。在某些情况下,开发人员可能需要添加其他信息来帮助翻译。

部署翻译

应用程序所需的 .qm 文件应放置在使用 QTranslator 的加载器代码可以找到的位置。一般来说,这是通过指定相对于 QCoreApplication::applicationDirPath() 的路径来实现的。

通常,应用程序会有 .qm 文件,如果使用的 Qt 版本未安装在系统上,则还需要部署 Qt 的 .qm 文件。

在 Qt 4 中,每个本地都有一个大的、单一的 .qm 文件。例如,qt_de.qm 文件包含所有库的德语翻译。

在 Qt 5 中,.qm 文件按模块拆分,有一个所谓的元目录文件,其中包含所有模块的 .qm 文件。元目录文件的名称与 Qt 4 单个 .qm 文件的名称相同,因此只要能找到所有包含的 .qm 文件,现有的加载器代码就能像以前一样工作。

不过,没有必要总是部署 Qt 5 的所有 .qm 文件。我们建议在部署步骤中使用工具 lconvert 将所需模块的 .qm 文件连接到一个与元目录文件名相匹配的文件中。例如,要为使用 Qt Core、Qt GUI 和 Qt Quick 模块的应用程序创建德语翻译文件,请运行

lconvert -o installation_folder/qt_de.qm qtbase_de.qm qtdeclarative_de.qm

教程

以下教程说明了如何为翻译准备 Qt 应用程序:

  • Hello tr() 是一个 C++ 应用程序,演示了如何创建 QTranslator 对象。它还演示了如何最简单地使用 tr() 函数来标记用户可见的源文本以进行翻译。
  • Arrow Pad是一个 C++ 应用程序,演示了如何使应用程序加载适用于当前语言的翻译文件。它还展示了 tr() 的双参数形式的使用,该形式可为翻译器提供额外信息。
  • Troll Print是一个 C++ 应用程序,演示了如何区分相同的源文本,即使它们出现在相同的上下文中。本教程还讨论了在应用程序升级时,翻译工具如何帮助最大限度地减少翻译工作。
  • 国际化是一个 Qt Quick 应用程序,演示了如何将 Qt Quick 应用程序国际化。

基于文本 ID 的翻译

文本 ID 翻译机制是一种用于国际化和本地化的 “工业级 ”系统。应用程序中的每个文本都被分配了一个唯一的标识符(文本 ID),这些标识符直接用于源代码中,以代替纯文本。这需要用户界面开发人员做更多的工作,但却使管理大量翻译文本变得更加容易。

注意:您必须在一个应用程序中只使用基于纯文本或基于文本标识符的功能。如果混合使用,最终将导致要翻译的文本不完整。

使用文本 ID 进行国际化

使用文本 ID 代替纯文本时,应用程序国际化的一般方法相同,但细节略有不同:

  1. 基于文本 ID 的翻译系统的函数和宏与纯文本系统不同。您可以使用 qsTrId() 函数代替 qsTr(),使用 QT_TRID_NOOP() 宏代替 QT_TR_NOOP()。
  2. 使用文本 ID 作为用户界面字符串,而不是纯文本字符串。例如,qsTrId(“id-back-not-front”)
  3. 不能使用文本 ID 指定上下文参数。如果有拼写相同但含义不同的单词,这些单词需要单独的文本 ID。例如,qsTrId(“id-back-backstep”) 将区分后步 “Back ”和对象后部 “Back”。
  4. 开发版用户界面中的 “工程英语 ”文本用 //% 注释表示。如果不包含该注释,用户界面中将显示文本 ID。这一点在带有参数的文本中尤为重要。//% 注释需要包含字符串中的参数指示符。例如,//% “文件数:%1”。
  5. 在纯文本系统中,为翻译人员提供额外信息的 //: 注释是可选的。但是,在基于文本 ID 的系统中,这些额外信息变得非常重要,因为如果没有这些额外信息,就只有文本 ID,译员可能无法在没有进一步上下文的情况下进行合理的翻译。您可以使用长的描述性文本 ID,也可以不使用注释,但注释通常更容易理解。

下面的并排代码片段比较了基于文本 ID 的翻译和基于纯文本的翻译:

text-ID-basedplain-text-based
Text {
    id: backTxt;
    //: The back of the object, not the front
    //% "Back"
    //~ Context Not related to back-stepping
    text: qsTrId("id-back-not-front");
}
Text {
    id: backTxt;
    //: The back of the object, not the front
    //~ Context Not related to back-stepping
    text: qsTr("Back","Not front")
}

使用文本 ID 进行本地化

使用文本 ID 进行本地化的过程与纯文本大致相同。 使用 lupdate 工具的方法相同,翻译都是在 .ts 文件中进行的:

lupdate <myapp>.pro

请注意,翻译文件中的源值将是文本 ID 而非纯文本。 这意味着您需要描述性很强的文本 ID,或很好的附加注释,或两者兼而有之,以确保译员做出正确的翻译。 上述基于文本 ID 的用户界面文本示例在 .ts 文件中产生了以下内容:

<message id="id-back-not-front">
    <source>Back</source>
    <extracomment>The back of the object, not the front</extracomment>
    <translation type="unfinished"></translation>
    <extra-Context>Not related to back-stepping</extra-Context>
</message>

使用 lrelease 时,需要指定翻译文本的键基于文本 ID,而不是纯文本。 如果代码中的字符串是用 qsTr() 指定的,则没有设置 "id "属性,因此 lrelease 会忽略它们。 该命令将生成应用程序的所有编译翻译 .qm 文件:

lrelease -idbased <myapp>.pro

但是,如果给定文本没有可用的翻译(通常在开发后期才会出现这种情况),用户界面中将显示文本 ID,而不是正确的文本。 为了使应用程序在测试时更可用,可以让 lrelease 使用 "工程英语 "源文本(来自 //% 注释)作为翻译文本,并用一些指示符标记它,这样就可以看到尚未翻译的文本。 例如,该命令会生成 .qm 文件,并在未翻译文本前加上"!":

lrelease -idbased -markuntranslated ! <myapp>.pro

高级用法

对于针对大量本地语言的项目,可以删除 .pro 文件中的 TRANSLATIONS 信息,转而使用单独的脚本管理翻译。 脚本可为每个目标调用 lrelease 和 lupdate。 更新脚本可以这样编写

lupdate -recursive <project-dir> -ts <project-dir>/i18n/myapp-text_en_GB.ts
lupdate -recursive <project-dir> -ts <project-dir>/i18n/myapp-text_en_US.ts
...

生成最终 .qm 文件的脚本可以这样编写:

lrelease -idbased <project-dir>/i18n/myapp-text_en_GB.ts
lrelease -idbased <project-dir>/i18n/myapp-text_en_US.ts
...

Qt Linguist Manual

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部