(→How to) |
(This page hasn't been update since 2010, added a warning box) |
||
| (20 intermediate revisions not shown) | |||
| Line 1: | Line 1: | ||
| - | + | <center> | |
| + | {| style="margin:0.5em; padding:0.5em; background:#FEE; border:1px solid #999;" | ||
| + | |- | ||
| + | | This page seems to be out of date, you might find some more recent information at [[QtInternationalization]] | ||
| + | |}</center> | ||
== Overview == | == Overview == | ||
This tutorial explains how to internationalise a QML application. | This tutorial explains how to internationalise a QML application. | ||
| + | |||
| + | It ''does not'' cover topics like integrating with translation sites (e.g. transifex), how to version control translation files, or automation of the Qt translation tools. In other words, it doesn't provide a build workflow for translations, such as you might want in a real development environment. | ||
<strong> | <strong> | ||
| - | + | If you are translating a Qt application (not a QML UI), you can incorporate many of the translation steps into the <code>.pro</code> project file: see http://doc.qt.nokia.com/4.7/linguist-manager.html. This automates some of the build steps covered below. | |
| - | + | ||
| - | If you are translating a Qt application (not a QML UI), you can incorporate the translation steps into the .pro file: see http://doc.qt.nokia.com/4. | + | |
| - | + | ||
| - | + | ||
| - | + | However, for translation of QML interfaces, I was unable to make QML files part of this type of project automation. There is no mention of how to do this in the page about QML i18n (http://doc.qt.nokia.com/4.7/qdeclarativei18n.html) either. So I've explained the manual process instead. | |
</strong> | </strong> | ||
| Line 21: | Line 23: | ||
=== System Setup === | === System Setup === | ||
| - | + | No special system setup is required. | |
== How to == | == How to == | ||
| Line 29: | Line 31: | ||
<ol> | <ol> | ||
| - | <li>Use a custom Qt app to load your QML, rather than the default <code>qmlviewer</code>: this makes it easier to internationalise the project. I used the [[QML | + | <li>Use a custom Qt app to load your QML, rather than the default <code>qmlviewer</code>: this makes it easier to internationalise the project. I used the [[QML/Creating_a_transparent_window|transparent window application]] as a starting point.<br/> |
If you run a QML application under the default <code>qmlviewer</code>, you'll have to pass a <code>-translation</code> flag to it, telling it which language file to use for string translations.</li> | If you run a QML application under the default <code>qmlviewer</code>, you'll have to pass a <code>-translation</code> flag to it, telling it which language file to use for string translations.</li> | ||
| Line 54: | Line 56: | ||
</pre> | </pre> | ||
| - | The <code>__string__</code> syntax makes it easier to notice whether translations are working when the application runs. In a real application you might want to put the translation strings in as English strings, so at least if any strings aren't translated, or if | + | The <code>__string__</code> syntax makes it easier for me to notice whether translations are working when the application runs (anything with underlines around hasn't been translated). In a real application you might want to put the translation strings in as English strings, so at least if any strings aren't translated, or if the system's locale is not supported, the user will see English. |
</li> | </li> | ||
| - | <li>You need one translation for each language you want to use. It's probably a good idea to include translations for the application's native language to stop yourself being lazy and accidentally leaving English (or whatever your native language) strings in there.<br/> | + | <li>You need one translation for each language you want to use. It's probably a good idea to include translations for the application's native language to stop yourself being lazy and accidentally leaving English (or whatever your native language is) strings in there.<br/> |
To generate these, you need to use the <code>lupdate</code> program first. This creates the <code>.ts</code> files which are used as a basis for creating translations. Run this inside the project directory from the command line: | To generate these, you need to use the <code>lupdate</code> program first. This creates the <code>.ts</code> files which are used as a basis for creating translations. Run this inside the project directory from the command line: | ||
| Line 73: | Line 75: | ||
<li>An (optional) underscore + two letter [http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1_alpha 2] country code (representing the regional variant of the language), e.g. ''_GB'', ''_US'', ''_CA'' (Canada).</li> | <li>An (optional) underscore + two letter [http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 ISO 3166-1_alpha 2] country code (representing the regional variant of the language), e.g. ''_GB'', ''_US'', ''_CA'' (Canada).</li> | ||
</ul> | </ul> | ||
| + | |||
| + | So you can potentially provide: | ||
| + | |||
| + | <ul> | ||
| + | <li>One file for each language code (<code>qml-translations.en.ts</code> for generic English).</li> | ||
| + | <li>One file for each language code/region pair (<code>qml-translations.en_US.ts</code> for American English, <code>qml-translations.en_GB.ts</code> for UK English).</li> | ||
| + | </ul> | ||
| + | |||
| + | In cases where you have both generic translations and region-specific ones, someone from a region you haven't covered (e.g. en_AU, Australian English) will get the generic translations (the en ones). | ||
| + | |||
</li> | </li> | ||
| Line 92: | Line 104: | ||
</li> | </li> | ||
| - | <li> | + | <li>Next we use the <code>.qm</code> files we just created as Qt resources, along with some special directory path syntax, to load them into the translator. (I couldn't get them to load as non-resource files unless I used an absolute file path.) |
<ol> | <ol> | ||
| - | <li>Add a new '''Qt Resource file''' to the project (right-click on the project in Qt Creator, select ''Add New...'').</li> | + | <li>Add a new '''Qt Resource file''' (<code>.qrc</code>) to the project (right-click on the project in Qt Creator, select ''Add New...'').</li> |
| - | <li>Add the <code>.qm</code> files to | + | <li>Add the <code>.qm</code> files to the <code>.qrc</code> file as resources. When the application is built, resources are compiled into the binary so they can be accessed by the application in a platform-agnostic fashion.</li> |
<li>Edit the <code>main.cpp</code> file so it loads the appropriate translation resource (<code>.qm</code>) into the application, based on the locale:<br/> | <li>Edit the <code>main.cpp</code> file so it loads the appropriate translation resource (<code>.qm</code>) into the application, based on the locale:<br/> | ||
<pre> | <pre> | ||
| Line 124: | Line 136: | ||
MainWindow w; | MainWindow w; | ||
| - | |||
w.show(); | w.show(); | ||
| Line 131: | Line 142: | ||
</pre> | </pre> | ||
| - | Note that we could enhance this code to default to English (set locale to <code>en</code>) if a user's language isn't supported. | + | Note that we could enhance this code to default to English (set locale to <code>en</code>) if a user's language isn't supported.<br/> |
| - | See http://doc.qt.nokia.com/4. | + | See http://doc.qt.nokia.com/4.7/linguist-programmers.html, which explains more about integrating translations into a Qt app. |
</li> | </li> | ||
| Line 141: | Line 152: | ||
</pre> | </pre> | ||
| - | NB this uses the <code>meego-sdk-qtapp</code> wrapper script, [[#MeeGo SDK wrapper script|described below]]. | + | NB this uses the <code>meego-sdk-qtapp</code> wrapper script, [[#MeeGo SDK wrapper script|described below]].<br/> |
| - | If your language is set to '''en_GB''' or '''en_US''', you should see the English version; if set to '''fr_FR''' or '''de_AT''', you'll see it in French or German respectively. If you are using another language, you'll see untranslated strings. | + | If your language is set to '''en_GB''' or '''en_US''', you should see the English version; if set to '''fr_FR''' or '''de_AT''', you'll see it in French or German respectively. If you are using another language, you'll see untranslated strings.<br/> |
You can try it in a different language with: | You can try it in a different language with: | ||
| Line 207: | Line 218: | ||
<pre> | <pre> | ||
| - | /opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp lupdate | + | /opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp lupdate <other arguments here> |
</pre> | </pre> | ||
| Line 215: | Line 226: | ||
/opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp ./qml-translator | /opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp ./qml-translator | ||
</pre> | </pre> | ||
| + | |||
| + | [[Category:Localization]] | ||
| + | [[Category:tutorial]] | ||
| + | [[Category:qml]] | ||
| This page seems to be out of date, you might find some more recent information at QtInternationalization |
Contents |
This tutorial explains how to internationalise a QML application.
It does not cover topics like integrating with translation sites (e.g. transifex), how to version control translation files, or automation of the Qt translation tools. In other words, it doesn't provide a build workflow for translations, such as you might want in a real development environment.
If you are translating a Qt application (not a QML UI), you can incorporate many of the translation steps into the .pro project file: see http://doc.qt.nokia.com/4.7/linguist-manager.html. This automates some of the build steps covered below.
However, for translation of QML interfaces, I was unable to make QML files part of this type of project automation. There is no mention of how to do this in the page about QML i18n (http://doc.qt.nokia.com/4.7/qdeclarativei18n.html) either. So I've explained the manual process instead.
Qt Creator (MeeGo 1.1 SDK version) installed. See these instructions.
No special system setup is required.
Follow these steps to internationalise a QML application:
qmlviewer: this makes it easier to internationalise the project. I used the transparent window application as a starting point.qmlviewer, you'll have to pass a -translation flag to it, telling it which language file to use for string translations.qsTr("some string") properties to elements in the QML user interface definition.
The recommendation is that you only use ASCII characters in the strings which occur in the source QML files.
For example:
import Qt 4.7
Rectangle {
width: 320
height: 240
Text {
text: qsTr("__hello__")
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
The __string__ syntax makes it easier for me to notice whether translations are working when the application runs (anything with underlines around hasn't been translated). In a real application you might want to put the translation strings in as English strings, so at least if any strings aren't translated, or if the system's locale is not supported, the user will see English.
lupdate program first. This creates the .ts files which are used as a basis for creating translations. Run this inside the project directory from the command line:
/opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper lupdate *.qml \ -ts qml-translations.en.ts qml-translations.fr.ts qml-translations.de.ts
The scan is recursive by default. It creates the .ts files you specified, with "unfinished" entries for each translatable string in your app's QML files. If you want more languages to be supported, add more .ts file names to the command line.
The language codes are constructed from:
So you can potentially provide:
qml-translations.en.ts for generic English).qml-translations.en_US.ts for American English, qml-translations.en_GB.ts for UK English).In cases where you have both generic translations and region-specific ones, someone from a region you haven't covered (e.g. en_AU, Australian English) will get the generic translations (the en ones).
.ts files using Qt Linguist to edit them:/opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper linguist *.ts
See http://doc.qt.nokia.com/4.7/linguist-translators.html for more about using Qt Linguist.
.ts files. This will prevent you releasing your application with missing translations. Here's an example command will show the names of any .ts files which have one or more unfinished translations:grep -c "translation type=\"unfinished\"" *.ts | grep -v -E ":0$"
.qm files) containing the translations:/opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper lrelease *.ts
.qm files we just created as Qt resources, along with some special directory path syntax, to load them into the translator. (I couldn't get them to load as non-resource files unless I used an absolute file path.)
.qrc) to the project (right-click on the project in Qt Creator, select Add New...)..qm files to the .qrc file as resources. When the application is built, resources are compiled into the binary so they can be accessed by the application in a platform-agnostic fashion.main.cpp file so it loads the appropriate translation resource (.qm) into the application, based on the locale:
#include <QTranslator>
#include <QLocale>
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QString locale = QLocale::system().name();
QTranslator translator;
/* the ":/" is a special directory Qt uses to
* distinguish resources;
* NB this will look for a filename matching locale + ".qm";
* if that's not found, it will truncate the locale to
* the first two characters (e.g. "en_GB" to "en") and look
* for that + ".qm"; if not found, it will look for a
* qml-translations.qm file; if not found, no translation is done
*/
if (translator.load("qml-translations." + locale, ":/"))
app.installTranslator(&translator);
MainWindow w;
w.show();
return app.exec();
}
Note that we could enhance this code to default to English (set locale to en) if a user's language isn't supported.
See http://doc.qt.nokia.com/4.7/linguist-programmers.html, which explains more about integrating translations into a Qt app.
qml-translations-build-desktop directory (where the code is compiled by default) or the equivalent location if you're using a MADDE toolchain:/opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp ./qml-translations
NB this uses the meego-sdk-qtapp wrapper script, described below.
If your language is set to en_GB or en_US, you should see the English version; if set to fr_FR or de_AT, you'll see it in French or German respectively. If you are using another language, you'll see untranslated strings.
You can try it in a different language with:
LANG=fr_FR.utf8 /opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper ./qml-translations LANG=de_AT.utf8 /opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper ./qml-translations
For reference: I created a wrapper for other MeeGo SDK Qt binaries (lupdate and lrelease) and my own executables, to ensure that the MeeGo SDK Qt libraries occur first on the path.
Hopefully this will eventually be redundant, if/when the SDK supplies its own wrapper.
Put the following code in a file called meego-sdk-qtapp, in the same directory as the MeeGo SDK binaries (/opt/meego/meego-sdk-qt/bin):
#!/bin/sh
export QTDIR="`meego-sdk-qmake -query QT_INSTALL_PREFIX`"
export QT_PLUGIN_PATH="`meego-sdk-qmake -query QT_INSTALL_PLUGINS`"
export QT_LIBS_PATH="`meego-sdk-qmake -query QT_INSTALL_LIBS`"
# Let the wrapped binary know that it has been run through the wrapper.
export WRAPPER="`readlink -f "$0"`"
HERE="`dirname "$WRAPPER"`"
case ":$PATH:" in
*:$HERE:*)
# $PATH already contains $HERE, leave it where it is.
;;
*)
# Prepend $HERE to $PATH.
export PATH="$HERE:$PATH"
;;
esac
# Always use our versions of Qt libs.
if [ -n "$LD_LIBRARY_PATH" ]; then
LD_LIBRARY_PATH="$QT_LIBS_PATH:$HERE:$HERE/lib:$LD_LIBRARY_PATH"
else
LD_LIBRARY_PATH="$QT_LIBS_PATH:$HERE:$HERE/lib"
fi
export LD_LIBRARY_PATH
APP=$1
shift
if [ -f $HERE/$APP ] ; then
$HERE/$APP "$@"
else
$APP "$@"
fi
Make sure it's executable (chmod +x).
Then use it to run the MeeGo SDK applications like this:
/opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp lupdate <other arguments here>
Or your own applications (like the qml-translator application created above) with:
/opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp ./qml-translator