Privacy policyContactsAbout siteOpinionsGitHubDonate
© EVILEG 2015-2018
Recommend hosting
TIMEWEB

QML - Lesson 025. Dynamic translation of multilanguage application on QML

Qt, QML, перевод, QTranslator, translation

Once we have learn how to make the translation of the application interface at Qt/C++ , it is time to research possibilities of dynamic translation application interface which is written in QML.

In developing the QML to have a couple of moments that need to be taken into account, as opposed to the standard application on QWidgets, namely:

  1. Requires additional configuration .pro file;
  2. Process of the loading of translation for your language is carried in C ++ layer;
  3. Reinitialize the translation interface implemented in QML layer using qsTr() function;
  4. After loading the translation, you need to send a signal from the C ++ layer in QML layer to re-translate the application interface.

Project Structure

Create a project, which will include the following files:

  • QmlLanguage.pro - profile of project;
  • deployment.pri - configuration file of deployment, created by default;
  • main.cpp - source file of file with main function;
  • qmltranslator.h - header file of class for translation loading;
  • qmltranslator.cpp - sourcefile of class for translation loading;
  • main.qml - main file of QML layer.

QmlLanguage.pro

Creating a translation file will be similar to how it is done when creating a translation for Qt / C ++ applications. That is, you need to connect the translation file. We will work with this file useing Qt Linguist:

# Add the translation file
# Which is in fact the file "source code" for our translation
TRANSLATIONS += QmlLanguage_ru.ts

Then run the utility lupdate, to create the translation file, edit it in the Qt Linguist, and launch lrelease create a binary translation file, which will be connected to the application.

Read more about this in a previous article on the use of QTranslator .

The most important thing to work with translations in QML is what you need to connect all the QML file as the source, as ordinary C ++ files. But with a mark that only use lupdate_only.

lupdate_only {
    SOURCES += main.qml
}

Below is the complete listing of the project .pro file.

TEMPLATE = app

QT += qml quick widgets

CONFIG += c++11

SOURCES += main.cpp \
    qmltranslator.cpp

# To create a translation file with strings of resources qml<br># need to include qml file as normal source in the .pro file<br># But only for use lupdate utility, so that she could learn,<br># Which strings need to be translated
lupdate_only {
    SOURCES += main.qml
}

RESOURCES += qml.qrc \
    translations.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Default rules for deployment.
include(deployment.pri)

# Add the translation file
# Which is in fact the file "source code" for our translation
TRANSLATIONS += QmlLanguage_ru.ts

HEADERS += \
    qmltranslator.h

main.cpp

Because of connection of the translation file is carried in C ++ layer, you will need to register the class object in QML context. In this case, we will write QmlTranslator class that is a wrapper over QTranslator, because the class has no methods with which we could work through QML.

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "qmltranslator.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // Create an object to work with translations ...
    QmlTranslator qmlTranslator;

    QQmlApplicationEngine engine;
    // and register it as a context in Qml layer
    engine.rootContext()->setContextProperty("qmlTranslator", &qmlTranslator);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

qmltranslator.h

In the class there is  method for the translation loading, in which we will pass the target language prefix. And from this method will emit a signal of the translation change to be able to re-translate the interface with a new translation.

Translation installation method you have to mark macro Q_INVOKABLE, to be able to use it in QML layer.

#ifndef QMLTRANSLATOR_H
#define QMLTRANSLATOR_H

#include <QObject>
#include <QTranslator>

class QmlTranslator : public QObject
{
    Q_OBJECT

public:
    explicit QmlTranslator(QObject *parent = 0);

signals:
    // The signal of change the current language to change the interface translation
    void languageChanged();

public:
    // Translation installation method, which will be available in QML
    Q_INVOKABLE void setTranslation(QString translation);

private:
    QTranslator m_translator;
};

#endif // QMLTRANSLATOR_H

qmltranslator.cpp

#include "qmltranslator.h"
#include <QApplication>

QmlTranslator::QmlTranslator(QObject *parent) : QObject(parent)
{

}

void QmlTranslator::setTranslation(QString translation)
{
    m_translator.load(":/QmlLanguage_" + translation, "."); // load translation
    qApp->installTranslator(&m_translator);                 // Set it to the application
    emit languageChanged();                                 // Signaling a change in the current translation
}

main.qml

Application interface will appear as follows:

The application logic is as follows: when you change the language in the combo box will change the language of the application.

