1. 程式人生 > >Qt、QML動態語言切換功能的實現

Qt、QML動態語言切換功能的實現

        本例jic+介紹了qml混合程式設計的du執行多語言翻譯,工程目錄及執行效果如下圖:

一、生成資原始檔

1.在pro中ti新增需要多語言翻譯所需要的檔案,這樣編譯工程時會自動生成這兩個ts檔案。

TRANSLATIONS = language_zh_cn.ts \
               language_en_us.ts

2.使用Qt Creator自帶的工具生成ts檔案

3.開啟Qt Linguist工具(該工具在裝Qt Creator一般預設是安裝的),分別開啟兩個檔案,進行翻譯,儲存(英文也可以不翻譯)。

4.翻譯完畢,執行步驟2中的第二個工具,將會由ts檔案生成qm檔案,這就是動態語言翻譯所需要的資原始檔。

二、動態載入資原始檔

        在下面這個例子中,Translator作為一個語言翻譯類以單例的形式存在。

1.初始化

Translator.h

#ifndef TRANSLATOR_H
#define TRANSLATOR_H

#include <QObject>
class QTranslator;

class Translator : public QObject
{
    Q_OBJECT
public:
    static Translator* getInstance();

private:
    explicit Translator(QObject *parent = 0);
    ~Translator();

signals:
    void languageChanged();

public slots:
    void loadLanguage(QString lang);

private:
    QTranslator*  m_translator;
};

#endif // TRANSLATOR_H

Translator.cpp

#include "Translator.h"
#include <QTranslator>
#include <QApplication>
#include <QDebug>

Translator *Translator::getInstance()
{
    static Translator transInstance;
    return &transInstance;
}

Translator::Translator(QObject *parent) : QObject(parent)
{
    m_translator = new QTranslator;
}

Translator::~Translator()
{
    delete m_translator;
}

void Translator::loadLanguage(QString lang)
{
    qDebug()<<"load"<<lang;
    if(NULL == m_translator)
    {
        return;
    }

    if(lang.contains("English"))
    {
        if(m_translator->load(":/language_en_us.qm"))
        {
            QApplication::installTranslator(m_translator);
            emit languageChanged();
        }
        else
        {
            qDebug()<<"load en error";
        }
    }
    else
    {
        if(m_translator->load(":/language_zh_cn.qm"))
        {
            QApplication::installTranslator(m_translator);
            emit languageChanged();
        }
        else
        {
            qDebug()<<"load cn error";
        }
    }
}

main.c

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    Translator::getInstance()->loadLanguage("Chinese");//初始化為中文
    
    MainWindow w;
    w.show();

    return a.exec();
}

2.QWidget新增動態翻譯支援

步驟1只能支援靜態設定,要想實現動態切換,需要在每個類中加入兩個函式changEvent(QEvent *event)和translateUI(),

具體解釋見程式碼標註:

maindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void changeEvent(QEvent* event);//用於動態翻譯
    void translateUI();//執行動態翻譯

signals:
    void sigSendPowerInitData(QString str);
    void sigSendTimeInitData(QString str);

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

void MainWindow::changeEvent(QEvent *event)
{
    switch (event->type()) {
    case QEvent::LanguageChange:
        translateUI();
        break;
    default:
        QMainWindow::changeEvent(event);
        break;
    }
}

void MainWindow::translateUI()
{
    ui->retranslateUi(this);
    /*跳轉到retranslateUi()函式,實際它執行了以下操作:重新設定了需要翻譯的文字。
     *在這個例子中ui是通過Qt Designer實現的,如果是自己new的部件也是同樣的處理方法,重新設定本類中需要翻譯的文字,qml檔案中也是類似的處理
     *
    void retranslateUi(QMainWindow *MainWindow)
    {
        label->setText(QApplication::translate("MainWindow", "This is a label", Q_NULLPTR));
        pushButton->setText(QApplication::translate("MainWindow", "Switch Language", Q_NULLPTR));
        pushButton_2->setText(QApplication::translate("MainWindow", "Show QML Page", Q_NULLPTR));
    }

    */
}

3.QML中新增動態翻譯支援

類似c++中的做法,qml動態翻譯的處理也是重新設定需要翻譯的文字。

如上所述,Translator::loadLanguage()被呼叫時執行動態語言的載入,同時發出一個languageChanged()訊號,該訊號在下面被接收處理,從而完成動態載入。關於Connections以及混合程式設計的知識參考:

Connections
    {
        target: translator
        onLanguageChanged:{
            initTranslator();
        }
    }

    function initTranslator(){
        m_txt.text = qsTr("Power/w");
        textChinese.text = qsTr("Chinese");
        textEnglish.text = qsTr("English");
    }

4.我們也可以在qml頁面完成語言切換

這裡是通過translator來呼叫loadLanguage(),載入語言檔案後發出languageChanged()訊號,從而觸發qml頁面的重新翻譯。

Button{
    id:btnEnglish
    anchors.left: scaleLayout.right
    anchors.leftMargin: 40
    anchors.verticalCenter: parent.verticalCenter
    anchors.verticalCenterOffset: -50
    Text {
        id : textEnglish
        anchors.centerIn : btnEnglish
        text: qsTr("English")
        color: "white"
        font.pointSize: fontButtonSize
    }
    onClicked: {
        translator.loadLanguage("English");
    }
    style: buttonStyle
}

三、需要注意的幾個點

1.QML上下文屬性設定

//點選按鈕彈出qml頁面的操作
void MainWindow::on_pushButton_2_clicked()
{
    QQuickWidget *quickWidget = new QQuickWidget();
    quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
    quickWidget->setAttribute(Qt::WA_DeleteOnClose);
    quickWidget->setClearColor(QColor(Qt::transparent));

    //這裡要注意:下面這個語句必須要在quickWidget->setSource()執行前執行,否則qml在載入的時候無法識別“translator”
    quickWidget->rootContext()->setContextProperty("translator", Translator::getInstance());

    quickWidget->setSource(QUrl(QStringLiteral("qrc:/PowerSetting.qml")));
    //quickWidget->setWindowFlags(Qt::FramelessWindowHint);
    quickWidget->show();

    QQuickItem *item = quickWidget->rootObject();
    //quickWidget->rootContext()->setContextProperty("translator", Translator::getInstance());//如果放在這裡程式也能執行,但是會報錯

    //...
}

2.注意是每個需要翻譯的頁面都要新增changEvent(QEvent *event)和translateUI()函式處理。

3.每次改動文字後,需要重新生成ts和qm檔案。

原始碼下載: