Nachdem wir uns mit Übersetzungen der Anwendungsschnittstelle zu Qt/C++ vertraut gemacht haben, ist es an der Zeit, die Möglichkeiten der dynamischen Übersetzung einer Anwendung zu erkunden, deren Schnittstelle geschrieben ist in * QML. *
Bei der Entwicklung auf QML sind im Gegensatz zu einer Standardanwendung auf QWidgets einige Dinge zu beachten, nämlich:
- Eine zusätzliche Konfiguration der .pro-Projektdatei ist erforderlich;
- Der Prozess des Ladens von Übersetzungen für die gewünschte Sprache wird in der C++-Schicht durchgeführt;
- Die Schnittstellenübersetzung wird in der QML -Schicht mit der Funktion qsTr(); neu initialisiert
- Nach dem Laden der Übersetzung müssen Sie ein Signal von der C++-Schicht an die QML -Schicht senden, um die Anwendungsschnittstelle erneut zu übersetzen, was für die C++-Anwendung ähnlich ist, aber die Einrichtung der Interaktion von C++ erfordert Ebene mit der Ebene QML .
Projektstruktur
Erstellen Sie ein Projekt, das die folgenden Dateien enthält:
- QmlLanguage.pro - Projektprofil;
- deployment.pri - Bereitstellungseinstellungsdatei, standardmäßig erstellt;
- main.cpp - Quellcodedatei mit main-Funktion;
- qmltranslator.h - Header-Datei der Übersetzungsladeklasse;
- qmltranslator.cpp - Quellcodedatei der Übersetzungsladeklasse;
- main.qml - QML -Hauptdatei der Ebene.
QmlLanguage.pro
Das Erstellen einer Übersetzungsdatei ähnelt dem Erstellen von Übersetzungen für eine Qt/C++-Anwendung. Das heißt, Sie müssen eine Übersetzungsdatei einfügen, mit der Qt Linguist arbeitet:
# Добавляем файл переводов, # который является по сути файлом "исходных кодов" для нашего перевода TRANSLATIONS += QmlLanguage_ru.ts
Als Nächstes führen wir das Dienstprogramm lupdate aus, um diese Übersetzungsdatei zu erstellen, bearbeiten sie in Qt Linguist und führen das Dienstprogramm lrelease aus, um eine binäre Übersetzungsdatei zu erstellen, die in die Anwendung aufgenommen wird.
Sie können mehr darüber im vorherigen Artikel über die Verwendung von QTranslator lesen.
Der wichtigste Punkt für die Arbeit mit Übersetzungen in QML ist, dass Sie alle QML-Dateien als Quellen einschließen müssen, genau wie normale C++-Dateien. Aber mit einer Markierung, die nur für die Verwendung lupdate_only.
lupdate_only { SOURCES += main.qml }
Nachfolgend finden Sie die vollständige Auflistung der .pro-Datei des Projekts.
TEMPLATE = app QT += qml quick widgets CONFIG += c++11 SOURCES += main.cpp \ qmltranslator.cpp # Для того, чтобы создать файл переводов со строками из ресурсов qml # понадобится включить файл qml в качестве обычных исходников в pro файле # но только для использования утилиты lupdate, чтобы она могла узнать, # какие строки нуждаются в переводе 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) # Добавляем файл переводов, # который является по сути файлом "исходных кодов" для нашего перевода TRANSLATIONS += QmlLanguage_ru.ts HEADERS += \ qmltranslator.h
main.cpp
Da Übersetzungsdateien in der C++-Schicht enthalten sind, müssen Sie ein Übersetzungsklassenobjekt im QML-Kontext registrieren. In diesem Fall schreiben wir die QmlTranslator -Klasse, die ein Wrapper für QTranslator ist , da diese Klasse keine Methoden hat, mit denen wir durch QML. arbeiten könnten.
#include <QApplication> #include <QQmlApplicationEngine> #include <QtQml> #include "qmltranslator.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); // Создаём объект для работы с переводами ... QmlTranslator qmlTranslator; QQmlApplicationEngine engine; // и регистрируем его в качестве контекста в Qml слое engine.rootContext()->setContextProperty("qmlTranslator", &qmlTranslator); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
qmltranslator.h
Die Klasse hat eine Methode zum Setzen der Übersetzung, der das Präfix der Zielsprache übergeben wird. Und von dieser Methode wird ein Signal zum Ändern der Übersetzung ausgegeben, sodass es möglich ist, die gesamte Schnittstelle mit einer neuen Übersetzung erneut zu übersetzen.
Die Übersetzungsaufbaumethode muss mit dem Makro Q_INVOKABLE, gekennzeichnet werden, damit sie in der QML -Schicht verwendet werden kann.
#ifndef QMLTRANSLATOR_H #define QMLTRANSLATOR_H #include <QObject> #include <QTranslator> class QmlTranslator : public QObject { Q_OBJECT public: explicit QmlTranslator(QObject *parent = 0); signals: // Сигнал об изменении текущего языка для изменения перевода интерфейса void languageChanged(); public: // Метод установки перевода, который будет доступен в 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, "."); // Загружаем перевод qApp->installTranslator(&m_translator); // Устанавливаем его в приложение emit languageChanged(); // Сигнализируем об изменении текущего перевода }
main.qml
Die Anwendungsoberfläche sieht folgendermaßen aus:
Die Anwendungslogik ist wie folgt: Beim Ändern der Sprache in der Combobox ändert sich die Anwendungssprache.
Da wir qmlTranslator im Kontext der QML -Schicht registriert haben, rufen wir im Textänderungshandler in der Combobox die Sprachänderungsmethode im qmlTranslator-Objekt auf. Und um die Sprachänderung zu verfolgen signalisieren, müssen Sie sich mit diesem über das Signal vom Typ Connections verbinden und einen Handler schreiben, in dem die Funktion retranslateUi() aufgerufen wird. Die Funktion retranslateUi() enthält alle Texteigenschaften aller Objekte, die übersetzt werden müssen. Dies wurde getan, um die Logik zu vereinfachen und redundanten Code zu reduzieren.
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"] // При изменении текста, инициализируем установку перевода через С++ слой onCurrentTextChanged: { qmlTranslator.setTranslation(comboBox.currentText) } } Label { id: labelText wrapMode: Text.Wrap anchors { top: helloLabel.bottom left: parent.left right: parent.right margins: 10 } } // Подключаемся к объекту переводчика Connections { target: qmlTranslator // был зарегистрирован в main.cpp onLanguageChanged: { // при получении сигнала изменения языка retranslateUi() // инициализируем перевод интерфейса } } // Функция перевода интерфейса 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.") } // Запускаем перевод приложения, когда окно приложения было создано Component.onCompleted: { retranslateUi(); } }
Insgesamt
Im Allgemeinen unterscheidet sich die dynamische Übersetzung einer Anwendung in Qt/QML nicht wesentlich von der Übersetzung einer Anwendung, die nur Qt/C++ verwendet. Der Schlüssel liegt darin, die Signale und Slots korrekt zu verbinden und die Methoden korrekt aufzurufen, um die Übersetzung zu initialisieren.
QML-Anwendung mit dynamischer Übersetzung herunterladen
Всё отлично :)
Только у меня вопрос: а как вместо ru_RU и en_US написать в ComboBox'e Russian и English чтобы сохранить функцию смены языка :)
UPD Разобрался
В comboBox model я пишу так:
И перед отправкой кода ru_RU или en_US в С++ делаю проверку
В Qt 5.10 была добавлена новая функция по переводу qml файлов. Теперь не нужно писать класс оболочку, достаточно вызвать функцию engine.retranslate(); и все обновится само.
Это хорошая новость!!!!