Quantcast

Override this.tr translations of contribs in the app using the contribs

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Override this.tr translations of contribs in the app using the contribs

Dietrich Streifert
Hi all!

While generalizing common classes for different projects into contribs,
I'm in need to have different translations for those contribs when used
in different applications.

Let's say I have a contrib named LIB, where I have a class using
translation this way:

var label = this.tr("item");

Depending on the app using the contrib I want to translate different,
optimally just by using differ *.po files for contrib LIB.

This would be for the (just examples) the app "APPLES" the po entry:

     msgid "item"
     msgstr "apple"

and the app "PEARS" the po entry:

     msgid "item"
     msgstr "pear"

I've already found an old thread with a similar problem:

http://qooxdoo.678.n2.nabble.com/library-translation-td4756389.html

But that thread is 5 years old. So I'm hoping there is a solution for
what I try to achieve.

Regards
Dietrich


------------------------------------------------------------------------------
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Override this.tr translations of contribs in the app using the contribs

Dietrich Streifert
I've chosen a simple solution by creating a mixin for the application as
follows:

qx.Mixin.define("apple.application.MTranslation",
{
   construct : function() {
qx.locale.Manager.getInstance().addListener("changeLocale",
this.loadApplicationTranslation, this);
     this.loadApplicationTranslation();
   },

   members : {

     loadApplicationTranslation : function() {
       var locale = qx.locale.Manager.getInstance().getLocale();
       if(locale) {
         var map = this.getApplicationTranslationMap(locale);
         if(map) {
qx.locale.Manager.getInstance().addTranslation(locale, map);
         }
       }
     },

     getApplicationTranslationMap : function(locale) {
       var map = {
         "item" : {
           en : "apple",
           de : "Apfel"
         }
       };

       var m = {};
       for(var id in map) {
         if(map[id][locale]) {
           m[id] = map[id][locale];
         }
       }

       return m;
     }
   }
});

for the pears application the relevant part in getApplicationTranslation
(besides the pear namespace) would be:

       var map = {
         "item" : {
           en : "pear",
           de : "Birne"
         }
       };

To use this mixin simply add it to the include [...] list in your
Application.js like this:

