本文的重點在於QT界面顯示的中文化。
##1、控制需要翻譯的文本
在編寫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
爲例。
###先看hello.h
#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
###再看hello.cpp
#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);
}
##2、lupdate更新翻譯
在上面,源文件中的相關字符串已經使用tr
函數包裝起來了。現在要做的就是更新這些要翻譯的字符串到ts
文件。lupdate
就是用於掃描pro
文件中指定的代碼或UI文件中被tr
包裝起來的文本。
###lupdate的使用 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 or -I | 附加的包含文件目錄 |
-no-ui-lines | 對ui文件的掃描不保留行號 |
-pro | .Pro 文件的名稱。對於具有.pro 文件語法,但不同的文件後綴的文件非常有用。 |
-source-language [_] | 指定新文件的源字符串的語言。默認值Posix 標準。 |
-target-language [_] | 指定新文件翻譯的語言。如果未指定,則猜測系統語言。 |
@lst-file | 從 lst 文件讀取附加文件的名稱 (每行一個)。 |
###生成ts文件 ####1、在命令行中指定方式生成 這裏只生成一個翻譯文件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)
####2、在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
##3、linguits翻譯文本
生成了ts
文件後就要進行翻譯了。ts
文件實際上是類似於xml
文件的,我們可以直接打開它來翻譯。
###1、直接翻譯
先打開看看
我們只需要在<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"
刪除。
###2、使用linguits工具翻譯 1、點擊菜單欄 文件 --> 打開 彈出文件選擇對話框後選擇生成的ts文件 2、設置源語言和目標語言,然而並沒什麼用,(__)
1、選擇要翻譯的短語 2、填寫翻譯的文本 3、翻譯完成後記得保存
##4、lrelease發佈翻譯 所謂發佈翻譯,就是使用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 | 如果消息有沒有真正的翻譯,使用源文本和 |
##4、在程序中使用翻譯文件 在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();
}
編譯後運行看看。把
zh_hans.qm拷貝到項目工作目錄