Since we registered qmlTranslator in the context of QML layer, the change in the output text in the combo box will cause a change of language in the object method qmlTranslator. And in order to keep track of changes in the language signal, you must use type Connections to connect to this signal and write a handler which will be called retranslateUi(). The function retranslateUi() rendered all the text properties of all the objects that need to be subjected to transfer. This is to simplify the logic and reduce redundancy.

import QtQuick 2.6
import QtQuick.Controls 1.5

ApplicationWindow {
    id: applicationWindow
    visible: true
    width: 640
    height: 480

    Label {
        id: helloLabel
        height: 50
        anchors {
            top: parent.top
            left: parent.left
            right: parent.horizontalCenter
            margins: 10
        }
    }

    ComboBox {
        id: comboBox
        anchors {
            top: parent.top
            left: parent.horizontalCenter
            right: parent.right
            margins: 10
        }

        model: ["ru_RU", "en_US"]

        // If you change the text, initialize the translation unit via C++ Layer
        onCurrentTextChanged: {
            qmlTranslator.setTranslation(comboBox.currentText)
        }
    }

    Label {
        id: labelText
        wrapMode: Text.Wrap
        anchors {
            top: helloLabel.bottom
            left: parent.left
            right: parent.right
            margins: 10
        }
    }

    // Connect to an interpreter object
    Connections {
        target: qmlTranslator   // was registered in main.cpp
        onLanguageChanged: {    // upon receipt of the signal to change the language
            retranslateUi()     // initialize interface translation
        }
    }

    // interface translation function
    function retranslateUi() {
        applicationWindow.title = qsTr("Hello World")
        helloLabel.text = qsTr("Hello World")
        labelText.text = qsTr("The QTranslator class provides internationalization" +
                              "support for text output.An object of this class contains " +
                              "a set of translations from a source language to a target language. " +
                              "QTranslator provides functions to look up translations in a translation file. " +
                              "Translation files are created using Qt Linguist.")
    }
    
    // Start translating the application window when the application was created
    Component.onCompleted: {
        retranslateUi();
    }
}

Result

In general, the dynamic translation application on Qt/QML is not much different from the translation application using only Qt/C ++. The key point is that you need to properly connect the signals and slots, and the right to call methods for the transfer initialization.

Download QML application with dynamic translation

Video

Comments

Only authorized users can post comments.
Please, Log in or Sign up
МК
Jan. 13, 2019, 8:35 p.m.
Мария Канева

C++ - Test 005. Structures and Classes

  • Result:91points,
  • Rating points8
МК
Jan. 13, 2019, 8:32 p.m.
Мария Канева

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:70points,
  • Rating points1
МК
Jan. 13, 2019, 8:28 p.m.
Мария Канева

C++ - Тест 003. Условия и циклы

  • Result:78points,
  • Rating points2
Last comments
I
Jan. 16, 2019, 8:06 a.m.
IscanderChe

Заработало. Забыл model->select(); вписать.
I
Jan. 16, 2019, 8:02 a.m.
IscanderChe

Всё равно пусто, хотя строка с данными в базу добавляется.
Jan. 16, 2019, 7:51 a.m.
Евгений Легоцкой

потому, что нужно сохранять информацию для всех остальных ролей и столбцов через вызов переопределённого метода. Да к тому же вы ещё и зациклили вызов метода data. QVariant MySqlTableModel:...
I
Jan. 16, 2019, 7:43 a.m.
IscanderChe

Сделал вот так. В tableView ничего нет, кроме заголовка. QVariant MySqlTableModel::data(const QModelIndex &index, int role) const{ if (role == Qt::DisplayRole) { QTime ...
Now discuss on the forum
Jan. 15, 2019, 4:53 p.m.
Михаиллл

Спасибо, заработало.Но выдало обычный текст без форатирования HTML.Придется искать дальше
Jan. 15, 2019, 12:52 p.m.
BlinCT

Я же вам выше написал CLion умеет работать с ремоут машинами. И Qt так же собирает.
ПБ
Jan. 14, 2019, 2:27 p.m.
Павел Богдевич

Да
m
Jan. 13, 2019, 4:52 p.m.
mihamuz

И так может кому будет интересно решил свою проблему следующим путем.Через дизайнер в базовый виджет добавил QQuickWidget (назвал его listProducts)Это соответственно убрал. this->m_qu...
Join us in social networks

For registered users on the site there is a minimum amount of advertising