概述
用Qt开发多语言界面应用程序, 主要包括以下几个步骤:
- 在程序设计阶段, 程序代码中每一个用户可见的字符串都用
tr()函数封装, 以便Qt提取界面字符串用于生成翻译资源文件。用UI设计器可视化设计窗体时统一用一种语言,如汉语。 - 在项目配置文件(
.pro文件)中设置需要导出的翻译文件(.ts文件)名称,使用lupdate工具扫描项目文件中需要翻译的字符串,并生成翻译文件。 - 使用Qt的
Linguist程序打开生成的翻译文件,将程序中的字符串翻译为需要的语言,如将所有中文字符串翻译为英文。 - 使用
lrelease工具编译翻译好的翻译文件,生成更为紧凑的.qm文件。 - 在应用程序中用
QTranslate调用不同的”.qm“文件,实现不同的语言界面。
一、tr()函数的使用
为了让Qt能自动提取程序中用户可见的字符串:
- 在使用Q_OBJECT宏定义的类或QObject的子类,可直接使用
tr()函数对每个字符串进行封装;否则使用QObject::tr() 在类定义中用
Q_DECLARE_TR_FUNCTIONS把tr()函数添加到类中,再直接调用tr()函数1.1 定义:
static QString tr(const char *sourceText, const char *comment = Q_NULLPTR, int n = -1);
sourceText是源字符串*comment为翻译者提供额外信息的字符串
1.2 注意事项
1.2.1 尽量使用常量字符串,不要使用字符串变量。
在 tr() 函数中应直接传递字符串常量,而不是用变星传递字符串,如下面的代码使用了字符串变量,使用 lupdate 工具提取项目中的字符串时, 将不能提取“不能删除记录” 这个字符串。
// 不能提取该字符串const char* errorStr = "不能删除记录";QString str1 = tr(errorStr);
1.2.2 使用字符串变量时需要用 QT_TR_NOOP() 宏进行标记
若要在 tr() 函数中使用字符串变量,需要在定义字符串的地方用 QT_TR_NOOP() 宏进行标记,这在使用字符串数组时比较有用,例如:
QComboBox* comboBox = new QComboBox(this);const char* cities[4] = {QT_TR_NOOP("Beijing"),QT_TR_NOOP("Shanghai"),QT_TR_NOOP("Qingdao"),QT_TR_NOOP("Wuhan")};for (int i = 0; i < 4; i++) {comboBox->addItem(cities[i]);}
1.2.3 tr()不能使用拼接的动态字符串
tr()不能使用拼接的动态字符串。
例如:
下面的用法是错误的:
QLabel* label = new QLabel(this);for (int i = 0; i < 4; i++) {// 仅能识别 第一个字: "第"QString text = QT_TR_NOOP("第" + QString::number(i) + "行");label->setText(text);}
正确的使用方式
QLabel* label = new QLabel(this);for (int i = 0; i < 4; i++) {// 识别出 "第%1行"label->setText(tr("第%1行").arg(i));}
翻译的字符串是”第%1行”,然后再用QString的arg()去替换占位符%1的内容。
1.2.4 QT_NO_CAST_FROM_ASCII的作用
在一个需要翻译为多语言的应用程序中,如果编写程序时忘了对某个字符串使用 tr() 函数,lupdate 生成的翻译资源文件就会遗漏这个字符串。为了避免这种疏忽错误,可以在项目配置文件(. pro 文件)中添加如下的定义:
DEFINES+= QT_NO_CAST_FROM_ASCII
这样在编译时,会禁止从 const char* 到 QString 的隐式转换,强制每个字符串都必须使用tr()或 QLatinlString() 封装,避免出现遗漏未翻译的字符串。
1.3 生成语言翻译文件
要生成多语言界面相关的翻译文件,需要以下三步:
- 对每个字符串都使用
tr()函数封装, - 在项目配置文件(
.pro文件)中使用TRANSLATIONS定义语言翻译文件(.ts文件) 使用
lupdate工具生成语言翻译文件。TRANSLATIONS = test_cn.ts \test_en.ts
使用:
lupdate:点击:Tools -> External -> Qt语言家 -> UpdateTranslations(lupdate)
- 若
TRANSLATIONS设置的文件不存在,则会自动生成;若文件已存在,则更新这些文件的内容1.4 使用
生成的ts文件包含了项目源程序和UI界面所有字符串,使用Qt Linguist翻译ts文件Qt Linguist可以将这些字符串翻译未需要的语言版本。在Qt安装后的程序组里可以找到Qt Linguist软件。如: C:\Qt5.15\5.15.2\msvc2019_64\bin\linguist.exe C:\Qt5.7\msvc2015\bin\linguist.exe
1.4.1 第一次打开一个ts文件,会要求选择源语言和目标语言:
1.4.2 进行翻译

- 字符串 列表里列出了从项目的UI窗口和代码文件中提取的字符串,
- 短语和表单 会显示窗口界面的预览或字符串在源程序中出现的代码段。
- 译文编辑框,在此填写字符串对应的英文译文。
1.5 调用翻译文件改变界面语言
1.5.1 生成qm语言
项目所有字符串都翻译后,通过lrelease生成与ts文件对应的qm文件,这是更为紧凑的翻译文件。
lrelease的位置:
Tools -> External -> Qt语言家 -> Release Translations(lrelease)
1.5.2 项目启动时设置界面语言
使用 QTranslator 类设置界面的不同语言版本,需在应用程序启动时设置界面语言翻译文件,即在 main() 函数中进行处理。
#include "widget.h"#include <QApplication>#include <QSettings>#include <QString>#include <QTranslator>QTranslator* trans = nullptr;QString readSetting();int main(int argc, char* argv[]){QApplication a(argc, argv);trans = new QTranslator;QString curLang = readSetting(); //读取语言设置curLang = QObject::tr("EN");if (curLang == QObject::tr("EN"))trans->load(QObject::tr("test_cn.qm"));elsetrans->load(QObject::tr("test_en.qm"));a.installTranslator(trans);Widget w;w.show();return a.exec();}QString readSetting(){// 从注册表读取上次设置的语言QString organization = QObject::tr("WWB-Qt");QString appName = QObject::tr("test");QSettings settting(organization, appName);QString language = settting.value(QObject::tr("Language"), QObject::tr("EN")).toString();return language;}
