Qt Weekly #2: Localizing Qt Quick Apps

Published Wednesday March 19th, 2014 | by

Most people feel more comfortable using applications in their native language. To attract as many users as possible for your apps, you should localize the apps to the languages spoken by the users in the regions that you target. Qt makes this easy by providing tools for localizing C++ and Qt Quick apps into local languages.

Let’s use the Quick Forecast app to illustrate the steps in localizing apps.

Quick Forecast app in English

Quick Forecast app in English

If you want to try running Quick Forecast yourself:

  

The steps to localize apps include creating translatable apps, preparing them for translation, using Qt Linguist to translate the apps, and creating run-time translation files for use by the released app.  This blog post covers the basics, whereas the Qt Linguist Manual describes the translation process and all the options you have in detail.

Creating Translatable Apps

To make an app translatable, you must make some changes in the project file, source files, and the main.cpp file. In the project file, you must list the files that contain translatable strings and list the languages that they will be translated to. In the source files, you add commands to mark strings translatable and comments to help the translators understand how the strings are used in the UI. In the main.ccp file, you add code to instruct the application to load the translated strings.

Specifying Translation Source Files

The lupdate tool extracts user interface strings from your application sources. It reads the Quick Forecast project configuration file, weatherapp.pro, to identify which source files contain text to be translated. This means your source files must be listed in the SOURCES or HEADERS entry in the .pro file. If your files are not listed, the text in them will not be found.

However, the SOURCES variable is intended for C++ source files. If you list QML or JavaScript source files there, the compiler tries to build them as though they were C++ files. As a workaround, you can use a conditional statement so the lupdate tool sees the .qml files but the C++ compiler ignores them. You can use wildcards to specify the files:

