QT實現多國語言的動態切換


摘要:本文論述瞭如何使用QT實現程序的多語系支持以及多語系的動態切換。

前沿

我們生活中用到的程序大多都是支持單一語言的,比如在中國我們用到的軟件大多是漢語的,也有很少部分使用的是英語的,但是很少有軟件可以實現兩種語言的動態切換。不過隨着近幾年我國的發展支持多國語言的軟件也越來越多,比如上海地鐵售票機,動車組自動售票機等都是支持漢語和英語兩種語言的。使用QT編程可以很容易的編寫支持多國語言的軟件。

QT實現多國語言支持有兩種情況:

第一種:使用UI編輯器來自動生成界面,這種方式實現多語系的動態切換很容易。

第二種:不使用UI編輯器,自己通過親自編程來設計應用程序界面,這種方式實現多語系動態切換比較繁瑣,注意不是難;

下面先來介紹第一種的實現方法:

voidMainWindow::ch_language()
{
    if(this->languageState)
    {
        this->languageState=CHINESE ;
       this->translator.load("test_ch") ;
       this->pOwner->installTranslator(&(this->translator));
    }
    else
    {
        this->languageState=ENGLISH ;
       this->translator.load("test_en") ;
       this->pOwner->installTranslator(&(this->translator));
    }
}
這個函數是實現動態切換的主要程序,其中languageState是用來記錄當前語言的狀態,pOwnerQApplication對象,我們只需使用QTranslator加載不同的文件就可以實現多語系的動態切換。

第二種方式就不那麼簡單了,除了要運行上述函數外還要將將要切換的語言重新設置一遍。

voidMainWindow::langChang()
{
    if(this->langState)
    {
        this->langState=CHINESE ;
       this->translator.load("test_ch") ;
       this->pOwner->installTranslator(&(this->translator));
    }
    else
    {
        this->langState=ENGLISH ;
       this->translator.load("test_en") ;
       this->pOwner->installTranslator(&(this->translator));
    }

   this->setWindowTitle(QObject::tr("hello world"));
    this->addFileAction->setText(QObject::tr("NewFile"));
   this->langChAction->setText(QObject::tr("Chinese"));
   this->playAction->setText(QObject::tr("Play")); ;
   this->stopAction->setText(QObject::tr("Stop"));
   this->menuBar()->addMenu(QObject::tr("FIle")) ;
    this->menuBar()->addMenu(QObject::tr("Control"));
}

因此比較麻煩,特別是界面比較繁瑣的時候,將是很麻煩的。

下面來討論爲什麼第一種方法爲什麼不需要重新設置語言了。因爲使用Ui時有這個函數

voidMainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);//
這裏實現語言翻譯器的更新。

 

 

 

下面就來看一下QT中如何製作多語言包。

實現方法:

       爲了支持國際化最關鍵的地方是製作多國語言包,然後再實現動態切換。QT裏面既可以採用命令行也可以採用Qt Creator的界面操作來生成,這裏我們利用Qt Creator來生成多國語言包。基本流程是,先生成ts文件,然後生成qm文件,最後通過QTranslator類來加載qm文件,實現多語言包的切換。注意:爲了更全面地實現多語言包,在程序中所有涉及到界面中的按鈕或者菜單中的文字顯示,都必須使用 QObject::tr("...") 的方式將顯示的內容包裹起來,這樣做的原因是:只有添加了QObject::tr()的標記,生成ts文件的時候程序纔會認爲被QObject::tr()包裹的地方是需要製作多語言的,從而在ts中預留出位置。

1> 生成ts文件

     在QT的項目文件(.pro)中添加:TRANSLATIONS = XXX.ts YYY.ts(如果是多行,則用 \ 分割)

     

     然後執行【工具】-》【外部】-》【QT語言家】-》【更新翻譯(lupdate)】,如下圖所示,執行完之後項目下就會生成對應的XXX.ts、YYY.ts文件。

     

     注意:如果項目中包含ui文件,如:FORMS += ZZZ.ui,則在生成的ts文件中包含所有ui文件上的字符顯示,而且,在製作ui文件時默認情況下界面上的文字顯示都是通過QObejct::tr(" ")包裹的,因爲在默認情況下ui中的所有控件都存在一個屬性:可翻譯的,就代表了默認用QObject::tr()嵌套了。

