Qt国际化的一般步骤
- 运行 lupdate,从应用程序的代码中提取所有界面上的可见字符。
这些可见字符必须被 tr() 、QCoreApplication::translate()、Qt_TR_NOOP()、Qt_TRANSLATE_NOOP()等来包裹字符串,具体这些函数或者宏是什么功能,我们后面细说。
- 使用 Qt Linguist 翻译应用程序。
- 运行 lrelease,生成二进制的 .qm 文件,应用程序可以使用 QTranslator 加载这个文件。
翻译标志函数和宏
在类内时,使用tr() 和 Qt_TR_NOOP()
使用 tr() 包裹可见字符,如下代码所示:
QPushButton *button = new QPushButton(this);
button->setText(tr("国际化"));
上面是将按钮的名称进行国际化,上面也是 tr() 函数的最简单的用法。当然,此种用法还是有其局限性。只有这段代码在类函数里面,并且所属的类继承于 QObject 的时候,才可以使用 tr() 。
如果所属的类不是继承于 QObject,我们可以将上面代码改成下面所示:
QPushButton *button = new QPushButton(this);
button->setText(QObject::tr("国际化"));
或者使用 Q_DECLARE_TR_FUNCTIONS 将 tr() 函数加入到这个类里,代码如下所示:
class MyClass
{
Q_DECLARE_TR_FUNCTIONS(MyClass)
public:
MyClass();
...
};
如果声明的字符串生命资源串和常量,我们就需要使用 QT_TR_NOOP() 和 tr() 配合使用。 示例代码如下所示:
QString FriendlyConversation::greeting(int type)
{
static const char *greeting_strings[] = {
QT_TR_NOOP("Hello"),
QT_TR_NOOP("Goodbye")
};
return tr(greeting_strings[type]);
}
或者在类内而不在类函数里,代码如下所示:
class MyClass
{
Q_DECLARE_TR_FUNCTIONS(MyClass)
static const char * const ids[] = {
//% "This is the first text."
QT_TR_NOOP("qtn_1st_text"),
//% "This is the second text."
QT_TR_NOOP("qtn_2nd_text"),
0
};
public:
MyClass();
void addLabels();
...
};
void MyClass::addLabels()
{
for (int i = 0; ids[i]; ++i)
new QLabel(tr(ids[i]), this);
}
- 在类外时,使用QCoreApplication::translate() 和 Qt_TRANSLATE_NOOP(),相对于 tr() 函数,translate() 函数的优点:
- 使用范围更广,tr() 的使用范围在类内使用,translate() 可以在类内也可以在独立的函数中使用,例如:main() 函数。
- 翻译更精细,因为 translate() 添加了上下文共能,所以他相对于 tr() 可以更精确的进行翻译,例如,translate("MainForm", "draw") 和 translate("SubForm", "draw"); 都是 “draw” 我们可以根据他在不同的窗体上,翻译有所区别。
同样,在 Qt_TRANSLATE_NOOP() 宏中也是相同的用法。
可见字符为中文,乱码问题
当我们的可见字符为中文的时候,在 Qt Linguist 中汉语显示为乱码,例如,tr("国际化"),在 Qt Linguist 中显示乱码如下图所示。
标红的地方全是乱码,这种乱码只是因为编码方式不对导致。在 Qt Linguist 中所有字符串都是默认的 Latinl 编码,所以导致中文乱码。下面我们就需要对 Qt Linguist 进行更改。
在 Qt Linguist 源码中我们需要更改两处:
- messagemodel 单元内的 MessageItem 类,将原来 text()函数 代码:
- QString text() const { return m_message.sourceText(); }
改为:
QString text() const
{
QString result = m_message.sourceText();
return QString::fromLocal8Bit(result.toLatin1());
}
在其他地方乱码,也可以类似的更改。MessageItem 就是他显示的一条需要翻译的记录。
- sourcevcodeview 单元内的 SourceCodeView 类,将原来代码:
void SourceCodeView::showSourceCode(const QString &absFileName, const int lineNum)
{
……
fileText = QString::fromLatin1(file.readAll());
……
}
改为:
void SourceCodeView::showSourceCode(const QString &absFileName, const int lineNum)
{
……
fileText = QString::fromLocal8Bit(file.readAll());
……
}
仍然存在的问题
在 “短语和猜测” 窗体中不显示,还未查询是什么原因。
作者:xiao69