Qt/QML Sprache zur Laufzeit ändern

mastering qt dynamic language change

Software wird heutzutage meist für den internationalen Gebrauch erstellt. Neben Internationalisierung und Lokalisierung, also dem Auslegen der Software für die Unterstützung mehrerer Sprachen, Kulturen, Gebiete, besteht oftmals auch die Anforderung, die Sprache bzw. besser die Lokalisierung der Applikation zur Laufzeit zu ändern. In diesem Artikel erfahren Sie, wie Sie in Qt/QML die Sprache zur Laufzeit ändern können.

Grundlagen

Internationalisierung und Lokalisierung von Qt/QML Applikationen

Hier die Ultra-Kurzfassung über den Internationalisierungs- und Lokalisierungsworkflow mit dem Qt Framework. Einen umfassenden Artikel zur Internationalisierung und Lokalisierung von Qt/QML Applikationen finden Sie hier.

Um Texte in einer Qt/QML Applikation in mehreren Sprachen anzuzeigen, werden diese im Source Code mit einer Methode gewrapped. In den meisten Fällen wird hierzu die Methode qsTr() verwendet, die als Argument den Text in der Basissprache erwartet.

Text {
    text: qsTr("Order");
}

Anhand dieser Funktion erkennt das im Qt Framework vorhandene Tool lupdate zu übersetzenden Stellen und extrahiert diese in eine Übersetzungsdatei. In diese Übersetzungsdatei (*.ts) fügt der Übersetzer die Zielsprachen ein. Anschließend wird die um die Zielsprachen ergänzte *.ts Datei mit dem Tool lrelease in eine *.qm Datei compiliert. Die *.qm Dateien werden auch als Lokalisierungsdatei bezeichnet. Für jede Zielsprache wird eine separate Datei generiert. Zur Laufzeit liefert die qsTr() Methode dann den Text in der eingestellten Zielsprache zurück. Mehr dazu weiter unten im Artikel.

Einbinden von Übersetzungen

Damit qsTr() den zum eingestellten Gebietsschema (engl. Locale) passenden Text anzeigen kann, greift die Methode auf die QTranslator Klasse zu. QTranslator stellt im Wesentlichen Methoden zum Zugriff auf eine Lokalisierungsdatei (*.qm) zur Verfügung.

QTranslator Objekte werden der Applikation (QCoreApplication) über die installTranslator() Methode bekannt gemacht. Generell können einer Applikation über diesen Weg mehrere Translators übergeben werden, wobei Qt in umgekehrter Intsallationsreiehenfolge nach einer passenden Übersetzung sucht.

Bei jeder Änderung an den installierten Translators wird ein LanguageChange Event generiert.

Dynamische Sprachumschaltung in QML

Vor der Version 5.10

Bis zur Qt Version 5.10 war die Änderung der Sprache zur Laufzeit in QML nur mit einem Workaround möglich. Die Ursache dafür ist, dass die qsTr() Methode nicht auf das LanguageChanged Event der QCoreApplication reagiert hat.

Ein gängiger Workaround für diese Problem sieht folgendermaßen aus.

Text {
   text: qsTr("Hi World!") + context.emptyDummyString
}

Jeder zu internationalisierende Text, hier qsTr(“Hi World!”), wird mit einem globalen QML Property (emptyDummyString im obigen Beispiel) verkettet, das einen leeren String zurück liefert. Das Notify Signal dieses Properties wird dann entweder manuell beim Umschalten der Sprache oder in einem Event Handler auf das LanguageChanged Event der QCoreApplication emittiert. Die Implementierung des “Dummy” Properties erfolgt üblicherweise im C++ Raum und wird als Context Property (context im obigen Beispiel) nach QML exportiert. Durch das Emittieren des Notify Signals des emptyDummyString Properties, wird der komplette Ausdruck des Bindings inklusive des qsTr() Teils neu evaluiert und somit auch neu übersetzt.

Ein Beispiel für die prinzipielle Implementierung dieses Workarounds ist hier zu finden.

Ab der Version 5.10

Ab der Version 5.10 stellt das Qt Framework nun eine bessere Lösung für dieses Problem zur Verfügung. Die Methode QQmlEngine::retranslate(). In der aktuellen Version 5.14, evaluiert diese Methode alle QML Bindings erneut. Dies führt dazu, dass auch alle über die qsTr() Funktion übersetzten Strings aktualisiert werden. Es ist geplant, dass in einer späteren Qt Version nur noch die Bindings mit einem Aufruf von qsTr() neu evaluiert werden. QQmlEngine::retranslate() macht den in Version 5.10 nötigen Workaround somit überflüssig. Der Quelltext verkürzt sich somit zu dem einfachen Ausdruck:

Text {
   text: qsTr("Hi World!")
}

Die C++ Funktion zur Umschaltung der Sprache bzw. allgemein der Lokalisierung (engl. Locale) während der Laufzeit sieht folgendermaßen aus (ohne Error Handling).

void Application::switchLocale(const QString &locale)
{
    if (!mTranslator->isEmpty())
        QCoreApplication::removeTranslator(mTranslator);

    mTranslator->load(QStringLiteral(":/translations/") + locale);
    QCoreApplication::installTranslator(mTranslator);

    mQmlEngine->retranslate();
}

Ist bereits ein Translator installiert, wird dieser deinstalliert. Dann lädt der Translator eine neue Lokalisierungsdatei. Danach wird der Translator installiert. Im letzten Schritt wird mQmlEngine->retranslate() aufgerufen, so dass alle Property Bindings mit qsTr() erneut ausgewertet werden. Dieses neue Feature erhöht die Robustheit des Codes und führt zu einfacherem QML Code.

Hier ist das komplette Beispiel auf Github.


Über den Autor

Dominik Prause

Dominik ist passionierter Designer und Ingenieur und sucht ständig nach besseren Lösungen für die Kunden von Inspirent. Er hat langjährige Erfahrung im Design und der Realisierung von erfolgreichen High Tech Geräten für Industrie, Forschung und Entwicklung.

One thought on “Qt/QML Sprache zur Laufzeit ändern

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.