2. 生成qm文件

    利用QT語言家:Linguist打開生成的ts文件,將裏面需要翻譯的地方寫上對應的語言,如下圖所示:

   

   ts文件翻譯完成後,執行Qt Creator中的【工具】-》【外部】-》【QT語言家】-》【部署翻譯(lrelease)】就會生成最終要用到的qm文件,如下圖所示:

  

3. 加載qm語言包

     到這裏qm語言包製作完成,工作就完成了一大半了。接下來的任務就是在代碼中實現語言包的加載,即:根據不同的選擇加載不同的語言包。    

voidLHSyncClientPrivate::InitUiByLanguage(const QString strLanguage)

{

    if (strLanguage.isEmpty())

    {

        return;

    }

 

    QString strLanguageFile;

    if (strLanguage.compare("en") ==0)

    {

        strLanguageFile = qApp->applicationDirPath()+QString("/languages/%1/%2").arg(LHT_SYNCCLIENT_VERSION_PRODOCUTNAME).arg(LHT_SYNCCLIENT_EN_FILE);

    }

    else if(strLanguage.compare("zh") == 0)

    {

        strLanguageFile =qApp->applicationDirPath() + QString("/languages/%1/%2").arg(LHT_SYNCCLIENT_VERSION_PRODOCUTNAME).arg(LHT_SYNCCLIENT_ZH_FILE);

    }

 

    if (QFile(strLanguageFile).exists())

    {

        m_translator->load(strLanguageFile);

       qApp->installTranslator(m_translator);

    }

    else

    {

        qDebug() << "[houqd]authclient language file does not exists ...";

    }

}

其中,m_translator即爲QTranslator實例,在類的構造函數中賦值:m_translator = new QTranslator;實現過程很簡單,就是取得語言包的絕對路徑,然後利用QTranslator來加載它,最後利用qApp->installTranslator(m_translator)來安裝。

4. 重新設置界面顯示

    重新設置界面的顯示,這一步是很多人容易忘記的一步,如果這兒被忽略了,往往就無法完成語言的切換,即:重新設置一下需要顯示的元素,該過程是在上面InitUiByLanguage過程之後進行的,相關代碼如下:

voidLHSyncClientPrivate::RetranslateUi()

{

    m_wgtSync->setWindowTitle(tr("DriveClient"));

       

    //! 左側同步信息

   m_btnSynchronizing->setText(tr("Synchronizing"));

   m_btnSynchronized->setText(tr("Synchronized"));

 

    //! 右側面板

   m_lblSyncStatus->setText(tr("looking for fileschanges..."));

   m_lblShowRecordsNum->setText(tr("There are n records..."));

    m_btnSyncOrPause->setText(tr("SyncOr Pause"));

    m_btnClearAll->setText(tr("Clearall"));

    m_btnSyncOrPause->setText(tr("SyncOr Pause"));

 

   m_btnClose->setText(tr("Close"));

    m_actSync->setText(tr("SyncInfo"));

}

實現效果:

       好了,到這裏整個語言包的製作過程就基本完成了。這裏還需要提及一點在網盤客戶端實現時的設計思路:由於網盤在登錄前和登錄後可操作的菜單是不一樣的,要涉及一種動態加載的方式,可以實現一個UiLoader的插件,它實現所有的窗體加載(即LoadUi()返回QWidget句柄)、菜單加載、語言切換,在這些功能中可能UiLoader插件並不完成具體的工作,而僅僅是實現信號的轉發功能。同樣,也需要實現一個邏輯控制插件,它負責所有的菜單邏輯,而對於每個窗體則由各自的窗體插件自行完成。多語言切換的實現效果如下:

           

切換爲中文:

         

切換後效果:

       

加油,堅持每天的學習!!

 

 

 

 

 

 

 

 

 

 

 

 

發佈了18 篇原創文章 · 獲贊 12 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章