QT tr与Qstring的差别
在論壇中漂,經(jīng)常遇到有人遇到tr相關(guān)的問題。用tr的有兩類人:
- (1)因?yàn)榘l(fā)現(xiàn)中文老出問題,然后搜索,發(fā)現(xiàn)很多人用tr,于是他也開始用tr
- (2)另一類人,確實(shí)是出于國(guó)際化的需要,將需要在界面上顯示的文件都用tr包起來,這有分兩種:
- (2a) 用tr包住英文(最最推薦的用法,源碼英文,然后提供英文到其他語言的翻譯包)
- (2b) 用tr包住中文(源碼用中文,然后提供中文到其他語言的翻譯包)
注意哦,如果你正在用tr包裹中文字符,卻不屬于(2b),那么,這是個(gè)信號(hào):
- 你在誤用tr
- 你需要的是QString,而不是tr
如果你確實(shí)屬于(2b),請(qǐng)做好心理準(zhǔn)備,你可能還會(huì)遇到很多困難,請(qǐng)考慮Qt國(guó)際化(源碼含中文時(shí))的點(diǎn)滴分析
tr 是做什么的?下面二者的區(qū)別是什么?
QString text1 = QObject::tr("hello"); QString text2 = QString("hello");tr是用來實(shí)現(xiàn)國(guó)際化,如果你為這個(gè)程序提供了中文翻譯包(其中hello被翻譯成中文"你好"),那么text1的內(nèi)容將是中文"你好";如果你為程序提供且使用日文翻譯包,那么text1的內(nèi)容將是日文。
tr是經(jīng)過多級(jí)函數(shù)調(diào)用才實(shí)現(xiàn)了翻譯操作,是有代價(jià)的,所以不該用的時(shí)候最好不要用。
關(guān)注的對(duì)象
本文關(guān)注的是tr或translate中包含中文字符串的情況:
-
QObject::tr()
-
QCoreApplication::translate()
-
QTextCodec::setCodecForTr
這個(gè)問題本多少可說的。因?yàn)樯婕暗降木幋a問題和QString 與中文問題中是完全一樣的,只不過一個(gè)是用的setCodecForCStrings一個(gè)用的是setCodecForTr。
簡(jiǎn)單回顧QString的中文問題
- QString 采用的unicode,在中文支持上不存在任何問題
-
"我是中文"?這是傳統(tǒng)的?const?char?*?的窄字符串
- 當(dāng)將窄字符串賦值到QString時(shí),我們需要告訴它我們的窄串采用的何種編碼(gbk?、utf-8?)
- 究竟何種編碼主要取決于我們的源代碼文件的編碼(windows上一般是gbk,其他平臺(tái)一般utf-8)
例子:
QString?s1?=?"我是中文";?QString?s2("我是中文");?QString?s3;?s3?=?"我是中文"-
s1、s2 用的是QString的構(gòu)造函數(shù)QString?(?const?char?*?str?)
-
s3 用的是QString的賦值操作符?QString?&?operator=?(?const?char?*?str)
如果不指定編碼,s1,s2,s3將全部都是(國(guó)內(nèi)大多數(shù)人所稱的)亂碼。因?yàn)镼String將這些const?char?*按照latin1來解釋的,而不是用戶期待的gbk或utf8。
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"))這兩條語句中的一條可以解決問題,至于如何選擇,此處不再重復(fù)。
QObject::tr
說實(shí)話,在tr中使用中文不是個(gè)好主意。不過既然總有人用(無論是(1)還是(2b)),而且總有人遇到問題,所以還是簡(jiǎn)單整理一下吧。
相比QCoreApplication::translate,大家用tr應(yīng)該用的很多了,盡管不少人不清楚tr究竟是做什么的^_^
?
?
tr("我是中文");這調(diào)用的是下面這個(gè)函數(shù)(至少我們可這么認(rèn)為是)。
QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 )與QString("我是中文")完全一樣,你必須告訴tr這個(gè)窄字符串是何種編碼?你不告訴它,它就用latin1。于是所謂的亂碼問題就出來了。
如何告訴tr你寫的這幾個(gè)漢字在磁盤中保存的是何種編碼呢?這正是
QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312")); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));所做的。這兩個(gè)選擇的原則,由于和前文完全一樣,此處也不再重復(fù)。
如果你的編碼采用的utf8,可以直接使用trUtf8而不必設(shè)置setCodecForTr。
如果你只關(guān)心亂碼問題,到此為止就可以了(下面不再關(guān)注編碼)。如果想對(duì)tr進(jìn)一步了解,不妨。。繼續(xù)。。
?
QCoreApplication::translate
我們知道tr是用于實(shí)現(xiàn)程序的國(guó)際化(或者說多語言翻譯),看Qt相關(guān)資料的話,我們知道實(shí)現(xiàn)該功能的還有下面這個(gè)函數(shù):
QString QCoreApplication::translate ( const char * context, const char * sourceText, const char * disambiguation, Encoding encoding, int n )其實(shí),這個(gè)才是真正進(jìn)行翻譯操作的函數(shù),前面我們提到的tr最終是通過調(diào)用該函數(shù)來實(shí)現(xiàn)翻譯功能的(稍后我們會(huì)看tr是如何調(diào)用translate的)。
對(duì)tr和這個(gè)函數(shù),manual中都有比較詳盡的解釋。我們這兒簡(jiǎn)單看一下它的這幾個(gè)參數(shù):
- context 上下文,一般就是需要翻譯的字符串所在的類的名字
- sourceText 需要翻譯的字符串。(我們關(guān)注的編碼其實(shí)就是它的編碼)
- disambiguation 消除歧義用的。(比如我們的類內(nèi)出現(xiàn)兩處"close",一處含義是關(guān)閉,另一處含義是親密的。顯然需要讓翻譯人員知道這點(diǎn)區(qū)別)
- encoding 指定編碼。它有兩個(gè)值
-
CodecForTr?使用setCodecForTr()設(shè)置的編碼來解釋 sourceText
- UnicodeUTF8 使用utf8編碼來解釋 sourceText
- 其實(shí)這兩個(gè)分別對(duì)應(yīng)tr和trUtf8
-
- n 處理單復(fù)數(shù)(對(duì)中文來說,不存在這個(gè)問題)
tr與translate
這兩個(gè)函數(shù)的說明,一個(gè)在QObject的manual,另一個(gè)在QCoreApplication的manual中。
介紹一下tr與translate的關(guān)系。前面提到了,tr調(diào)用的是translate。如果僅僅這樣一說,沒有證據(jù),還真難以讓大家相信。好吧,繼續(xù)
tr 在何處定義
你可能說:這不廢話嗎,manual中寫得明白的,它是QObject的靜態(tài)成員函數(shù)。而且還有源碼為證:
//來自 src/corelib/kernel/qobject.h?#ifdef qdoc?static?QString?tr(const?char?*sourceText,const?char?*comment?=?0,?int?n?= -1);?static?QString?trUtf8(const?char?*sourceText,?constchar?*comment?=?0,?int?n?= -1);?#endif嘿嘿,差點(diǎn)就被騙了,發(fā)現(xiàn)沒:它們被預(yù)處理語句包住了。
這說明了什么呢?說明了這段代碼僅僅是用來生成Qt那漂亮的文檔的(qdoc3從代碼中抽取信息,生成一系列的html格式的manual)。
啊,也就是說,這是假的。那么真正的定義呢??在一個(gè)大家都很熟悉的地方,猜猜看?
這就是
Q_OBJECT該宏的定義在src/corelib/kernel/qobjectdefs.h中
#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
#?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); }現(xiàn)在看到:tr調(diào)用的是 staticMetaObject對(duì)象的tr函數(shù),staticMetaObject 的定義在moc生成的 xxx.moc 或 moc_xxx.cpp 文件內(nèi)(你隨時(shí)可以驗(yàn)證的)。
staticMetaObject 是一個(gè) QMetaObject 類的實(shí)例,我們繼續(xù)看一下該類的源碼:
/*!??\internal?*/??QString?QMetaObject::tr(const?char?*s,?const?char?*c)?const??{??returnQCoreApplication::translate(d.stringdata,?s,?c,?QCoreApplication::CodecForTr);??}??/*!?\internal?*/?QString?QMetaObject::trUtf8(const?char?*s,?const?char?*c)?const?{?returnQCoreApplication::translate(d.stringdata,?s,?c,?QCoreApplication::UnicodeUTF8);}
總結(jié)
以上是生活随笔為你收集整理的QT tr与Qstring的差别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SEO高级指令
- 下一篇: java 日期calendar_java