qx.Class.define("apple.Application",
{
   extend : qx.application.Standalone,

   include : [
     apple.application.MTranslation
   ],

...

I know that this way I'm loosing the automatism given by "generat.py
translation", having to track the this.tr/this.trn entries manually.

Any thoughts, hints, optimizations are very welcome.

Regards
Dietrich

Am 14.10.2015 um 15:02 schrieb Dietrich Streifert:

> Hi all!
>
> While generalizing common classes for different projects into
> contribs, I'm in need to have different translations for those
> contribs when used in different applications.
>
> Let's say I have a contrib named LIB, where I have a class using
> translation this way:
>
> var label = this.tr("item");
>
> Depending on the app using the contrib I want to translate different,
> optimally just by using differ *.po files for contrib LIB.
>
> This would be for the (just examples) the app "APPLES" the po entry:
>
>     msgid "item"
>     msgstr "apple"
>
> and the app "PEARS" the po entry:
>
>     msgid "item"
>     msgstr "pear"
>
> I've already found an old thread with a similar problem:
>
> http://qooxdoo.678.n2.nabble.com/library-translation-td4756389.html
>
> But that thread is 5 years old. So I'm hoping there is a solution for
> what I try to achieve.
>
> Regards
> Dietrich
>


------------------------------------------------------------------------------
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Override this.tr translations of contribs in the app using the contribs

thron7
Hi Dietrich,

I suppose the thread you've linked to still holds true basically. The approach of qooxdoo's translation system is to keep translations "close to the code", so that in the generated app translations are bundled with the code that actually uses them. Hence the need to internationalize libraries on their own. I think this makes sense in most cases.

The drawback is that of brittle coupling of application and libraries. The application depends on the foresight of the library maintainer. What if your application want to use a language X which was not included in the library?! This shouldn't be a big issue either, as you always can fall back on the library's sources and edit the configuration and the translations to suit you.

But, as you found out, it is also hard to 'override' in the app existing translations that come with a library. In this case, I think your approach with a mixin is quite viable. As you are using .addTranslation() you're still hooking into the resolution process of the this.tr() calls at run time. But as you are using keys that the library already might have provided ("item" in your example) you are relying on the fact that your translations take precedence. I'm sure you tested this and it worked, but you are sort of relying on an internal implementation detail that might change in the future.

But taking this as a given, what you could try is you could combine your idea with qooxdoo's translation service. You could make your translation map generic, with no hard-coded translations in it, e.g. like this:

getApplicationTranslationMap : function(locale) {
    var map = {
       "item" : this.tr("item") 
    };
    var m = {};
    for(var id in map) {
        m[id] = map[id];  
    }
    return m;
}

This relies on the fact that "item" is mapped to the translated string according to the locale that is in effect at run time.

This would make your mixin generic and you could include it into the APPLES and PEARS applications unchanged. Then just do the normal cycle of running 'translation' and translating the "item" key differently in each application. You might run into situations where the translation of the app gets overridden by the translation of the library, I'm not sure. See how it goes!

You would still need to keep track of the keys in your translation map by hand (short of generating it from the library's .po file ...). But there are other projects that also have code (e.g. in the form of a static class) just to list keys they want to register with translation, so you are not far off.

HTH,
Thomas


------------------------------------------------------------------------------

_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Override this.tr translations of contribs in the app using the contribs

Dietrich Streifert
Thank you Thomas,

this way it would be able to use the po files created by generate.py translation. Never thought about using this.tr in the map itself. Thank your for the hint!

But shouldn't calling qx.locale.Manager.getInstance().addTranslation(locale, map) at some point after initialization override existing translations?

The comment for addTranslation in qx.local.Manager says:

     * If <code>languageCode</code> already exists, its map will be updated with
     * <code>translationMap</code> (new keys will be added, existing keys will be
     * overwritten).

See
https://github.com/qooxdoo/qooxdoo/blob/release_5_0_1/framework/source/class/qx/locale/Manager.js#L318

Regards
Dietrich

Am 19.10.2015 um 22:13 schrieb thron7:
Hi Dietrich,

I suppose the thread you've linked to still holds true basically. The approach of qooxdoo's translation system is to keep translations "close to the code", so that in the generated app translations are bundled with the code that actually uses them. Hence the need to internationalize libraries on their own. I think this makes sense in most cases.

The drawback is that of brittle coupling of application and libraries. The application depends on the foresight of the library maintainer. What if your application want to use a language X which was not included in the library?! This shouldn't be a big issue either, as you always can fall back on the library's sources and edit the configuration and the translations to suit you.

But, as you found out, it is also hard to 'override' in the app existing translations that come with a library. In this case, I think your approach with a mixin is quite viable. As you are using .addTranslation() you're still hooking into the resolution process of the this.tr() calls at run time. But as you are using keys that the library already might have provided ("item" in your example) you are relying on the fact that your translations take precedence. I'm sure you tested this and it worked, but you are sort of relying on an internal implementation detail that might change in the future.

But taking this as a given, what you could try is you could combine your idea with qooxdoo's translation service. You could make your translation map generic, with no hard-coded translations in it, e.g. like this:

getApplicationTranslationMap : function(locale) {
    var map = {
       "item" : this.tr("item") 
    };
    var m = {};
    for(var id in map) {
        m[id] = map[id];  
    }
    return m;
}

This relies on the fact that "item" is mapped to the translated string according to the locale that is in effect at run time.

This would make your mixin generic and you could include it into the APPLES and PEARS applications unchanged. Then just do the normal cycle of running 'translation' and translating the "item" key differently in each application. You might run into situations where the translation of the app gets overridden by the translation of the library, I'm not sure. See how it goes!

You would still need to keep track of the keys in your translation map by hand (short of generating it from the library's .po file ...). But there are other projects that also have code (e.g. in the form of a static class) just to list keys they want to register with translation, so you are not far off.

HTH,
Thomas



------------------------------------------------------------------------------

_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Override this.tr translations of contribs in the app using the contribs

thron7


On Tue, Oct 20, 2015 at 12:50 PM, Dietrich Streifert <[hidden email]> wrote:
Thank you Thomas,

this way it would be able to use the po files created by generate.py translation. Never thought about using this.tr in the map itself. Thank your for the hint!

But shouldn't calling qx.locale.Manager.getInstance().addTranslation(locale, map) at some point after initialization override existing translations?

Yes, maybe this would be doing too much. You might end up overriding an existing translation with itself :-). So this would make calling .addTranslation() unnecessary, you could just provide a list of "tr()" calls somewhere enumerating the translation keys from the lib you want to override and include in the app's .po files.

The other question is, if your main app provides a translation for "item" and the library does as well, which wins? As there is a single translation map for any locale at run time, only one translation can make it into it (NB: In the long run it might be interesting to name-space the translation keys, so that each library can have their own translation of "item", without disturbing each other). 

My guess is the later the lib appears in the "libraries" array of the generator, the more likely its translation will "win". This might suggest you create yet another library just for a single class that has the keys you wish to override, and their translations, and place it at the far end of your "libraries" array. (If earlier libs win you are fine as the app itself always should come first in the array.)

I'm mostly guessing here so I'm afraid you have to experiment to find it out :-).

T.


------------------------------------------------------------------------------

_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Override this.tr translations of contribs in the app using the contribs

Dietrich Streifert
In the current use case the libraries do not translate anything. The po
files of the libraries do contain the "msgids" but the translation
strings are empty.

qx.locale.Manager.getInstance().addTranslation(locale, map) is called
first in the constructor of the app mixin and that seems to work
reliable in this setup.

So it is not a real override.

But yes, if I'm facing the problem of doing a real override, I think I
would take your advice and create a "translation override" lib and
include it at last position in config.json

Thank you again Thomas for your help.

Regards
Dietrich

Am 20.10.2015 um 21:17 schrieb thron7:
> My guess is the later the lib appears in the "libraries" array of the
> generator, the more likely its translation will "win". This might
> suggest you create yet another library just for a single class that
> has the keys you wish to override, and their translations, and place
> it at the far end of your "libraries" array. (If earlier libs win you
> are fine as the app itself always should come first in the array.)
>


------------------------------------------------------------------------------
_______________________________________________
qooxdoo-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/qooxdoo-devel
Loading...