Monthly Archives: April 2016

Translating the TextEditor

The QtCreator and QtSDK make it pretty easy to localize your application. Here is a short description of how to translate the TextEditor app to different languages.

Marking strings to be translated

The first step in the translation process is to mark the text strings that we want to translate in our source code. In the QML files you just need to pass the text strings to the qsTr function as shown in the following example.

    QueryDialog {
        id: dialog
        message: qsTr("Save before exiting?")
        acceptButtonText: qsTr("Yes")
        rejectButtonText: qsTr("No")
        onAccepted: {
            appIsClosing = true
            saveBeforeClosed(editPage.content)
        }
        onRejected: {
            appToBeClosed()
        }
    }

If the text string is a sentence that contains some variable part (e.g. a file name) you need to use the .arg method of the translated string object. Here is an example with one argument:

myLoader.item.title = qsTr("%1 already exists.").arg(fileName)

In the C++ code we must use the tr() function to translate the text strings. One special case in the C++ side is a static const string that is defined outside of any context. In the texteditor.cpp there is one const string like this (defining the default file name for new files):

const char *TextEditor::UNTITLED = QT_TRANSLATE_NOOP("TextEditor","Untitled");

In this case we must use the QT_TRANSLATE_NOOP macro to pass in the context (“TextEditor”).

Collecting the strings for translation

After we  have marked all the translatable strings in the QML and C++ files we need to collect the strings for the translation stage. This is done with the lupdate tool. First open the QtSDK command prompt from the Windows start menu.

TextEditor-QtSDK-Cmd

Go to the project folder and create a sub-folder called i18n in the qml\texteditor folder. Go to the qml\texteditor folder in the command window and run the lupdate command:

lupdate -recursive ../.. -ts i18n\tr_en.ts

The lupdate command will go through all the source files starting from the project main folder (../..). It will collect all the strings that we marked previously and create a British English translation file (tr_en.ts) into the i18n folder.

The tr_en.ts is an XML formatted file that you can inspect in the QtCreator editor:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="en_US">
<context>
    <name>BrowseMenu</name>
    <message>
        <location filename="../BrowseMenu.qml" line="7"/>
        <source>Cancel</source>
        <translation type="unfinished"></translation>
    </message>
</context>
<context>
    <name>BrowsePage</name>
    <message>
        <location filename="../BrowsePage.qml" line="55"/>
        <source>Save as</source>
        <translation type="unfinished"></translation>
    </message>
...

For each translatable text string the file shows the string location (filename and line number). The <source> tag shows the string to be translated. After the translation each new language will have a separate file (e.g. tr_de.ts for the german translation) where the translated text strings will be stored. The translated string will be marked with the <translation> tag.

<?xml version="1.0" ?><!DOCTYPE TS><TS language="de" version="2.0">
<context>
    <name>BrowseMenu</name>
    <message>
        <location filename="../BrowseMenu.qml" line="7"/>
        <source>Cancel</source>
        <translation>Abbrechen</translation>
    </message>
</context>
<context>
    <name>BrowsePage</name>
    <message>
        <location filename="../BrowsePage.qml" line="50"/>
        <source>Save as</source>
        <translation>Speichern unter</translation>
    </message>
...

Translating with the Qt Linguist tool

The Qt Linguist tool should be available as part of the QtSDK package. It provides a nice graphical interface for translating the application text strings. Let’s assume we can translate from english to the german language. Start Qt Linguist from the windows Start menu and load the tr_en.ts file.

First select Edit>Translation File Settings… and set the target language to German, Then save the file (File>Save As…) to i18n/tr_de.ts.

TextEditor-QtSDK-Linguist-01

We are ready to start. The context pane on the left hand side shows all the files that the lupdate command found containing translatable strings. The numbers following the file name show the number of translated strings and the number of strings available for translation in that particular file. On the right hand side is the source code with the current source string highlighted. Below the source code is the translation pane where we can enter the translation. We can then click the green check mark in the tool bar to accept the translated source text and to move on to the next string.

Creating the runtime translation files

When the translation is ready we can create the runtime translation file to be used in the application. This is done with the lrelease command. Start the QtSDK command prompt and go to the qml/texteditor folder where we created the i18n subfolder and run the lrelease command:

lrelease i18n/*.ts

For each source file (*.ts) a runtime file (*.qm) will be created.

Taking the translations into use

To use the translations in the application we will need to create a resource file (let’s call it translations.qrc) and load all the .qm files from the i18n folder to the resource. Add an alias for each .qm file (e.g. tr_de for qml/texteditor/i18n/tr_de.qm) for easier access from the source code.

Next we will modify the main.cpp file and activate the translations. The QTranslator header is needed. To load the correct language file we will just query the system locale and use the locale string to create the language file name (assuming here that the locale string has been used when naming the translation files). Then we will instantiate the QTranslator class, load the language and install the translator. In case the loading fails (e.g. because we don’t have a translation available) we will fall back to the english version.

#include <QtGui/QApplication>
#include <QtDeclarative/QDeclarativeContext>
#include <QDeclarativeItem>
#include <QTranslator>
#include "qmlapplicationviewer.h"
#include "texteditor.h"

Q_DECL_EXPORT int main(int argc, char *argv[])
{
    QScopedPointer<QApplication> app(createApplication(argc, argv));
    TextEditor *texteditor;

    QmlApplicationViewer viewer;

    QString locale = QLocale::system().name();
    QTranslator translator;

    // fall back to using English translation, if one specific 
    // to the current setting of the device is not available.
    if (!(translator.load("tr_"+locale, ":/")))
        translator.load("tr_en", ":/");

    app->installTranslator(&translator);

You can also test different translations in the simulator simply by loading a specific language file, e.g. to test the german translation:

    translator.load("tr_de", ":/");

TextEditor-UC-20