-->

sencha touch i18n basics

2020-06-17 06:26发布

问题:

How is i18n handled within Sencha touch? (I am talking of localization support for strings, but also of localized components)

A more specific question: I have a form that contains a date picker, how do I make sure that the date will be displayed and picked in european format when I access the application using a french android phone?

Cheers

回答1:

There isn't an official API for i18n in SenchaTouch, yet. Although in Ext 4 there are localization files for all components in the /locale folder.

There is an old tutorial that indicates a way, by dynamically in setting the src attribute of a script tag according to the locale.

<script type="text/javascript" id="extlocale"></script>
<script type="text/javascript">

var browserLang = window.navigator.language; // get the browsers language
var locales = [ 'fr', 'es', 'pt', 'pt-BR', 'pt-PT' ]; // available locale files
var locale = 'fr'; // default locale

// check browser language against available locale files
for (var i = locales.length - 1; i >= 0; i--) {
    if (browserLang === locales[i]) {
        locale = browserLang;
        break;
    }
};

// Insert src attribute to extlocale
if(locale) {
    Ext.fly('extlocale').set({src:'ext/locale/ext-lang-' + locale + '.js'});
}

</script>

Use window.navigator.language to check the browser's language.

Locale files must be set in /ext/locale/ext-lang-fr.js
Where you can override the components properties.

Ext.onReady(function() {

if(Date){
    Date.shortMonthNames = [
        "Janv",
        "Févr",
        "Mars",
        "Avr",
        "Mai",
        "Juin",
        "Juil",
        "Août",
        "Sept",
        "Oct",
        "Nov",
        "Déc"
    ];

    Date.getShortMonthName = function(month) {
        return Date.shortMonthNames[month];
    };

    Date.monthNames = [
        "Janvier",
        "Février",
        "Mars",
        "Avril",
        "Mai",
        "Juin",
        "Juillet",
        "Août",
        "Septembre",
        "Octobre",
        "Novembre",
        "Décembre"
    ];

    Date.monthNumbers = {
        "Janvier" : 0,
        "Février" : 1,
        "Mars" : 2,
        "Avril" : 3,
        "Mai" : 4,
        "Juin" : 5,
        "Juillet" : 6,
        "Août" : 7,
        "Septembre" : 8,
        "Octobre" : 9,
        "Novembre" : 10,
        "Décembre" : 11
    };

    Date.getMonthNumber = function(name) {
        return Date.monthNumbers[Ext.util.Format.capitalize(name)];
    };

    Date.dayNames = [
        "Dimanche",
        "Lundi",
        "Mardi",
        "Mercredi",
        "Jeudi",
        "Vendredi",
        "Samedi"
    ];

    Date.getShortDayName = function(day) {
        return Date.dayNames[day].substring(0, 3);
    };

    Date.parseCodes.S.s = "(?:er)";

    Ext.override(Date, {
        getSuffix : function() {
            return (this.getDate() == 1) ? "er" : "";
        }
    });
}

});

I made a working prototype you can check out here:
http://lab.herkulano.com/sencha-touch/date-picker-i18n/



回答2:

For your own strings (not talking about native touch component) you could do something like this.

1) In your index.html in the head section, load a LocaleManager.js file (whatever the name) before the

<script id="microloader" type="text/javascript" src="sdk/microloader/development.js"></script>

In your localeManager, depending on your browser's language load the resource file corresponding to your language (myStrings-fr.js | myStrings-en.js )

You can do something like this to get the language in the browser:

window.navigator.language || window.navigator.userLanguage || window.navigator.browserLanguage || window.navigator.systemLanguage

2) Create your resources files with your translated string

It should look like this for the english version (myStrings-en.js) :

var myStrings = {
MyPackage1: {
    myString1: 'Seach...'
}};

It should look like this for the french version (myStrings-fr.js) for example :

var myStrings = {
MyPackage1: {
    myString1: 'Recherchez...'
}};

3) In your sencha touch code, for example for a searchfield place holder value

xtype: 'searchfield',
id: 'searchToolbarItem',
placeHolder: myStrings.MyPackage1.myString1

Hope it will help.

Another solution could be to modify the build process of your sencha touch app and create localized versions of your app when building it. So there would be one version per language. Then depending on the brower language you would load the right version of your app when loading the app in the browser.



回答3:

I wrote my own i18n class, here it is:

Ext.define('MyApp.util.I18n', {
    singleton : true,

    config : {
        defaultLanguage : 'en',
        translations : {
            'en' : {
                'signIn' : 'Sign in',
                'name' : 'Name',
                'hello' : 'Hello {0} !',
                        'enOnly' : 'English only !'
            'fr' : {
                'signIn' : 'Identifiez-vous',
                        'name' : 'Nom',
                        'hello' : 'Bonjour {0} !'
            }
        }
    },

    constructor: function(config) {
        this.initConfig(config);
        this.callParent([config]);
    },

    translate: function (key) {

        // Get browser language
        var browserLanguage = window.navigator.userLanguage || window.navigator.language;

        // Is it defined ? if not : use default
        var language = this.getTranslations()[browserLanguage] === undefined ? this.getDefaultLanguage() : browserLanguage;

        // Translate
        var translation = "[" + key + "]";
        if (this.getTranslations()[language][key] === undefined) {

            // Key not found in language : tries default one
            if (this.getTranslations()[this.getDefaultLanguage()][key] !== undefined) {
                translation = this.getTranslations()[this.getDefaultLanguage()][key];
            }

        } else {

            // Key found
            translation = this.getTranslations()[language][key];
        }

        // If there is more than one argument : format string
        if (arguments.length > 1) {

            var tokenCount = arguments.length - 2;
            for( var token = 0; token <= tokenCount; token++ )
            {
                translation = translation.replace( new RegExp( "\\{" + token + "\\}", "gi" ), arguments[ token + 1 ] );
            }

        }

        return translation;

    }
});

Then you can call it like this:

MyApp.util.I18n.translate('signIn'); 
// Gives 'Identifiez-vous'

MyApp.util.I18n.translate('hello', 'Gilles'); 
// Gives 'Bonjour Gilles !'

MyApp.util.I18n.translate('enOnly'); 
// Gives 'English only !' (defaults to en, as the key is not defined for fr)

MyApp.util.I18n.translate('missing'); 
// Gives '[missing]' (the key is never defined, so it is returned into brackets)

For more information, you can read the original blog post here: http://zippy1978.tumblr.com/post/36131938659/internationalization-i18n-with-sencha-touch



回答4:

Here is my implementation:

I want me app to be translated to English and Spanish, based in the device's language, if the language is not Spanish, then it takes the default (English). Here are my classes:

Ext.define('MyApp.i18n.I18N', {
    alternateClassName: 'i18n',
    singleton: true,
    constructor: function(config) {
        var lang = window.navigator.userLanguage || window.navigator.language

        if(lang==='undefined' || lang.substring(0,2) != 'es'){ //don't care about region
            lang = 'defaultLocale';
        }

        return Ext.create('MyApp.i18n.locales.' + lang, config);
    }
});


Ext.define('MyApp.i18n.locales.defaultLocale', {
    hello:'Hello'
});

Ext.define('MyApp.i18n.locales.es', {
    extend: 'MyApp.i18n.locales.defaultLocale',
      hello:'Hola'
});

And here is how you call it:

i18n.hello

I hope it helps.



回答5:

locale folder is under /src folder in sencha touch