1. #1
    Ext User Tawez's Avatar
    Join Date
    Feb 2009
    Location
    Poland
    Posts
    16
    Vote Rating
    0
    Tawez is on a distinguished road

      0  

    Lightbulb More general approach to i18n in Ext

    More general approach to i18n in Ext


    Intro: Background
    Our products are localized to 7 languages (with tendency to grow).
    We use various independent APIs on the backend side, two or more in one application.
    Because of that, we find that it will be easier to localize our products on the frontend side with english language as reference.

    What we got in Ext?
    Ext is localized in various places.
    A little bit in Date and Ext.util.Format objects, then of course we have got ext-lang-xx.js files... just to mention a few places.
    Some parts are good, some not... as in real world

    Date
    Date is vary general object - it is its strength as well as weakness (sometimes).
    There is no natural/common way to localize date formats.
    November 16, 2003 may be localized as '11/16/2003' (US format 'm/d/Y') as well as '2003-11-16' ('Y-m-d').
    The date format is parameter here.

    Ext.util.Format
    Ext.util.Format behave like there is US and TheRestOfTheWorld, or US and nothing more.
    The 1st approach I used to call 'I can live with it... for a while at least', the 2nd one IMHO is just inappropriate for such a professional framework.
    • Ext.util.Format.number()
      - quite good as far as You can live only with 'comas' and 'dots' as a separators. Unfortunately sometimes there is a need to have other separators like 'space' for grouping.
    • Ext.util.Format.plural()
      - It may be hard to imagine, but there are other languages with more than one plural form, and it's not so easy as to add 's' or another magic character to singular form.
    • Ext.util.Format.usMoney()
      - yes, we have a little bit more than one currency... unfortunately. Should we add euMoney(), ukMoney(), jpMoney()? Maybe a more general function will work for all of us?

    ext-lang-xx.js
    For me, the problem with ext-lang-xx.js files is redundancy, but frankly speaking, I got no good solution for this...
    After all it works, so 'do not touch' may be the right way


    In general... Yes, we can override functions, or extend objects just to have what we need, but sometimes it just don't work or it's wrong if we need portable and universal code.

    Our solution
    We got separate i18n class so we got all in one place.
    It's not a singleton, so we can have as many instances as we need.
    It may be helpful when more than one language is needed at the same time.
    i18n got few config params so we don't need to override functions to have different results.

    Numbers
    Code:
    var EN = new Our.i18n({
        group: ',',
        dec = '.'
    });
    var PL = new Our.i18n({
        group: ' ',
        dec = ','
    });
    EN.number(1234567890.987, '0.00'); // => '1,234,567,890.99'
    PL.number(1234567890.987, '0.00'); // => '1 234 567 890,99'
    Strings
    The key approach is to translate the strings 'on the fly', so we can translate texts in JavaScript files as well as from AJAX requests.
    Each instance of i18n has got its dictionary, few params and translation functions that works according to dictionary and params.
    Translation engine is based on GNU gettext - i18n has _() and _n() functions that allows to translate text with optional context.
    Code:
    Ext.ns('App');
    App.i18n = new Our.i18n({
        lang: 'en',
        pluralForms: 2,
        plural: function (n) {
            return (n == 1 ? 0 : 1);
        },
        dict: { 
            __default__: {
                single: {
                    'new': 'New'
                },
                plural: {
                    'car': ['1 car', '{0} cars', 'no car']
                }
            },
            'super': {
                single: {
                    'new': 'Super New'
                },
                plural: {
                    'car': ['1 super car', '{0} super cars', '{0} super cars']
                }
            }
        }
    });
    
    App.i18n._('new'); // -> 'New'
    App.i18n._('new', 'super'); // -> 'Super New'
    App.i18n._n('car', 2); // -> '{0} cars'
    App.i18n._n('car', 2, 'super'); // -> '{0} super cars'
    App.i18n._n('car', 0); // -> 'no car'
    App.i18n._n('car', 0, 'super'); // -> '{0} super cars'
    Dates
    In each i18n instance we have defined few date/time format params, so we can use uniform syntax and got variable response. The main problem here is naming convention, as usually
    Code:
    var EN = new Our.i18n({
        date_YMD: 'm/d/Y'
    });
    var PL = new Our.i18n({
        date_YMD: 'Y-m-d'
    });
    var now = new Date();
    var lang = PL;
    
    now.format(lang.date_YMD);
    ...
    //then we can switch the language
    lang = EN;
    now.format(lang.date_YMD);

    Outro
    After over 18 months of development We've got few ideas about i18n of Ext and apps based on it. (If it will help, we can share the code.)
    It's not a perfect solution, but maybe it will led to more general and universal approach to localization in Ext?

    Do we know the plans for i18ning the ExtJS 4.0 ?...

  2. #2
    Ext JS Premium Member
    Join Date
    Aug 2007
    Location
    Antwerp, Belgium
    Posts
    555
    Vote Rating
    27
    joeri has a spectacular aura about joeri has a spectacular aura about joeri has a spectacular aura about

      0  

    Default


    I just use override files that load localization and translation. The order is (1) load code, (2) load i18n overrides, (3) initialize code based on overrides. The override files are dynamically generated from PHP based on current translation files and database settings. The size of the files is kept reasonable through on-demand loading mechanisms (each piece of on-demand loaded code also loads its translation overrides file). The only downside is that locale changes require a complete refresh of the app's UI.

  3. #3
    Ext User Tawez's Avatar
    Join Date
    Feb 2009
    Location
    Poland
    Posts
    16
    Vote Rating
    0
    Tawez is on a distinguished road

      0  

    Default


    We also use override files. Right now it is the only effective way to localize Ext framework - and it works quite well.
    After loading Ext we use only our i18n object - it works very well
    Of course our solution might not suits to everyone needs, but...

    Thanks to our i18n functions to translate texts we have more natural interface from linguistic point of view - no matter which language was chosen by user.
    It's easy as switching between two dictionaries.

    Let us asume that we have Ext.i18n (singleton as Ext.Ajax).
    Then everything related to localization would be in one place.
    With a little effort we can have very universal tool not only for US part of the community.


    After all, even if it's bad idea (is it?), existence or behavior of functions like Ext.util.Format.number(), Ext.util.Format.plural() or Ext.util.Format.usMoney() is questionable.

  4. #4
    Sencha User
    Join Date
    Apr 2010
    Location
    Italy
    Posts
    17
    Vote Rating
    0
    bariand is on a distinguished road

      0  

    Default


    I managed to localize my app extending the existing classes and adding in the properties labels to be localized, also modifying the ext-lang-xx.js file.
    But in this way I'm forced to extend every single object I added to my app.

    Is there a way to obtain a more clear and elegant result?
    Would be possible for you to exploit plugin development in this case?

  5. #5
    Ext JS Premium Member
    Join Date
    Mar 2010
    Posts
    37
    Vote Rating
    0
    sareko is on a distinguished road

      0  

    Default


    I use something similar to the dictionary approach, based on resource files as they work in .NET

    MyApp.Local = new MyCompany.ResourceBag({
    SomeWord: { en: 'SomeWordInEnglish', fr: 'SomeWordInFrench', cn: 'SomeWordInChinese' }
    })

    Then a little bit of magic in ResourceBag so that:

    MyApp.Local.SomeWord gives me the appropriate version.

    Thus i never use a displayed string anywhere in my code, always using MyApp.Local.Something...
    Now obviously this wouldn't scale to 100 languages, but in my case i sometimes need multiple languages on one page, or switching between 2 languages in the middle of a workflow. If you don't need that, the ResourceBag could be replaced simply by an object of key/values, generated from the server. Problem solved.

    The critical part is to centralize your strings in a file that can be swapped (or contain multiple languages, depending on requirement). Everything else is just case by case gravy.

  6. #6
    Sencha User
    Join Date
    Apr 2010
    Location
    Italy
    Posts
    17
    Vote Rating
    0
    bariand is on a distinguished road

      0  

    Default


    First of all thanks for your advice.

    So, if I'm not wrong, it should be enough to build somethign like this:
    Code:
    var localeStrings = Ext.extend(Object, {    
        attenzione: 'Attention',
        carica:        'Load',
        constructor : function() {
            Ext.ux.uirnet.localeStrings.superclass.constructor.call(this);
            }
        });
    and having put this definition in each locale file (I need only a few locales) it is possible to substitute labels with a call to
    Code:
    localeString.prototype.carica
    I have a limited number of custom labels (other than ExtJS built-in ones) so I think this wouldn't suffer any performance issue...

  7. #7
    Ext JS Premium Member
    Join Date
    Mar 2010
    Posts
    37
    Vote Rating
    0
    sareko is on a distinguished road

      0  

    Default


    localeStrings.carica would be sufficient. Why call the prototype? No need to extend object or anything either.

    localStrings = {
    foo: 'bar',
    foo2: 'bar2',

    }

    Basically all you need to do is make a bag of constants and only load one such bag form the server.

    My version was slightly more complex since i needed all the languages at the same time as well as ways to dynamically select them based on various factors

  8. #8
    Ext JS Premium Member vishalg's Avatar
    Join Date
    Sep 2007
    Location
    Los Angeles, CA
    Posts
    75
    Vote Rating
    0
    vishalg is on a distinguished road

      0  

    Default


    Could you make your I18n code available it would help to look it everything together.

Similar Threads

  1. i18n with Ext.js: Resource Bundles!
    By elmasse in forum Community Discussion
    Replies: 29
    Last Post: 25 Jan 2013, 2:21 PM
  2. Replies: 0
    Last Post: 25 Nov 2009, 4:27 AM
  3. General approach for forms with variable fields
    By BitPoet in forum Ext 2.x: Help & Discussion
    Replies: 2
    Last Post: 8 Mar 2009, 11:07 PM
  4. Using TinyMCE as a field in an Ext Form - best approach?
    By pianoroy in forum Ext 1.x: Help & Discussion
    Replies: 4
    Last Post: 27 Sep 2007, 1:52 PM

Thread Participants: 4

Tags for this Thread