天天看點

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是用來記錄目前語言的狀态,pOwner是QApplication對象,我們隻需使用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實作多國語言的動态切換

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

QT實作多國語言的動态切換

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

2. 生成qm檔案

    利用QT語言家:Linguist打開生成的ts檔案,将裡面需要翻譯的地方寫上對應的語言,如下圖所示:

QT實作多國語言的動态切換

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

QT實作多國語言的動态切換

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

QT實作多國語言的動态切換

切換為中文:

QT實作多國語言的動态切換

切換後效果:

QT實作多國語言的動态切換

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

繼續閱讀