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

Virtual hosting with 10 percent discount
Virtual hosting with 10 percent discount
EVILEG offers reliable hosting with a 10% discount for virtual hosting and 5% for VPS
ДЧ

Всё отлично :) Только у меня вопрос: а как вместо ru_RU и en_US написать в ComboBox'e Russian и English чтобы сохранить функцию смены языка :)

UPD Разобрался В comboBox model я пишу так:

model: ["English", "Russian"]

И перед отправкой кода ru_RU или en_US в С++ делаю проверку

onCurrentTextChanged: {
            if(comboBox.currentText === "Russian")
                qmlTranslator.setTranslation("ru_RU")
            if(comboBox.currentText === "English")
                qmlTranslator.setTranslation("en_US")
        }

Comments

Only authorized users can post comments.
Please, Log in or Sign up
МБ
April 21, 2019, 9:40 a.m.
Моисей Бушуев

Qt - Test 001. Signals and slots

  • Result:0points,
  • Rating points-10
AA
April 17, 2019, 7:40 p.m.
Anton Ablin

Qt - Test 001. Signals and slots

  • Result:73points,
  • Rating points1
E
April 17, 2019, 6:16 p.m.
Evgeny

Qt - Test 001. Signals and slots

  • Result:100points,
  • Rating points10
Last comments
April 21, 2019, 4:22 p.m.
Евгений Легоцкой

Через метод setIcon table.horizontalHeaderItem(0).setIcon("qrc://path/to/icon.png")
April 21, 2019, 3:48 p.m.
Евгений Легоцкой

Добрый день! Спасибо за комментарий. Там действительно лучше будет сделать с инициализацией по умолчанию.
U
April 18, 2019, 3:37 p.m.
Unreal_man

А как иконку в хедер задать?
u
April 18, 2019, 2:15 a.m.
uaa

доброго времени,большое спасибо за пример для начинающего)при адаптации к своему проекту столкнулся с таким ньансом:в vepolyline.h в 47 строке нужна инициализация по умолчанию: int m_pointF...
E
April 11, 2019, 12:49 p.m.
Evgeny

Спасибо за ответ) У меня компоновщик на нее ругался просто. Оказалось, просто забыл Q_OBJECT в начале класса указать.
Now discuss on the forum
April 21, 2019, 4:16 p.m.
Евгений Легоцкой

Приветствую Нужно сохранять где-то выбранное значение, а потом восстанавливать его. Или использовать QSettings или добавить метод open(), в который передавать начальные значения для того...
R
April 19, 2019, 9:55 a.m.
RED_Spider

мені важко це зараз навіть перевірити, тому що знайшов коміт, це ще було в 2016 році, і цей код не буде працювати коректно зараз, єдине скажу що це були QThread
i
April 17, 2019, 3:03 p.m.
ilya.guzikov

BlinCT, на стороне ++ это делать необходимо так как в qml при использовании функции append происходит перерисовка всех точек лини(как я понимаю) и из-за этого при использовании больших массиво...
April 10, 2019, 11:20 a.m.
Алексей Внуков

может тоже кому надо будет - QML не принимает QVector<QVector<int>> , при попытке вывести полученый вектор QML показывает что это QVariant(QVector<QVector<int> ...
Join us in social networks

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