用tr的有兩類人:
(1)因爲發現中文老出問題,然後搜索,發現很多人用tr,於是他也開始用tr
(2)另一類人,確實是出於國際化的需要,將需要在界面上顯示的文件都用tr包起來,這有分兩種:
(2a) 用tr包住英文(最最推薦的用法,源碼英文,然後提供英文到其他語言的翻譯包)
(2b) 用tr包住中文(源碼用中文,然後提供中文到其他語言的翻譯包)
注意,如果你正在用tr包裹中文字符,卻不屬於(2b),那麼,這是個信號:
- 你在誤用tr
- 你需要的是QString,而不是tr
如果你確實屬於(2b),請做好心理準備,你可能還會遇到很多困難,請考慮Qt國際化(源碼含中文時)的點滴分析
tr 是做什麼的?下面二者的區別是什麼?
QString text1 = QObject::tr("hello");
QString text2 = QString("hello");
tr是用來實現國際化,如果你爲這個程序提供了中文翻譯包(其中hello被翻譯成中文"你好"),那麼text1的內容將是中文"你好";如果你爲程序提供且使用日文翻譯包,那麼text1的內容將是日文。
tr是經過多級函數調用才實現了翻譯操作,是有代價的,所以不該用的時候最好不要用。
關注的對象:
本文關注的是tr或translate中包含中文字符串的情況:
-
QObject::tr()
-
QCoreApplication::translate()
-
QTextCodec::setCodecForTr
這個問題本多少可說的。因爲涉及到的編碼問題和QString 與中文問題中是完全一樣的,只不過一個是用的setCodecForCStrings一個用的是setCodecForTr。
簡單回顧QString的中文問題:
1) QString 採用的unicode,在中文支持上不存在任何問題
2) "我是中文" 這是傳統的 const char * 的窄字符串
3) 當將窄字符串賦值到QString時,我們需要告訴它我們的窄串採用的何種編碼(gbk?、utf-8?)
4) 究竟何種編碼主要取決於我們的源代碼文件的編碼(windows上一般是gbk,其他平臺一般utf-8)
例子:
QString s1 = "我是中文";
QString s2("我是中文");
QString s3;
s3 = "我是中文"
-
s1、s2 用的是QString的構造函數QString ( const char * str )
-
s3 用的是QString的賦值操作符 QString & operator= ( const char * str)
如果不指定編碼,s1,s2,s3將全部都是(國內大多數人所稱的)亂碼。因爲QString將這些const char *按照latin1來解釋的,而不是用戶期待的gbk或utf8。
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"))
這兩條語句中的一條可以解決問題,至於如何選擇,此處不再重複。
QObject::tr()
說實話,在tr中使用中文不是個好主意。不過既然總有人用(無論是(1)還是(2b)),而且總有人遇到問題,所以還是簡單整理一下吧。
相比QCoreApplication::translate,大家用tr應該用的很多了,儘管不少人不清楚tr究竟是做什麼的^_^
tr("我是中文");
這調用的是下面這個函數(至少我們可這麼認爲是)。
QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 )
與QString("我是中文")完全一樣,你必須告訴tr這個窄字符串是何種編碼?你不告訴它,它就用latin1。於是所謂的亂碼問題就出來了。
如何告訴tr你寫的這幾個漢字在磁盤中保存的是何種編碼呢?這正是
QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
所做的。這兩個選擇的原則,由於和前文完全一樣,此處也不再重複。
如果你的編碼採用的utf8,可以直接使用trUtf8而不必設置setCodecForTr。
如果你只關心亂碼問題,到此爲止就可以了。