一、翻译Qt Quick应用软件
1.对所有用户界面中的文字字符串使用qsTr()
QML中的字符串可以使用qsTr()、qsTranslate()、qsTrId()、QT_TR_NOOP()、QT_TRANSLATE_NOOP()和QT_TRID_NOOP()函数进行标记以进行翻译。标记字符串最常使用的方法是使用qsTr()函数。如果想要将应用界面中字符串进行翻译,那必须先进行标记。
2、为翻译器添加上下文注释
用户界面字符串通常很短,所以需要帮助翻译文本的人去理解文本的上下文含义,哈哈,一般开发人员怎么会去做翻译的嘛,毕竟一个名词可能有多个含义,不加注释,翻译人员怕要哭哟!!。
这时候注释将排上用场,可以在源代码中添加上下文信息,作为要翻译的字符串之前的额外描述性文本来解释待翻译的名词。这些额外的描述包含在发给翻译人员的.ts翻译文件中。【需要遵循所设定的语法规则进行上下文文本的编写】
【注意】
.ts文件是包含源文本和翻译文本的XML文件。更新后的.ts文件会被转换成二进制翻译文件,并作为最终应用程序的一部分。本质上就是,lupdate.exe程序首先根据Qt Quick应用软件中的需要标记翻译的文本生成一个XML文件,然后,lrelease.exe程序根据xml文件生成一个二进制的文件,供应用程序使用,这一点与QWidget一样。
在下面的代码片段中,//:行上的文本是翻译程序的主要注释。
~行上的文本是可选的额外信息。文本的第一个单词被用作.ts文件中的XML元素中的附加标识符,因此要确保第一个单词不是句子的一部分。例如,注释“Context Not related to that”在.ts文件中被转换为“<extra-Context>Not related to that”。
Text {
id: txt1;
// This user interface string is only used here
//: The back of the object, not the front
//~ Context Not related to back-stepping
text: qsTr("Back");
}
3、消除歧义文字
翻译系统将用户界面文本字符串合并为唯一的条目。这种合并节省了翻译工作人员不得不多次翻译相同文本的次数。然而,在某些情况下,相同的文本有不同的含义。例如,在英语中,“back”的意思是后退一步,也指物体与前面相对的部分。需要将这两种不同的含义告诉翻译系统,以便翻译人员可以创建两种不同的翻译。
【如何实现】
通过添加一些id文本作为qsTr()函数的第二个参数来区分相同的文本。
在下面代码片段中,not front文本是一个id,用来区分这个“Back”文本和后退的“Back”文本:
Text {
id: txt1;
// This user interface string is used only here
//: The back of the object, not the front
//~ Context Not related to back-stepping
text: qsTr("Back", "not front");
}
4、使用%x将参数插入字符串
不同的语言将单词以不同的顺序放在一起,所以通过连接单词和数据来创建句子不是很好。相反,使用%将参数插入字符串。例如,下面的代码片段有一个带有两个数字参数%1和%2的字符串。这些参数是用.arg()函数插入的。
Text {
text: qsTr("File %1 of %2").arg(counter).arg(total)
}
%1指的是第一个参数,%2指的是第二个参数,所以这段代码产生的输出类似于“File 2 of 3”。
5、使用%Lx使数字本地化
如果在指定参数时包含%L修饰符,则根据当前区域设置本地化该数字。例如,在下面的代码片段中,%L1表示根据当前选择的区域(地理区域)的数字格式约定格式化第一个参数:
Text {
text: qsTr("%L1").arg(total)
}
那么,用上面的代码,如果总数是“4321.56”(四千三百二十一点五十六);对于英语区域设置(locale),输出是“4,321.56”;采用德国区域设置,输出为“4.321,56”。
6、国际化日期、时间和货币
没有特殊的字符串修饰符用于格式化的日期和时间。那么需要查询当前地区(地理区域)并使用Date的方法格式化字符串。
Qt.locale()返回一个Locale对象,该对象包含关于Locale的各种信息。具体来说,locale. name属性包含当前语言环境的语言和国家信息。所以说可以直接使用该值,也可以对其进行解析以确定当前区域设置的适当内容。
下面的代码片段使用Date()获取当前日期和时间,然后将其转换为当前区域设置的字符串。然后将日期字符串插入%1参数中进行适当的转换。
Text {
text: qsTr("Date %1").arg(Date().toLocaleString(Qt.locale()))
}
要确保货币数字本地化,需要使用Number类型。此类型具有与Date类型类似的功能,用于将数字转换为本地化的货币字符串。
7、对可翻译数据文本字符串使用QT_TR_NOOP()
如果用户在没有重新启动的情况下更改了系统语言,根据系统情况,数组和列表模型中的字符串以及其他数据结构可能不会自动刷新。要强制在用户界面中显示文本时刷新文本,需要使用QT_TR_NOOP()宏声明字符串。然后,在填充要显示的对象时,需要显式地检索每个文本的翻译。例如:
ListModel {
id: myListModel;
ListElement {
//: Capital city of Finland
name: QT_TR_NOOP("Helsinki");
}
}
...
Text {
text: qsTr(myListModel.get(0).name); // get the translation of the name property in element 0
}
8、使用区域设置扩展本地化特性
如果想要针对不同的地理区域使用不同的图像或音频,可以使用Qt.locale()来获取当前区域设置。然后为该地区选择适当的图像或音频。
下面的代码片段展示了如何选择合适的图标来表示当前区域设置的语言。
Component.onCompleted: {
switch (Qt.locale().name.substring(0,2)) {
case "en":
languageIcon = "../images/language-icon_en.png";
break;
case "fi":
languageIcon = "../images/language-icon_fi.png";
break;
default:
languageIcon = "../images/language-icon_default.png";
}
}
9、动态的语言选择
通过使用QCoreApplication::installTranslator()和QCoreApplication::removeTranslator()添加和删除翻译器,可以改变Qt翻译函数使用的语言。然后可以调用QQmlEngine::retranslate()来触发所有使用翻译的绑定的刷新。因此,可使用户界面动态地切换到新选择的语言。【这一点非常重要】
或者,也可以将QEvent::LanguageChange事件转发到应用程序的QQmlEngine实例,或者将自己的信号连接到QQmlEngine::retranslate()。
10、本地化应用程序
Qt Quick应用程序使用与Qt C++应用程序相同的底层本地化系统(lupdate, lrelease和.ts文件)。您可以使用Qt Linguist Manual中描述的相同工具。甚至可以在同一个应用程序中使用C++和QML源文件中的用户界面字符串。系统将创建一个合并的翻译文件,字符串可以从QML和C++中访问。
使用条件从编译器隐藏QML源
lupdate工具从应用程序中提取用户界面字符串。lupdate读取应用程序的.pro文件,以确定哪些源文件包含要翻译的文本。这意味着源文件必须列在.pro文件的SOURCES或HEADERS条目中。如果文件中没有列出,其中的文本将不会被找到。
然而,SOURCES变量用于C++源文件。如果在这里列出QML或JavaScript源文件,编译器会尝试将它们作为C++文件来构建。但是可以使用lupdate_only{…}条件语句,因此lupdate工具会看到.qml文件,但C++编译器会忽略它们。
例如,下面的.pro文件片段指定了应用程序中的两个.qml文件。
lupdate_only{
SOURCES = main.qml \
MainPage.qml
}
还可以使用通配符匹配指定.qml源文件。注意:文件搜索不是递归的,所以需要在源代码中指定每个有用户界面字符串的目录。
lupdate_only{
SOURCES = *.qml \
*.js \
content/*.qml \
content/*.js
}
参考链接:
1、https://doc.qt.io/qt-5/qtquick-internationalization.html#1-use-qstr-for-all-literal-user-interface-strings