❝简单的QML小例子,展示如何在QML中多语言动态切换。❞
0x01 加载语言文件操作
代码语言:javascript复制/* 加载中文语言(默认) */
QTranslator translator;
if (! translator.load(":/Resources/zh_CN.qm")) {
qDebug() << "Failed to load translation file!";
}
qApp->installTranslator(&translator);
0x02 切换语言
这里涉及到C 与QML的数据操作与交互。
- 创建一个C 自定义类型,用于导入到QML中使用。其中SettingModel中的language属性为切换语言的状态。
class SettingModel : public QObject
{
Q_OBJECT
Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY languageChanged)
public:
SettingModel(QObject *parent = NULL) : QObject(parent)
{
m_language = "zh_CN";
}
QString language()
{
return m_language;
}
void setLanguage(const QString &language)
{
QTranslator translator;
if (! translator.load(QString(":/Resources/%1.qm").arg(language))) {
qDebug()<<"Failed to load translation file!";
return;
}
/* 切换语言 */
qApp->installTranslator(&translator);
m_language = language;
emit languageChanged();
}
signals:
void languageChanged();
private:
QString m_language;
};
- QML切换语言操作,通过操作SettingModel类中的language属性后,会即刻切换语言(文件)。
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: tr("Hello World")
font.pixelSize: 30
}
Row {
spacing: 10
Button {
id: chinese
text: "中文"
/* 切换为中文,逻辑在SettingModel的setLanguage函数中。 */
onClicked: settingModel.language = "zh_CN"
}
Button {
id: english
text: "English"
/* 切换为英文,逻辑在SettingModel的setLanguage函数中。 */
onClicked: settingModel.language = "en"
}
}
SettingModel { id: settingModel }
0x03 这就完成了吗?
上面一顿操作猛如虎,一看效果二百五。怎么没反应的,没变化呀。似乎有细心的人发现了一些奇怪的地方就是:
代码语言:javascript复制text: tr("Hello World")
不应该是下面这个吗?
代码语言:javascript复制text: qsTr("Hello World")
别急,还没写完嘛!tr函数
如下咯。
function tr(string) {
/**
* tmp变量这里没有使用,原因是利用QML语言绑定机制,
* 当settingModel.language有变化时,
* QML立即自动调用tr函数,对所有绑定该函数的表达式都会重新调用一次。
*/
var tmp = settingModel.language;
/* 设置"Window"字段上下文,在对应ts中需要添加<name>Window</name> */
return qsTranslate("Window", string)
}
这tr
函数太奇怪了吧!没错要使QML的翻译动态更新,就需要额外绑定一个变量,当变量变化时就会触发对应tr
函数的绑定,从而重新调用一次text: tr("Hello World")
后刷新翻译了。
0x04 翻译误区
这里需要注意的是,君君特别地使用qsTranslate
这个接口而不是使用qsTr
,如果单纯使用qsTr
会导致翻译不到的情况,因为大多数翻译字段都设置了上下文。
qsTranslate("Window", string)
中的第一个参数是翻译的「上下文」,第二个参数是需要翻译的字段。
关于翻译字段「上下文」理解,选取zh_CN.ts
文件内容为例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="zh_CN">
<context>
<name>QObject</name>
<message>
<source>QtHub.com</source>
<translation>@Qt君</translation>
</message>
<message>
<source>Hello World</source>
<translation>你好,世界</translation>
</message>
<message>
<source>open</source>
<translation>打开</translation>
</message>
<message>
<source>close</source>
<translation>关闭</translation>
</message>
</context>
<context>
<name>Window</name>
<message>
<source>QtHub.com</source>
<translation>@Qt君</translation>
</message>
<message>
<source>Hello World</source>
<translation>你好,世界</translation>
</message>
<message>
<source>open</source>
<translation>打开</translation>
</message>
<message>
<source>close</source>
<translation>关闭</translation>
</message>
</context>
</TS>
从上面可以看出,有两个上下文字段QObject
和Window
,如果在QML中使用了qsTr
是不能直接翻译成功的,必须加上上下文。
<name>QObject</name>
<name>Window</name>
做翻译字段时,建议大多数情况下都添加上下文。
0x05 更多
- 2019-01-31 推文 《Qt多语言翻译示例》,介绍Qt多语言翻译。
- 2020-05-02 推文《Qt Quick实践系列-函数绑定》,介绍数据绑定机制。
关于Qt&QML的多语言翻译有什么想法在留言区和大家讨论吧。