lunedì 26 settembre 2011

Translating C++/Qml applications

I have spent a bit of time to understand how to translate qml applications since examples on the web are a different between each others.
Just a reminder, this is for compiled sofware using C++ and QDeclarativeView; for QML files loaded with QMLViewer there is no need since it's already set (and you just need to put qm files in a subdirectory).

Any translatable string in qml must be wrapped inside qsTr(), like this:

Than, assuming you have put all qml files in the same directory, you have to run lupdate to generate the ts file:


Now you have a ts file to open with QtLinguist. After you are done release it and put it in the translations subdir. To make the application locale-aware, we need to load the translation automatically at runtime. If we're using last QtSdk than we can implement a public function in the QmlApplicationViewer class, otherwise we can simply implement it in the main.cpp. This function must be called before the QDeclarativeView::showFullScreen() and QDeclarativeView::setSource() are called.


void QmlApplicationViewer::loadTranslator()
{
    QString locale = QLocale::system().name();
    QTranslator* translator = new QTranslator;
    qDebug()<<"Translating: "<<translator->load(QString("/opt/myproject/translations/myproject_") + locale + QString(".qm"));
    qApp->installTranslator(translator);
}

In this way the application will look for an available translation for the current set locale, and will load it if founf. Otherwise application will keep staying in source language. Coded in this way, to add a new translation is really simple: just add another qm file in the translations subdir.
This Subdir does not have to stay in the file system, it can be put in the resource file of the application.

8 commenti:

  1. Hello I have still problems with translations in QML. Is it not necessary to install translator functions like:

    QScriptEngine engine;
    ...loading translator
    engine.installTranslatorFunctions();

    ?

    my C++ text is tranlating good but QML file loaded and showed via QmlApplicationViewer is not translating at all. I am sure translator is loaded properly and installed (because on C++ widget it is working) . Any hints?

    RispondiElimina
  2. Hi, how have you created the ts file? I found that using the QtCreator built-in lupdate fails to include qml files strings so I had to call it from terminal. You still have to call the translator manually because QmlApplicationViewer is not doing that by itself like qmlviewer.

    RispondiElimina
  3. I called lupdate from terminal. It is okay.
    What do you mean by calling the translator mannually.
    I put to my main.cpp code something like this before declaring QmlApplicationViewer.

    QScopedPointer app(createApplication(argc, argv));

    QTranslator* translator = new QTranslator;

    qDebug()<<"Translating: "<load(QString("qml/International/inter_en"));

    app->installTranslator(translator);

    I get "Translating: true" on qDebug so the translator is loaded correctly, I know it is installed as well, because I can test it on a C++ QPusgButton widget in the same main.cpp code. Only the QmlApplicationViewer is not working with translator

    RispondiElimina
  4. Hi, I found out that main.qml file which is set as a main file in:
    viewer->setMainQmlFile(QLatin1String("qml/International/main.qml"));

    this is translating correctly!
    But main.qml is loading the MainPage.qml as the component for intitalPage here:

    initialPage: MainPage {tools: toolBarLayout}

    and text in MainPage.qml is not translating correctly.

    Have you experienced something like this?

    RispondiElimina
  5. Is the ts file you generate including the strings of the MainPage?
    Have you tried without using the application booster?

    The only issue I encountered when translating qml apps was defining QT NO DEBUG, in this way UI wasn't getting translated even if the translator function returned true.

    RispondiElimina
  6. OK! I think I found what is the issue.

    lupdate main.qml mainpage.qml -ts inter_sk.ts did not work

    lupdate main.qml MainPage.qml -ts inter_sk.ts is correct. So case sensitity !!!
    But anyway thanks for discussion.

    RispondiElimina
  7. Glad you solved it, you may try with lupdate *.qml when you get bigger projects, it will handle case sensivity aswell.

    RispondiElimina
  8. now that is a problem with Windows, lupdate on windows does not accept wildcards

    RispondiElimina