本文由乌合之众瞎写http://www.cnblogs.com/oloroso/
qt国际化其实就是qt中字符串的字符集编码的设置。当然这个设置不是简单的选择一下什么语言就好,这个需要编程人员来处理的。
通常对于非拉丁字符(主要指latin1
字符集)的字符串,就需要使用到unicode
字符集,而通常使用UTF-8
编码。如果只是本地使用一下,直接使用""
包含文件就可以了。但是有时候设计到网络传输等情况,就要考虑这些了。
QT提供了QTextCodec
类来进行文本字符集的转换操作。
本文的重点不在于此。深入学习可以看
本文的重点在于QT界面显示的中文化。
在编写QT程序的时候,对于要翻译的文本,应当使用tr()
包含起来。
我们先来看看tr
函数的原型,注意,这是一个静态函数。
QString QObject::tr(const char * sourceText, const char * disambiguation = 0, int n = -1)
因为Qt中的类都继承自QObject
类,所以这里直接使用了tr
,如果不是在继承自QT的类中使用,应该用Object::tr(...)
来调用。
这还不是很准确,在宏定义Q_OBJECT
展开后,会创建一个QMetaObject
对象,即static const QMetaObject staticMetaObject;
这个可以看看
#define Q_OBJECT \
public: \
Q_OBJECT_CHECK \
static const QMetaObject staticMetaObject;\
Q_OBJECT_GETSTATICMETAOBJECT \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
QT_TR_FUNCTIONS \
virtual int qt_metacall(QMetaObject::Call,int, void **); \
private:
展开一个宏定义QT_TR_FUNCTIONS
,而这里面定义了一个内联的tr
函数。可以看出这里实际是使用了一个静态对象staticMetaObject
的成员函数tr
。
# define QT_TR_FUNCTIONS \
static inline QString tr(const char *s, const char *c = 0) \
{ return staticMetaObject.tr(s, c); } \
static inline QString trUtf8(const char *s,const char *c = 0) \
{ return staticMetaObject.trUtf8(s, c); } \
static inline QString tr(const char *s,const char *c, int n) \
{ return staticMetaObject.tr(s, c, n); } \
static inline QString trUtf8(const char *s,const char *c, int n) \
{ return staticMetaObject.trUtf8(s, c, n); }
例如对于一个QLabel
控件,将其显示的文本使用tr
括起来。tr是经过多级函数调用才实现了翻译操作,是有代价的,所以不该用的时候最好不要用。
QLable *label = new QLable(tr("hello"),this);
这次还是以一个hello world
为例。
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
public slots:
void btn_click();
};
#endif // WIDGET_H
#include "widget.h"
#include <QPushButton>
#include <QMessageBox>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建一个PushButton
QPushButton * btn = new QPushButton(tr("click me"),this);
//连接信号和槽
connect(btn,SIGNAL(clicked()),this,SLOT(btn_click()));
}
Widget::~Widget()
{
}
void Widget::btn_click()
{
QMessageBox::information(NULL, tr("click button"),
tr("hello world"), QMessageBox::Yes);
}
在上面,源文件中的相关字符串已经使用tr
函数包装起来了。现在要做的就是更新这些要翻译的字符串到ts
文件。lupdate
就是用于扫描pro
文件中指定的代码或UI文件中被tr
包装起来的文本。
lupdate
的使用可以使用lupdate --help
来查看。
粗略的说一下这个工具的用法:
使用方法:
lupdate [选项] [项目文件]...
lupdate [选项] [源文件 | 路径 | @ lst 文件]...-ts ts 文件 | @ lst 文件
(lst文件是一个文本文件,保存一些文件名称,一行一个)
常用选项 | 说明 |
---|---|
-ts
|
指定输出文件。 |
-codecfortr
|
指定为 tr() 调用假设的编解码器。只有与-ts 有效。 |
-extensions
|
扩展支持的文件后缀。扩展名列表必须用逗号分隔。默认值: 'java,jui,ui,c,c++,cc,cpp,cxx,ch,h,h++,hh,hpp,hxx,js,qs,qml'。 |
-no-recursive | 指定不递归扫描的目录 |
-recursive | 递归扫描指定目录 |
-I
|
附加的包含文件目录 |
-no-ui-lines | 对ui文件的扫描不保留行号 |
-pro
|
.Pro 文件的名称。对于具有.pro 文件语法,但不同的文件后缀的文件非常有用。 |
-source-language
|
指定新文件的源字符串的语言。默认值Posix 标准。 |
-target-language
|
指定新文件翻译的语言。如果未指定,则猜测系统语言。 |
@lst-file | 从 lst 文件读取附加文件的名称 (每行一个)。 |
这里只生成一个翻译文件zh_hans.ts
,其实可以跟多个文件名来生成多个用于翻译的ts
文件。这个方式会忽略掉pro
文件中指定要生成的翻译文件。
o@o-pc:~/hello$ lupdate hello.pro -ts zh_hans.ts
Updating 'zh_hans.ts'...
Found 3 source text(s) (3 new and 0 already existing)
pro
文件中指定这里我们先修改一个hello.pro
文件。
这是原本的hello.pro
文件:
QT += core gui
TARGET = hello
TEMPLATE = app
SOURCES += main.cpp\
hello.cpp
HEADERS += hello.h
LIBS += -lxcb
现在我们添加一句
TRANSLATIONS = zh_hans.ts
添加之后使用lupdate
来生成zh_hans.ts
文件
o@o-pc:~/hello$ lupdate hello.pro
生成了ts
文件后就要进行翻译了。ts
文件实际上是类似于xml
文件的,我们可以直接打开它来翻译。
先打开看看
我们只需要在<translation>
和</translation>
之间填写我们翻译后的文件即可。
例如我们将"click me"翻译为**"点击我^_^"**。则修改为:
6 <message>
7 <location filename="widget.cpp" line="9"/>
8 <source>click me</source>
9 <translation type="unfinished">点击我</translation>
10 </message>
如果你认为翻译合格了,没有问题了,可以将translation type="unfinished">
中的type="unfinished"
删除。
1、点击菜单栏 文件 --> 打开 弹出文件选择对话框后选择生成的ts文件
2、设置源语言和目标语言,然而并没什么用,(*^__^*)
1、选择要翻译的短语
2、填写翻译的文本
3、翻译完成后记得保存
所谓发布翻译,就是使用lrelease
工具将ts
文件转换输出不包含多余信息的qm
文件(qm文件是二进制文件,非文本文件)。
我们先来看看翻译后的ts
文件。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>Widget</name>
<message>
<location filename="widget.cpp" line="9"/>
<source>click me</source>
<translation>点击我^_^</translation>
</message>
<message>
<location filename="widget.cpp" line="20"/>
<source>click button</source>
<translation>单击按钮</translation>
</message>
<message>
<location filename="widget.cpp" line="21"/>
<source>hello world</source>
<translation>你好 世界</translation>
</message>
</context>
</TS>
lrelease
生成qm
文件o@o-pc:~/hello$ lrelease zh_hans.ts -qm zh_hans.qm
lrelease
使用简要说明使用方法:
lrelease [选项] 项目文件
lrelease [选项] ts 文件 [-qm qm 文件]
选项 | 说明 |
---|---|
-idbased | 使用 Id 而不是源字符串作为消息的键 |
-compress | QM 文件压缩 |
-nounfinished | 不使用未完成的翻译 |
-removeidentical | 如果源文本与翻译后的文本相同,不使用这个 |
-markuntranslated
|
如果消息有没有真正的翻译,使用源文本和
|
在QT程序中要使用翻译文件,需要使用到类QTranslation
。现在来修改main.cpp
.
#include "widget.h"
#include <QApplication>
#include <QTranslator>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator tsor; //创建翻译器
tsor.load("zh_hans.qm"); //加载语言包
a.installTranslator(&tsor); //安装翻译器
Widget w;
w.show();
return a.exec();
}