[Qt Topic] – 中文化研習,做一個多語言的簡易天氣預報器
作者: Jason Lee
日期: 2010-04-01 -- 2010-04-02
平台: Qt SDK v2010.02.1 + Windows Xp
聲明: 文章作者僅在Intel軟體網絡 和CSDN部落格 發表本文,如有轉載,請注明出處。
[1] 簡單地使用 QTextCodec 和 tr 配合
在預設情況下,我們直接在源碼 中使用中文,比如 setWindowTitle(tr(" 中文化研習 ")); ,則會在運作界面發現中文亂碼。遇到這種問題,如果無需考慮國際化,則可以直接使用 QTextCodec 設定編碼方式:
view plain copy to clipboard print ?
- QTextCodec::setCodecForTr(QTextCodec::codecForName( "GB18030" ));
QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030"));
該語句需要包含頭檔案 #include <QTextCodec> 。
選擇 GB18030 而不是 GBK 或者 GB2312 是因為前者的漢字收錄更豐富,并向下相容了後兩者。但是在嵌入式裝置上,如手機或 MP3 ,并不一定支援 GB18030 。
而既然是 setCodecForTr ,那麼就應該在第一次對 tr() 的調用之前設定編碼方式,一般應該在 main() 函數中緊接 Qapplication 對象建立後設定。 tr() 用來傳回一個翻譯過的文本版本,在編寫代碼的過程中,對每一個使用者可見的文本都應該加上 該函數。
這樣設定了以後,基本的中文顯 示,如按鈕文本、視窗标題以及文本編輯區域,都可以得到良好的顯示。
值得一提的是,如果出現的不是 亂碼,而是問号,則可能是字元編碼内無該字的編碼。另外一種問題是,如果出現的是方框(正方形),而不是亂碼,則可能是無該指定字型,可以通過設定 QFont 嘗試解決該問題。
[2] 關于使用 QString 來顯示中文
一是使用 toLocal8Bit 和 fromLocal8Bit 。比如下述代碼就可以良好地顯示中文:
view plain copy to clipboard print ?
- QString gbText;
- gbText = gbText.fromLocal8Bit("漢化" );
- btn = new QPushButton(gbText);
QString gbText;
gbText = gbText.fromLocal8Bit("漢化");
btn = new QPushButton(gbText);
通過這種方式可以使用系統的本 地 8 位編碼格式。
二是通過 QString 和 QTextCodec 結合,設定在 const char * 和 Qstring 之間轉換時使用的編碼格式,比如下述代碼也可以使得漢字良好顯示:
view plain copy to clipboard print ?
- QTextCodec::setCodecForCStrings(QTextCodec::codecForName( "GB18030" ));
- QString str = "漢化" ;
- textEdit->append(str);
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB18030"));
QString str = "漢化";
textEdit->append(str);
[3] 使用 Qt 翻譯家
Qt 提供了外部的翻譯檔案,隻要對需要進行翻譯的文本使用 tr() 函數,然後在 .pro 工程檔案中添加 TRANSLATIONS = localizer.ts ,這裡的檔案名自然要根據具體需要設定。之後使用 lupdate 指令,如 lupdate localizer.pro ,生成 localizer.ts 。接着用 linguist 打開 localizer.ts ,并在檔案裡面進行相應文本的翻譯,儲存後釋出,生成 localizer.qm 。
至此,在包含了頭檔案 #include <QTranslator> 後,即可以安裝翻譯家,将相應的文本進行翻譯:
view plain copy to clipboard print ?
- QTranslator translator;
- translator.load(":/localizer" );
- app.installTranslator(&translator);
QTranslator translator;
translator.load(":/localizer");
app.installTranslator(&translator);
此時再運作程式,則可以發現界 面上的文本已經得到翻譯了。
補充:在上述代碼中, localizer.qm 是由 qrc 檔案指定位置的,本例中 localizer.qm 相對于 qrc 檔案的位置是“ /localizer.qm ”,是以添加的時候使用“ :/localizer ”。而如果 qm 檔案相對于 qrc 檔案的位置是“ /translator/localizer.qm ”,則需要指定為“ :/translator/localizer.qm ”。
[4] 檔案讀寫中的中文
這裡以讀取 Google 的天氣 API 為例。
Google 的中文天氣 API 為 http://www.google.com/ig/api?hl=zh_cn&weather= ,等号後面加城市名,比如“ beijing ”或者“ hongkong ”。
該 API 是以 XML 格式給出資訊,而如果我們不加以修飾地直接讀取該 XML 檔案的話,則會出現如“ é£ åï ¼ ä ¸åã é£ é ”之類的亂碼。
針對這種情況,可以先使用(不 一定必須使用) QString 存放資訊,因為可以用 QTextCodec 對 QString 進行編碼格式的設定:
view plain copy to clipboard print ?
- QTextCodec::setCodecForCStrings(QTextCodec::codecForName( "UTF-8" ));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
這樣的話就可以以相應的編碼格 式進行檔案讀取。運作後,可以看到中文顯示正常。
同樣地,使用其它方式進行檔案 讀取的話也可以使用類似設定編碼格式的方法。比如,使用 QTextStream 時,如果希望使用特定的編碼進行讀寫,則可以使用該類的成員函數 setCodec() 。
[5] 可動态切換語言的天氣預報器
關于這個話題可以精煉成以下幾點(具體的完整代碼将會在後面給出):
1 、動态的語言切換的實作是通過在運作時,使用者進行語言選擇時觸發的信号引起相應槽的運 作。比如可以設定一個語言菜單供使用者選擇語言,我在這裡隻設定了英語和中文。當使用者點選菜單選項的時候,利用 QTranslator 進行不同 qm 檔案的重新載入,然後再重繪可見文本。是以這就要求:一是使用者可見的文本應該用 tr() 函數處理,畢竟這不是一樣很大的負擔,最好将其養成習慣;二是生成使用者可見文本的代碼最 好放在一個函數裡,為了取名有意義可以取做 retranslateUi() 。
view plain copy to clipboard print ?
- void QWR::retranslateUi(){
- enAct->setText(tr("&English" ));
- cnAct->setText(tr("&Chinese" ));
- languageMenu->setTitle(tr("&Language" ));
- cityLabel->setText(tr("City" ));
- runBtn->setText(tr("&Run" ));
- setWindowTitle(tr("QWeatherReporter" ));
- }
void
QWR::retranslateUi(){
enAct->setText(tr("&English"));
cnAct->setText(tr("&Chinese"));
languageMenu->setTitle(tr("&Language"));
cityLabel->setText(tr("City"));
runBtn->setText(tr("&Run"));
setWindowTitle(tr("QWeatherReporter"));
}
2 、天氣預報的功能是通過調用 Google API 實作的,需要注意的是溫度機關在國内外的不同。如果目前使用者選擇英文,就選擇英文 API ,同樣的,如果使用者選擇中文,就設定 URL 為中文 API 位址。這就需要在編碼的時候進行判斷,判斷的方式有多種。
view plain copy to clipboard print ?
- QString url;
- if (cnAct->isChecked()){
- url = "http://www.google.com/ig/api?hl=zh_cn&weather=" ;
- url.append(cityBox->text());
- }else {
- url = "http://www.google.com/ig/api?hl=en&weather=" ;
- url.append(cityBox->text());
- }
- request.setUrl(QUrl(url));
QString url;
if(cnAct->isChecked()){
url = "http://www.google.com/ig/api?hl=zh_cn&weather=";
url.append(cityBox->text());
}else{
url = "http://www.google.com/ig/api?hl=en&weather=";
url.append(cityBox->text());
}
request.setUrl(QUrl(url));
3 、 Google 天氣 API 給的結果是 XML 格式的,是以參考 [4] 中提到的,要設定編碼格式。正确讀取 XML 資料後,再根據結點名稱擷取具體的天氣資料,如最高溫、最低溫以及日期等。
view plain copy to clipboard print ?
- QTextCodec::setCodecForCStrings(QTextCodec::codecForName( "UTF-8" ));
- QString xmlFile = reply->readAll();
- if (xmlFile.size() < 1000){ //Error city information
- resultBox->setText("No Such City!" );
- return ;
- }
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
QString xmlFile = reply->readAll();
if(xmlFile.size() < 1000){ //Error city information
resultBox->setText("No Such City!");
return ;
}
4 、最後就是将天氣預報的結果呈現出來。

[ 結語 ] 這個小程式我給放到了 http://qwr.sf.net ,各位如果有興趣去可以下載下傳完整源碼。由于陸續有朋友郵件我說需要源碼(其實 sf.net上有),是以我給放到了CSDN資源上,位址為:http://download.csdn.net/source/2231965
[補充]後來,我在寫一個程式的時候發現使用GB18030(或者GBK、GB2312也一樣)在我 的機子上運作是OK的,但是拿到其他機子(同樣的系統)卻出現了亂碼,這令我很是驚訝。不過後來還是尋求了一個解決方案,就是設定目前編碼為本地編碼:
view plain copy to clipboard print ?
- QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
- QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
這可能是樓下的朋友提出的不管輸什麼城市都是“No Such City”的原因,可以如此修改一番。