本地化是当今软件开发中一个重要但通常被忽视的部分。 大多数应用的作者,无论这些应用是商业应用还是开源应用,都希望为他们的应用赢得大量用户。 这意味着越来越多地需要在多个地区支持多种语言,而且通常需要在一个地区支持多种语言(可以将其视为在加拿大共存的法语和英语)。
很长一段时间以来,Qt 都有一个使应用易于本地化的框架,其工具可以帮助您避免在应用中硬编码字符串,还有一个名为Qt Languist的 GUI 来帮助管理翻译。 在本章中,我们将介绍 Qt 的本地化策略,讨论 Qt 提供的三种工具(lupdate、lrelease和 Qt Languist)以及如何使用它们,以及在编写应用以利用 Qt 的本地化框架时需要做些什么。
在本章中,我们将介绍以下主题:
- 理解本地化的任务
- 标记用于本地化的字符串
- 使用 QLanguist 本地化您的应用
- 使用 QLocale 本地化特殊参数-货币和日期
本章的技术要求包括 Qt 5.12.3、MinGW 64 位、Qt Creator 4.9.0 和 Windows 10。
如果您想要在全球销售您的产品,本地化是其重要功能。 当用户看到他们的母语在一款软件中被显示和使用时,他们更有可能会依恋它,成为你的忠实客户之一。 然而,本地化并不总是一个容易实现的特性,至少在 Qt 引入了一种更简单的方式之前是这样。
本地化应用有几个阶段,在整个项目生命周期中通常会重叠。
下图显示了这些阶段的交互方式:
这些阶段如下:
- 在编写应用时,将需要本地化的字符串放入特定函数中(请参见步骤 5),以便 Qt 可以识别需要本地化的字符串。
- 定期提取应用中的所有字符串,并将它们交给翻译人员进行翻译。
- 翻译器为应用中的字符串提供翻译。
- 您可以使用要支持的每种语言的翻译字符串编译翻译文件。
- C++ 和 QML 的
tr和qsTr函数允许您识别应用中需要本地化的字符串。 Qt 提供了四个工具来简化这些阶段。 lupdate命令生成应用中需要本地化的字符串的列表。- 翻译者使用 Qt Languist 为您的应用中的字符串提供翻译。
lrelease命令从 Qt Creator 获取翻译后的字符串,并将它们打包成供您的应用使用的格式。
软件开发是迭代的,本地化也不例外。 小型项目可能更喜欢只本地化一次或两次,等到应用接近完成后再提交应用字符串进行本地化。 大型应用或拥有专职翻译人员的大型公司可能更喜欢迭代的方法,在整个应用开发过程中多次经历本地化周期。 Qt 支持这两种型号。
我们已经了解了本地化的重要性以及如何在 Qt 中实施本地化。 在下一节中,我们将学习如何使用 C++ 方法完成此操作。
回到第 1 章,Qt Creator 入门,我告诉过您要始终使用tr和qsTr函数将字符串标记为本地化:tr用于 C++,qsTr用于 QML 字符串。 这样做有两个关键优势:
- 它使 Qt 能够找到每个需要本地化的字符串。
- 如果在应用中安装 Qt Translator 对象并提供翻译文件,则用这些函数包装的字符串将自动替换为它们的本地化等效项。
让我们更详细地研究一下tr的用法。 所有在声明中包含Q_OBJECT宏的 Qt 对象都包含tr函数。 你已经看到了它的一个论点,如下所示:
button = new QPushButton(tr("&Quit"), this); 字符串中的前导&不是用于tr函数,而是用于键盘快捷键;您可以在字母前面加上&来指定键盘快捷键,它将获得默认系统(对于 Windows,Alt、对于 Apple,cmd和对于 Linux,Alt是一个组合键)。 如果该字符串的翻译版本未出现在应用的当前转换表中,tr函数将使用您在用户界面中作为字符串传递的字符串,或者使用当前转换表中的字符串(如果存在)。
tr函数可以接受第二个参数,即tr用于可能需要不同翻译的同一字符串的消歧上下文。 如下所示:
tr("&Copy", "Menu"); 此函数还可以处理带复数的字符串,如下所示:
tr("%n item(s) replaced", "", count); 根据count的值和区域设置,返回不同的字符串。 因此,本地英语翻译可以返回"0 items replaced"、"1 item replaced"、"2 items replaced"等,而法语翻译可以返回"0 item remplacé"、"1 item remplacé"、"2 items remplacés"等。
在 QML 中,您只需使用qsTr函数,该函数的工作方式与 C++ 中的tr方法完全相同。
在本节中,我们了解了如何标记字符串,让 Qt 知道哪个字符串需要本地化。 接下来,我们将学习如何在 Qt 中运行本地化过程,并根据用户的语言偏好显示正确的语言。
一旦使用tr或qsTr标记了字符串,就需要生成这些字符串的表,以便 Qt 语言学家进行本地化。 可以使用lupdate命令实现这一点,该命令获取.pro文件并遍历源代码以查找要本地化的字符串,并为 Qt 语言学家创建需要翻译的字符串的 XML 文件。 您需要为您想要支持的每种语言执行一次此操作。 在执行此操作时,最好系统地命名生成的文件;一种方法是使用项目文件的名称,后跟破折号,然后是该语言的 ISO-639-2 语言代码。
下面是一个具体的例子。 本章使用QtLinguistExample;我们可以使用如下命令运行lupdate,以创建要转换为世界语(ISO-639-2 语言代码,ePO)的字符串列表:
% lupdate -pro .\QtLinguistExample.pro -ts .\QtLinguistExample-epo.tsDon't forget that the % character is the Command Prompt, which might differ from system to system.
这里,-pro文件表示.pro文件包含要扫描以查找要翻译的字符串的源列表,而-ts参数表示要写入的翻译文件的名称。 当然,您需要在您的道路上使用lupdate。 如何设置路径将取决于您使用的是 Windows、MacOSX 还是 Linux,以及 Qt 的安装位置。 Qt 的某些安装可能会自动更新您的路径,而其他安装可能不会这样做。 例如,在我的 Windows 机器上,我可以在C:\Qt\5.13.0\msvc2017_64\bin\lupdate.exe处找到lupdate。
.ts文件是一个带有标记的 XML 文件,用于指示要翻译的字符串、它们在应用源代码中的上下文等。 Qt 语言学家会将翻译保存到它的输出文件中,该文件的名称也带有一个 QM 后缀,但是不要担心:lupdate足够聪明,如果您在提供一些翻译之后再次运行它,它不会覆盖现有的翻译。
您还可以轻松地从 Qt Creator 运行命令提示符,方法是在项目面板中右键单击.pro命令文件,然后选择 Build Environment(构建环境)选项,以自动配置命令提示符相对于项目目录的路径,如下所示:
除了使用命令外,您还可以直接从 Qt Creator 中使用lupdate和lrelease,方法是转到工具|外部|语言学家|更新翻译(Lupdate)或发布翻译(Lrelease)。 请注意,这将更新或释放所有翻译文件。 如果您只想更新或发布特定的文件/语言,命令仍然是您最好的朋友。
以下屏幕截图显示了lupdate工具在应用菜单上的位置:
Qt Language ist 是一个 GUI 应用;在启动该应用时,您将看到一个与下一个屏幕截图非常相似的屏幕:
首先,您需要打开您通过导航到文件|打开文件并选择翻译文件生成的.ts文件。 系统将提示您输入目标语言,然后给出找到的字符串列表:
您或您的翻译人员只需遍历每个字符串,然后以翻译的语言输入相应的字符串。 这样做时,您可以在最右边的窗格中看到源代码中字符串的上下文;从中捕获字符串的源代码所在的行会高亮显示。
Qt 语言学家可以让您跟踪已翻译的字符串以及仍需翻译的字符串。 每个字符串左侧的图标可以是以下图标之一:
- 黑色问号,表示字符串尚未翻译
- 黄色问号,表示该字符串没有通过 Qt 语言学家的所有验证测试,但您忽略了这些失败
- 一个感叹号,表示您提供的字符串没有通过 Qt 语言学家的验证测试
- 黄色的复选框,表示您提供了翻译,但 Qt Creator 可能发现翻译有问题
- 绿色的复选框,表示字符串已翻译完毕,可以开始使用了
Qt Languist 提供了一些简单的验证测试,比如确保具有printf样式参数的字符串在每次翻译中都有相同数量的参数。
Qt 语言学家还支持词汇书;您可以下载包含已本地化为目标语言的常用字符串的词汇书。
在任何时候,您都可以通过运行lrelease来生成要包含在应用中的转换文件。 例如,要为世界语字符串创建一个,我们将使用lrelease,如下所示:
% lrelease .\QtLinguistExample-epo.ts .\QtLinguistExample-epo.qm这将获取传入的.ts文件,并生成包含字符串的.qm文件。 .qm文件是 Qt 在呈现应用的过程中直接使用的高度压缩的二进制文件。
我们已经了解了如何使用 Qt Languist 将所有文本导出到列表中,并允许您和您的翻译人员进行翻译。 接下来,我们将继续在我们的应用中包含本地化文本。
为了向应用中的tr和qsTr函数提供翻译后的字符串,您的应用需要包括一个QTranslator对象来读取.qm文件,并将提供给tr和qsTr的字符串替换为翻译后的对应字符串。
我们可以在您的主要入口点函数中执行此操作,如下所示:
QApplication a(argc, argv);
QTranslator translator;
bool result = translator.load("QtLinguistExample-epo.qm");
a.installTranslator(&translator);
// Other window setup stuff goes here
return a.exec(); 此代码分配一个QTranslator对象,并在将其安装到QApplication对象之前将指定的翻译文件加载到转换器中。 在本例中,我们对语言进行了硬编码,以便将其本地化为世界语。
请注意,如果您希望支持系统选择的区域设置,则可以选择这样做:
QString locale = QLocale::system().name();
QTranslator translator;
translator.load(QString("QtLinguistExample-") + locale); 这里的QLocale类是用于管理系统区域设置的类。 在这里,我们使用它来确定系统的区域设置,然后尝试加载系统当前区域设置的本地化字符串文件。
要实现这一点,应用的.qm文件需要可由应用定位。 它们应该在输出目录中;在开发过程中,一种方法是在 Qt Creator 中关闭影子构建,在项目窗格的 Build 和 Settings 下。 构建应用安装程序是一项特定于平台的任务,这超出了本书的范围,为此,您需要在应用二进制文件中包含.qm个文件。
For more information on Qt Linguist, refer to its manual at https://doc.qt.io/qt-5/qtlinguist-index.html.
接下来,我们将了解如何本地化一些特殊参数以满足我们的要求。
您可能需要做的一件常见的事情是本地化货币和日期。 Qt 使这一点变得简单,尽管解决方案在您仔细考虑之前并不明显。 让我们试试看吧。
- 您需要了解
QString arg方法。 这将用其参数的格式化版本替换转义数字。 例如,如果我们编写以下内容:
QString s = QString("%1 %2").arg("a").arg("b"); 然后,s将包含字符串"a b"。
- 您需要了解
QLocale的toString方法,该方法以特定于区域设置的方式格式化其参数。 因此,我们可以写下以下内容:
QString currencyValue = QString("%1 %2")
.arg(tr("$")).arg(QLocale::toString(value, 'g', 2) 它使用tr本地化货币符号,并使用QLocale类的静态方法toString将货币值转换为带有区域设置特定小数分隔符(在美国和加拿大为句点,在欧洲为逗号)的字符串。
日期格式类似;QLocale的toString方法重载了QDateTime、QDate和QTime参数,因此只需编写以下代码:
QDateTime whenDateTime = QDateTime::currentDateTime();
QString when = QLocale::toString(whenDate); 这将获取当前日期和时间并将其存储在whenDateTime中,然后使用区域设置的默认格式将其转换为字符串。 toString方法可以采用第二个参数来确定输出格式;它是以下参数之一:
QLocale::LongFormat:这使用长版本的月份和日期名称。QLocale::ShortFormat:这使用月和日名称的简短版本。QLocale::NarrowFormat:这提供了日期和时间的最窄格式。
就这样。 我们不仅学习了如何使用 Qt 本地化文本,还学习了如何本地化货币和日期等特殊字符。
使用 Qt 语言学家和 Qt 中的本地化框架,可以轻松地使用 Qt 本地化应用。 不过,要使用该框架,您必须将字符串标记为在源代码中使用tr或qsTr进行本地化,无论它们出现在哪里。 完成此操作后,您可以使用 Qt 的lupdate命令创建要使用 QLanguist 进行翻译的字符串的源文件,然后为每个字符串提供翻译。 提供翻译后,使用lrelease编译它们,然后通过在应用的主函数中安装QTranslator对象并加载由lrelease生成的翻译表,将它们包含在应用中。
在本章中,我们学习了如何标记可翻译文本,以便 Qt 知道哪些文本需要本地化。 接下来,我们还学习了如何使用 Qt Language ist 将这些文本导出到列表中,以便您和您的翻译人员可以轻松地针对每种语言进行编辑。 然后,我们了解了如何将翻译后的文本重新加载到 Qt 应用中,并根据用户的喜好显示它们。 最后,我们还学习了如何本地化特殊字符,如货币和日期。
在下一章中,我们将介绍 Qt Creator 支持的软件开发的另一个重要方面:使用 QML Profiler 和 Valgrind 进行性能分析。




