1. 程式人生 > >QT實現多國語言的動態切換

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外掛並不完成具體的工作,而僅僅是實現訊號的轉發功能。同樣,也需要實現一個邏輯控制外掛,它負責所有的選單邏輯,而對於每個窗體則由各自的窗體外掛自行完成。多語言切換的實現效果如下:

           

切換為中文:

         

切換後效果:

       

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