Important: Please read the Qt Code of Conduct -

Translations: How to efficiently handle language variants?

  • Hello,

    I'm new with Translation features of Qt and wondering how to deal efficiently with language variants (e.g.: fr_fr, fr_BE and fr_CA; or en_US and en_GB).

    Let's consider the case where only little differences would appear between variants. The final translation files (.ts) would be pretty close. Therefore, it would not be efficient to send each of those "unfinished" (=not yet translated) .ts files to different translators that would translate separately these files: at the end they would have mostly done the same job.

    Is there a way to define a "master" translation .ts file from which children may inherit? How to setup a correct translation process?

    Up to now, I have identified two options:

    1st: at the lupdate level.

    Generate the master file with lupdate, send it to the "main" language variant translator (e.g.: fr_FR; OK I could be killed for such a statement)

    Get the file back, completely translated. Now, copy this file as fr_CA and then send it to the french canadian translator, that will review and identify the non-canadian expressions and replace them in the fr_CA file.

    When new strings need to be translated, the fr_fr is updated with lupdate. The main translator translates the new "unfinished" strings and sends back the file

    Problem: Now, what about the fr_CA file? We could let fr_CA outdated (not touched by lupdate) and merge the freshly translated fr_FR to fr_CA (with a diff tool), and then send fr_CA to the french canadian translator that should know which new strings have to be reviewed.

    2nd: at the C++ code level. When "loading" and "installing" QTranslator objects.

    lupdate creates new (or updates) the .ts files for both fr_FR and fr_CA, those files are then left with "unfinished" strings.

    fr_FR is sent to the 1st translator

    then fr_FR (translated) and fr_CA (unfinished) is sent to the french canadian translator. While he reviews the fr_FR, he identifies the non-fr_canadian expressions and inserts them in the fr_CA thanks to Qt Linguist. The fr_CA file looks full of unfinished strings in the original programmer language (let's say english) and contains few fr_canadian expressions.

    now, in the code the fr_FR is first loaded and installed, and after we repeat the operation for the fr_CA file (the unfinished strings won't erase the finished fr_FR strings):

    QApplication app(argc, argv);

    QTranslator fr_FRTranslator, fr_CATranslator;

    //Full translated file

    //Partial translation (with only variants identified) that will erase the finished strings
    Of course we would need to make it generic (not only for french).

    Which option is best? Am I reinventing the wheel?


  • Apologies for reviving an thread, but I am hoping somebody will reply. I am trying to figure out whether it is possible to implement option 2 described here - using "sparsely populated" region-specific translation files (fr_CA for instance), and falling back to the "main" translation file (fr) for any strings not found in the region-specific file.

    I am installing 2 translators just as this post suggests, with full translations in the fr file, and only a few strings in the fr_CA file. The fallback does not work, however, I only ever get strings from the translation file that I load last. That is, if I load the fr_CA file last, I get the fr_CA-specific strings displayed translated, but the rest fall back directly to the source file strings (English in my case). And if I load the fr file last, I get all the strings from the fr file, but none of the fr_CA strings.

    Has anybody made this work?

  • I'm sorry, but how does dynamic language switching have anything to do with this problem? I am not switching languages, I am using French all the time.

    What I want is to get the strings that are located in the fr_CA file to be displayed, and for the strings that are NOT in the fr_CA file, I want the strings from the fr file to be displayed (not fall back to the source strings).

    So I need language fallback to work. I would have hoped that this would just work by default, as in Java, but it obviously does not. So I am trying to work around that issue, by loading 2 QTranslators (as suggested by the original poster), but that also does not work.

  • The "QTranslator docs": report that using multiple translations is possible. They're checked in reverse order so you can load a first translation which would be your main translation, and a second translation that would be your language variant.
    Basically, you load your fr_FR main translation, then load the fr_CA translation. The QTranslator will first look for a translation in fr_CA; if none is found then it'll look back into the previous (main) translation fr_FR.

    I hope that helps ;)

  • Apologies if this is a duplicate response, not sure if my first attempt disappeared in thin air.

    I know that the QTranslator docs state that this is possible, but has anybody made it work? It certainly does not work for me. I only get translations from the last loaded file.

  • That's right, you would normally get translations from the last loaded translation file. But, in case the last translation file is missing a translation, all previously loaded translations files are checked in reverse-loading order until any translation is found.
    I haven't used it, but seems to be pretty easy...

  • It SEEMS pretty easy, except it does not work the way you describe it.

    The translation file loading I see corresponds to what my understanding has always been: QTranslator looks for translation files in a fallback order (if I ask for an fr_CA translation, and QTranslator does not find an _fr_CA file, then it will look for an _fr version, etc.). BUT, if QTranslator finds an _fr_CA file, then it will ONLY look for translations in that file. If a certain string does not have a translation in the fr_CA file, then QTranslator just loads the source string. So we have translation file fallback on a per-file basis, but not on a per-string basis.

    I would love to see a Hello World app with 2 strings that demonstrates that this actually works as advertised...

  • I guess you're doing something wrong because the docs clearly state:
    @Using Multiple Translations
    Multiple translation files can be installed in an application. Translations are searched for in the reverse order in which they were installed, so the most recently installed translation file is searched for translations first and the earliest translation file is searched last. The search stops as soon as a translation containing a matching string is found.@
    The last phrase means that the app will keep searching a translation in the installed translation files until a matching translation is found.

    Probably there's some particular approach needed to install multiple translations. Probably, the way you're using is overwriting the previous translation instead of adding it in the translation files list.

  • I know what the docs state. i would love for somebody to demonstrate that the docs are correct.

  • OK, I did find a way to make this work. It turns out that with context-based translation strings you can just install the 2 translators in the order stated, and the translations will be loaded from the fallback file if not found in the more specific file. So the documentation is indeed correct for that case.

    I was using ID-based translation strings, and for some reason it does not work there (at least I have not been able to make it work - yet). Will update if I do.

Log in to reply