lupdate_only {
    SOURCES +=  $$PWD/qml/*.qml \
    $$PWD/qml/pages/*.qml \
    $$PWD/qml/models/*.qml \
    $$PWD/qml/touch/*.qml
}

The options you have are described in Qt Linguist Manual: Developers.

Adding Target Languages

To tell lupdate which translation files to create and update, add the target languages to weatherapp.pro. The following code creates translation source files for German and French:

TRANSLATIONS +=  QuickForecast_de.ts \
                 QuickForecast_fr.ts

To add other languages, use the ISO 639-1 language codes. For more information about the supported languages and writing systems, see Internationalization with Qt.

Marking Strings Translatable

For lupdate to find the strings, you need to mark all the text strings that are visible to users translatable in the source files. For QML, you use the qsTr() function, as follows:

BasicPage {
    id: page1
    title1: qsTr("Cities")

For C++, you use the tr() function.

All the options you have are described in Internationalization and Localization with Qt Quick.

Adding Context

To make the translators’ job easier, you should identify the context in which the phrases appear. The translators will see the following comments in Qt Linguist:

BasicPage {
    id: page1
    //: The label of the search field for finding cities
    title1: qsTr("Cities")

Making the App Aware of the Translations

To enable the application to load the translation files according to the current locale at runtime, add the following code to the main() function in the main.cpp:

    QTranslator qtTranslator;
    qtTranslator.load("QuickForecast_" + QLocale::system().name(), ":/translations/");
    app.installTranslator(&qtTranslator);

First, a QTranslator object is created. Then, a translation is loaded according to the current locale at runtime. Finally, the translator object is installed into the application. The above code assumes that you store the translations in ressources, in a subdirectory/alias called translations.

For more information, see Internationalization with Qt.

Generating Translation Source Files

You must now put on the hat of a release manager and run the lupdate tool to generate the first set of translation source (TS) files with all the user-visible text but no translations. Switch to the folder that contains the project files and run lupdate. You need to specify the full path to the lupdate tool in the bin directory in the Qt 5 installation directory as a part of the command. For example, on Mac OS X, you might enter the following command:

~/Qt5/5.2.1/clang_64/bin/lupdate weatherapp.pro

Using lupdate is described in detail in Qt Linguist Manual: Release Manager.

Usually, you would now deliver the TS files to translators for translating the user visible strings. As you are playing all the roles this time, it is the time to change hats again.

Translating Apps

Start Qt Linguist (located in the bin directory in the Qt installation directory) and select File > Open to open the TS file to translate. We will use QuickForecast_de.ts as an example.

Qt Linguist displays the translatable strings in the application.

German TS file opened in Qt Linguist

German TS file opened in Qt Linguist

Enter a translation in the German translation field.

Adding a translation

Adding a translation

When you are happy with the translation, click the check mark button to accept the translation and move to the next string.

The final translations are released as Qt message (QM) files. When you have translated and accepted all the strings, select File > Release to create a QM file with the same base name as the current translation source file. The release manager’s command line tool, lrelease, performs the same function on all of an application’s translation source files. Note that only accepted translations are included in the QM file.

Translating with Qt Linguist is described in detail in Qt Linguist Manual: Translators.

Embedding QM Files in App Resources

You still need to embed the QM files in the app resources. The simplest way to do so is to create a resource file called translations.qrc that lists the QM files:

<RCC>
    <qresource prefix="/">
        <file>translations/QuickForecast_de.qm</file>
        <file>translations/QuickForecast_fr.qm</file>
    </qresource>
</RCC>

Note that Qt Linguist lrelease tool creates by default the QM files in the project directory and you must move them to the translations directory for the example code to work.

For an example of using Qt Creator to create resource files, see Creating a Qt Widget Based Application.

You must also add translations.qrc as a value of the RESOURCES variable in weatherapp.pro:

RESOURCES += \
    weatherapp.qrc \
    translations.qrc

There are some ways in which you can automate the generation of QM files and embedding them in the application resources. We use one such method in the Quick Forecast source files, which are available from: https://qt.gitorious.org/qt-labs/weather-app. The method is described on the Automating Generation of QM Files wiki page.

Building and Running the App

You can now test the translations by building the app and running it on a German speaking mobile device:

Quick Forecast in German

Quick Forecast in German

You can use Qt Creator to easily build apps and run them on desktops and mobile devices.

Qt Weekly is a new blog post series that aims to give your daily Qt usage a boost. Stay tuned for next week’s post!

 

 

Did you like this? Share it:

Posted in C++, Qt | Tags:

11 comments to Qt Weekly #2: Localizing Qt Quick Apps

Great Qt Weekly post!
We also have written a tutorial how to use multi-languages in Qt apps, you can find it here: http://v-play.net/doc/howto-multi-language/

It contains the addition to change languages at runtime, and a few more screenshots. Looking forward to the next Weekly posts – the last one on logging was also very good! :)

Leena Miettinen says:

Thanks, Christian!

And thanks for the link! It is always interesting to see real-life examples of using the Qt tools.

Cyttorak says:

Just a question about Qt Quick controls: are they getting native look&feel in iOS and Android? Any ETA? Thanks in advance :)

Jens Bache-Wiig says:

The ETA for Android styled controls is 5.4. We don’t really have a set date for IOS yet.

Cyttorak says:

Thanks Jens ;)

Mike Trahearn says:

I’d like to see more dynamic support for QML translations rather than the long standing extra binding workaround for example if the qsTr function was a bit more like a property binding behind the scenes and would update itself automatically if the language changed.

Ed says:

This app actually makes a really nice *complete* tutorial for an Android app with Qt/QML.

However I see some problems with it inside QtCreator.

The first is a warning to add a “@uri” annotation to main.cpp to fix an error on “import org.qtproject.demo.weather 1.0″. This is fine, I add the annotation and the import error highlight goes away.

However, all of the types like CitiesPage, LongTermPage and so on are highlighted in QtCreator as errors, i.e. “Unknown Component”.

How do you make QtCreator recognise all those new types?

Leena Miettinen says:

Thanks, Ed!

The following line needed to be added to the main.cpp file before the custom QML types, so that org.qtproject.demo.weather gets recognized when loaded in Qt Creator:

// @uri org.qtproject.demo.weather

I added the line to the Quick Forecast source files in change: https://codereview.qt-project.org/81585

Ed says:

Thanks for the reply, Leena.

I had already added that line myself, it fixes the QtCreator error on the import statement.

But even with that line added, QtCreator shows error indicators, e.g. in main.qml, for CitiesPage, LongTermPage, OneDayPage and TouchLabel.

This example app was really very useful to me as a Qt beginner, but it would be nice if it worked 100% in QtCreator.

Leena Miettinen says:

Maybe it is the place where you add the line, because when I add it just before the custom QML types (as shown in the patch), it removes the error indicators for the page types.

However, the TouchLabel is a little bit different case. The devs here are trying to come up with a fix for it. The problem for us is that QML allows you to do almost anything and it is hard for tooling to support all the edge cases.

Keep bringing them up, though, and write bug reports and we’ll try to fix things where we can.

Commenting closed.