Evgenij LegotskojJune 5, 2016, 12:43 p.m.

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

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

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate
DCh

Всё отлично :)
Только у меня вопрос: а как вместо 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")
        }
  • #
  • July 15, 2019, 5:32 a.m.

В Qt 5.10 была добавлена новая функция по переводу qml файлов. Теперь не нужно писать класс оболочку, достаточно вызвать функцию engine.retranslate(); и все обновится само.

Это хорошая новость!!!!

Comments

Only authorized users can post comments.
Please, Log in or Sign up
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Donate

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways

PayPalYandex.Money
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting
S
  • Sergej
  • July 10, 2020, 3:15 p.m.

Qt - Test 001. Signals and slots

  • Result:68points,
  • Rating points-1
S
  • Sergej
  • July 10, 2020, 3:10 p.m.

C++ - Test 001. The first program and data types

  • Result:80points,
  • Rating points4
S
  • Sergej
  • July 10, 2020, 3:06 p.m.

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

  • Result:78points,
  • Rating points2
Last comments
V

Django - Tutorial 027. Implementation Google reCAPTCHA

Спасибо. Только использую декоратор не в urls.py а перед views
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Вы меня не совсем правильно поняли, но все равно спасибо, принял все к сведению. Все сделал как вы сказали, все отлично работает, еще раз огромнейшее спасибо) Разве что только что были опять про…

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Стоило перед использованием что ли инструкцию прочитать https://www.cyberforum.ru/blogs/131347/blog2457.html "После сборки при запуске требовались dll," Ясное дело стоило задепло…
R
R

Qt WinAPI - Lesson 001. How to collect all DLL, which used in Qt project?

Да, собралось. После сборки при запуске требовались dll, перекинул всю папки bin, plugins(не знаю как можно было сделать более умно). Как я понял в первой строке путь к екзешнику вставляю, втор…
Now discuss on the forum

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …
o

Нужен человек кто хорошо понимает паттерны и их использование

Добрый день. Если вопрос про паттерны, то рисуй диаграмму классов.

Сборка Qt / C++ проекта под windows и linux

Отбой. Забыл в исходнике обернуть каждый #include макросом. #ifdef Q_OS_WIN32#include "win_controller.h"#else#include "linux_controller.h"#endif
C

Счечик производительности сети

Здравствуйте! Я решил проблему используя QtNetworkMonitor пример с GitHub . Вопрос закрыт.

Вопрос по указателям в с++

Как то это все усложняет. Еще вероятно работает так: void v(xxx *x3){ x2=x3;}
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB