天天看點

QT程式設計國際化的點點滴滴

[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 ?

  1. 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 ?

  1. QString gbText;  
  2. gbText = gbText.fromLocal8Bit("漢化" );  
  3. 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 ?

  1. QTextCodec::setCodecForCStrings(QTextCodec::codecForName( "GB18030" ));  
  2. QString str = "漢化" ;  
  3. 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 ?

  1. QTranslator translator;  
  2. translator.load(":/localizer" );  
  3. 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 ?

  1. 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 ?

  1. void  QWR::retranslateUi(){  
  2.     enAct->setText(tr("&English" ));  
  3.     cnAct->setText(tr("&Chinese" ));  
  4.     languageMenu->setTitle(tr("&Language" ));  
  5.     cityLabel->setText(tr("City" ));  
  6.     runBtn->setText(tr("&Run" ));  
  7.     setWindowTitle(tr("QWeatherReporter" ));  
  8. }  

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 ?

  1. QString url;  
  2. if (cnAct->isChecked()){  
  3.     url = "http://www.google.com/ig/api?hl=zh_cn&weather=" ;  
  4.     url.append(cityBox->text());  
  5. }else {  
  6.     url = "http://www.google.com/ig/api?hl=en&weather=" ;  
  7.     url.append(cityBox->text());  
  8. }  
  9. 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 ?

  1. QTextCodec::setCodecForCStrings(QTextCodec::codecForName( "UTF-8" ));  
  2. QString xmlFile = reply->readAll();  
  3. if (xmlFile.size() < 1000){   //Error city information   
  4.     resultBox->setText("No Such City!" );  
  5.     return  ;  
  6. }  

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

QString xmlFile = reply->readAll();

if(xmlFile.size() < 1000){ //Error city information

resultBox->setText("No Such City!");

return ;

}

4 、最後就是将天氣預報的結果呈現出來。

QT程式設計國際化的點點滴滴
QT程式設計國際化的點點滴滴

[ 結語 ] 這個小程式我給放到了 http://qwr.sf.net ,各位如果有興趣去可以下載下傳完整源碼。由于陸續有朋友郵件我說需要源碼(其實 sf.net上有),是以我給放到了CSDN資源上,位址為:http://download.csdn.net/source/2231965

[補充]後來,我在寫一個程式的時候發現使用GB18030(或者GBK、GB2312也一樣)在我 的機子上運作是OK的,但是拿到其他機子(同樣的系統)卻出現了亂碼,這令我很是驚訝。不過後來還是尋求了一個解決方案,就是設定目前編碼為本地編碼:

view plain copy to clipboard print ?

  1. QTextCodec::setCodecForTr(QTextCodec::codecForLocale());  
  2. QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());  

QTextCodec::setCodecForTr(QTextCodec::codecForLocale());

QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());

這可能是樓下的朋友提出的不管輸什麼城市都是“No Such City”的原因,可以如此修改一番。

繼續閱讀