Meego Wiki
Views

QML/Internationalisation

From MeeGo wiki
Revision as of 15:13, 26 November 2010 by Elliot (Talk | contribs)
Jump to: navigation, search

Contents

Overview

This tutorial explains how to internationalise a QML application.

IT IS STILL A VERY ROUGH DRAFT

It would probably be a good idea to write a script to generate the translations for you, check if any are unfinished etc.

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.5/linguist-manager.html.

But for QML translations, I couldn't work out a way to get the QML files to be parsed. There is no mention of this in the page about QML i18n (http://doc.qt.nokia.com/4.7/qdeclarativei18n.html) either.

Note that I've also ignored anything like version control and separate translation services (transifex etc.) in this account.

Pre-requisites

Qt Creator (MeeGo 1.1 SDK version) installed. See these instructions.

System Setup

TBD

How to

The workflow:

  1. Use a custom Qt app to load your QML: this way it's easier to add the translation steps to the project. I used the transparent window application as a starting point.
  2. Add 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
      }
    }
    

    Note that I used a __string__ syntax, so we can easily see if translations are working when I run the application. 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 a user's language is not supported, you will see English.

  3. 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.
    To generate these, you need to use the 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 a load of *.ts files with entries for each translatable string in your app's QML files.

  4. Now you need to flesh out the *.ts files using the linguist GUI to edit them:
    /opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper linguist *.ts

    I'm not going to try to explain linguist to you: http://doc.qt.nokia.com/4.7/linguist-translators.html does that.

  5. Check that there are no unfinished translations in the .ts files. This will prevent you releasing your application with missing translations (again a script to do this would be good). 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$"
    
  6. Create the release binaries (.qm files) containing the translations:
    /opt/meego/meego-sdk-qt/bin/meego-sdk-wrapper lrelease *.ts
    
  7. The next bit isn't documented anywhere where I could find it, but works. We use the .qm files we just created as Qt resources, and use a bit of magic to load them into the translator. (I couldn't get them to load otherwise unless I used an absolute file path.)
    1. Add the .qm files to a .qrc file as resources: this compiles them into the binary.
    2. In the main.cpp file, load the appropriate translation file 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.setLocale(locale);
        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.5/linguist-programmers.html, which explains more about integrating translations into a Qt app.

    3. Run the binary from the qml-translations-build-desktop directory (where the code is compiled by default) or equivalent (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, 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
      

      Hah! It works!

    MeeGo SDK wrapper script

    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 ...
    

    Or your own applications (like the qml-translator application created above) with:

    /opt/meego/meego-sdk-qt/bin/meego-sdk-qtapp ./qml-translator
    
Personal tools