Qt、QML动态语言切换功能的实现

        本例介绍了qt、qml混合编程的多语言翻译,工程目录及执行效果如下图:

Qt、QML动态语言切换功能的实现

一、生成资源文件

1.在pro中ti添加需要多语言翻译所需要的文件,这样编译工程时会自动生成这两个ts文件。

TRANSLATIONS = language_zh_cn.ts \
               language_en_us.ts

2.使用Qt Creator自带的工具生成ts文件

Qt、QML动态语言切换功能的实现

3.打开Qt Linguist工具(该工具在装Qt Creator一般默认是安装的),分别打开两个文件,进行翻译,保存(英文也可以不翻译)。

Qt、QML动态语言切换功能的实现

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以及混合编程的知识参考:

https://blog.csdn.net/ieearth/article/details/42243553

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文件。

源码下载:https://download.csdn.net/download/zzwdkxx/10703708