Qt4.5多國語界面動態(tài)切換的實現(xiàn)
|
|
|
作者:wangxinus, <[email protected]> 來源:http://wangxinus. 說明:原創(chuàng)文章歡迎轉載,交流請Email給作者
最近一直在折騰Qt,,不過偶爾也會分分心,,做了一些C++筆試題,發(fā)現(xiàn)自己的很多基礎知識還不牢固,,可悲?。?br> 多國語界面的實現(xiàn),,在MFC中是很別扭的,。以前在作MFC時,實現(xiàn)多國語言的界面,,只有把資源文件做成各個語言的資源DLL,,在程序啟動時,根據(jù)選擇判斷選擇載入哪個DLL來獲取資源,。MFC的資源也是分語言的,,在創(chuàng)建資源的時候要選擇,但是這樣的實現(xiàn)還有有弊端,。最根本的原因是MFC的資源文件不是Unicode編碼的,,而是不同語言的本地碼,至少VC6是這樣的,。這樣在中文系統(tǒng)中載入日文的資源,,界面出現(xiàn)的是亂碼。
Qt內(nèi)部采用的全Unicode編碼,,這從根本上保證了多國語界面實現(xiàn)的正確性和便捷性,。Qt本身提供的linguist工具,就是來實現(xiàn)這個翻譯過程的,。實現(xiàn)多國語的步驟大體上說來有這么幾步: 1,、在需要被翻譯的字符串前面標識tr,如QString str=tr(“hello,world!”); ,,這很重要,,因為翻譯工具會把源碼中tr標識的字符串提取出來,翻譯成其他語言,,如果沒有用tr標識的,,不會被工具提取。在界面中輸入的文字,,默認已經(jīng)是加上tr的了,,所以在翻譯時也能看見。建議:在程序中的字符串使用英文,,漢語等通過多國語翻譯來實現(xiàn),,而不要采取把漢字寫在代碼中,。 2、在工程文件***.pro中,,添加一項 TRANSLATIONS += ***.ts ****.ts 擴展名為.ts是翻譯的源文件,,表示生成這幾個文件。一般我們會在命名中把區(qū)域加進去,,更好的注釋這些文件是用于什么語言的,,比如中文大多會這樣命名 myapp_zh_CN.ts, zh_CN表示的就是中國,。 3,、使用lupdate工具提取翻譯源文件, 命令是這樣的 #lupdate ***.pro ,,lupdate會解析***.pro即工程文件,,生成TRANSLATIONS中的 ***.ts 幾個文件,這些文件可以被linguist工具打開,,按照提示一個一個的翻譯成需要的文件,,然后保存就OK,linguist的使用很簡單,,一看界面基本就會了,。上面提到的這些工具都是Qt自帶的。 4,、使用lrelease工具發(fā)布翻譯文件的二進制文件,,這樣在程序運行時載入會大大的加快速度。使用方式是#lrelease ***.pro,,這個工具會提示你多少語句被翻譯,,多少被忽略了等,。生成的文件是 ***.qm,,于同名的 ***.ts只是換了一個擴展名。而這才是我們程序需要使用到的文件,。 5,、使用***.qm文件。關于這個,,我想還是摘抄書上的原文來說明一下:
切換語言分為兩種情況:
1. 程序載入的時候,,根據(jù)當前的區(qū)域設置,自動選擇語言包(.qm),,即可,;
2. 要求在程序運行過程中動態(tài)切換語言,需要
第一種情況,,一般在main函數(shù)中程序啟動的部分加入如下代碼:
QString locale = QLocale::system().name()); // for example: zh_CN, en_US
QTranslator *translator = new QTranslator(app);
translator->load(QString("./language/" + locale)); // 會在當前目錄下的language目錄下尋找,,可以不帶".qm"后綴名
app->installTranslator( translator ); // 安裝翻譯器
第二種情況,,我們假設有一個QComboBox連接了changeLang的槽:
connect(langCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changeLang(int)) );
// 載入不同的語言包
void WizarDialog::changeLang( int langIndex )
{
QTranslator *translator = new QTranslator(qApp);
switch( langCombo->currentIndex() ){
case 0:
translator->load(QString("./language/pt_BR"));
break;
case 1:
translator->load(QString("./language/en_US"));
break;
case 2:
translator->load(QString("./language/zh_CN"));
default:
break;
}
qApp->installTranslator( translator );
this->initGUI();
}
// initGUI() 中會有大量的tr函數(shù)
void WizarDialog::initGUI()
{
this->setWindowTitle(tr("RTA04W"));
/* ...... */
}
這兩種情況,也可以復合起來用,。
|
需要說明的時,, 一般我們使用設計器來設計界面UI,也就是程序源碼中我們看到的 ***.ui文件,,在載入翻譯器后,,我們應該調(diào)用 ui->retranslateUi() ,這個函數(shù)實際上就是把界面控件的text重新載入一遍,,可以在 ui_***.cpp中看到該函數(shù)的實現(xiàn),。 5、在幫助文檔中,,關于QTranslator::load有這樣一句話,。
The data is not copied. The caller must be able to guarantee that data will not be deleted or modifiled.
|
這段話明確的說明了,QTranslator在load以后,,并沒有把qm文件中的數(shù)據(jù)拷貝一份,,而是在需要的時候去查詢字符串。如果qm在這期間被刪除或修改,,對程序都是有影響的,。擴展開來,QTranslator必須保證要一直有效,,如果在函數(shù)中定義的局部變量,,函數(shù)結束后就自動釋放掉了,那么翻譯工作就不能正常進行,。所以建議在private中定義個成員變量 QTranslator* app_translator;來確保整個翻譯工作的正確性,。
如果你也喜歡Qt,有什么疑問和提議,,我們可以交流一下,,歡迎聯(lián)系。
|
|
|