views:

125

answers:

2

Has anyone managed to have the correct layout direction (left-to-right and right-to-left) be inferred from the user’s language settings?

I am having trouble localizing my application to the Arabic (Saudi Arabia) locale. Detection of the current locale, and loading and installing the appropriate QTranslators both work fine. (The text looks great on Linux!) The issue I have is that the global layout direction is not being inferred from the system locale.

The documentation for QApplication::layoutDirection states (with my highlights):

This property holds the default layout direction for this application. On system start-up, the default layout direction depends on the application's language.

This is not what happens, however: the layout is set to Qt::LeftToRight regardless of the system locale. I made a test program that displays the problem. It’s main function is:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QTranslator translator;
    translator.load(":/layoutDirection.qm");
    a.installTranslator(&translator);

    Window w;
    w.show();

    return a.exec();
}

It also has a resource file containing the necessary images and translation files. It is defined like this:

<RCC>
    <!-- Arabic resources. The arrow points to the left. -->
    <qresource prefix="/" lang="ar">
        <file alias="arrow.png">images/arrow-rtl.png</file>
        <file alias="layoutDirection.qm">translations/layoutDirection_ar.qm</file>
    </qresource>
    <!-- English resources. The arrow points to the right. -->
    <qresource prefix="/" lang="en">
        <file alias="arrow.png">images/arrow-ltr.png</file>
        <file alias="layoutDirection.qm">translations/layoutDirection_en.qm</file>
    </qresource>
</RCC>

The source code of the Window class is trivial and the corresponding .ui file does not set the layoutDirection for any widget. When run on the English (United States) locale, the window looks like this:

English screenshot showing left-to-right layout, proper translation, and image of arrow pointing to the right

and when run on the Arabic (Saudi Arabia) locale, it looks like this:

Arabic screenshot showing wrong left-to-right layout, proper translation, and image of arrow pointing to the right

As you can see, the translation of the strings is correct and the image of the arrow points to the right, meaning that the correct resources were loaded. The layout direction is wrong: it should mirror the English layout.

Note. Since I don’t know the Arabic language, the example text is Google-translated. I apologize if it is incorrect.

Solution

Artyom's answer is correct and eventually led me to discovering how top-level Widgets determine their layout direction from the QApplication instance. The Internationalization with Qt manual says:

Qt itself contains over 400 strings that will also need to be translated into the languages that you are targeting. You will find translation files for French, German and Simplified Chinese in $QTDIR/translations, as well as a template for translating to other languages.

The QApplication code has an interesting method, too:

static bool qt_detectRTLLanguage()
{
    return force_reverse ^
        (QApplication::tr("QT_LAYOUT_DIRECTION",
                         "Translate this string to the string 'LTR' in left-to-right"
                         " languages or to 'RTL' in right-to-left languages (such as Hebrew"
                         " and Arabic) to get proper widget layout.") == QLatin1String("RTL"));
}

When the "QT_LAYOUT_DIRECTION" string is translated, the application will automatically detect its layout direction and everything works just fine:

Correct arabic layout on Linux

A: 

Does the order matter... for instance, does this work:

<qresource prefix="/" lang="ar">
    <file alias="layoutDirection.qm">translations/layoutDirection_ar.qm</file>
    <file alias="arrow.png">images/arrow-rtl.png</file>
</qresource>

instead of:

<qresource prefix="/" lang="ar">
    <file alias="arrow.png">images/arrow-rtl.png</file>
    <file alias="layoutDirection.qm">translations/layoutDirection_ar.qm</file>
</qresource>
NinjaCat
I tried it here, but it doesn’t change anything. Resources are being loaded as expected: the arabic text comes from the .qm file and the left-pointing arrow is the .png. The issue is the layout direction itself.
andref
Can you set the property as "AlignLeft" for both of them?
NinjaCat
I can set the layout direction manually, but that’s what I am trying to avoid: I’d have to do it for a multitude of widgets in a real app.
andref
Yeah, I understand. I haven't played with this in a while, but from what I read, the AlignLeft doesn't mean all the text goes from LtoR, but for English etc, it's aligned on the left, and for Arabic, Hebrew, etc it's aligned to the right.
NinjaCat
+4  A: 

As far as I know the layout direction should be set explicitly in Qt.

I know that GTK application do this automatically and qt does not and this is good thing.

I explain. Suppose you have untranslated application started in Arabic or Hebrew locale, what happens all layout displayed from right to left and everything looks ugly and not natural with RTL English stings. Think of untranslated IDE with RTL layout.

The trick to do this right, is to define a special translation key, so the original key has value LTR and only in translated applications to Arabic, Parisian or Hebrew it is translated to RTL.

So best would be something like that:

a.setLayoutDirection(tr("LTR")=="RTL" ? Qt::RightToLeft : Qt::LeftToRight)

And then the direction defined explicitly in the translation file.

So my good advice - from Hebrew speaker, do this the way I shown and don't try to do this automatically according to locale and regardless of actual translation.

Artyom
Thank you! It's the first time I'm localizing an application to a locale with a different layout direction and I never thought of the implications of determining the direction from just the user's language preferences.
andref