      1 // ==========================================================================
      2 // Project:   The M-Project - Mobile HTML5 Application Framework
      3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
      4 // Creator:   Dominik
      5 // Date:      29.11.2010
      6 // License:   Dual licensed under the MIT or GPL Version 2 licenses.
      7 //            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
      8 //            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
      9 // ==========================================================================
     10
     11 m_require('core/foundation/object.js');
     12
     13 /**
     14  * @class
     15  *
     16  * M.I18N defines a prototype for for internationalisation and localisation within
     17  * The M-Project. It is used to set and get the application's language and to
     18  * localize any string within an application.
     19  *
     20  * @extends M.Object
     21  */
     22 M.I18N = M.Object.extend(
     23 /** @scope M.I18N.prototype */ {
     24
     25     /**
     26      * The type of this object.
     27      *
     28      * @type String
     29      */
     30     type: 'M.I18N',
     31
     32     /**
     33      * The system's default language.
     34      *
     35      * @type String
     36      */
     37     defaultLanguage: 'en_us',
     38
     39     /**
     40      * This property is used to map the navigator's language to an ISO standard
     41      * if necessary. E.g. 'de' will be mapped to 'de_de'. Currently we only provide
     42      * support for english and german. More languages are about to come or can be
     43      * added by overwriting this property.
     44      *
     45      * @type Object
     46      */
     47     languageMapper: {
     48         de: 'de_de',
     49         en: 'en_us'
     50     },
     51
     52     /**
     53      * This method returns the localized string for the given key based on
     54      * the current language.
     55      *
     56      * @param {String} key The key to the localized string.
     57      * @returns {String} The localizes string based on the current application language.
     58      */
     59     l: function(key) {
     60         return this.localize(key);
     61     },
     62
     63     /**
     64      * This method returns the localized string for the given key based on
     65      * the current language. It is internally used as a wrapper for l() for
     66      * a better readability.
     67      *
     68      * @private
     69      * @param {String} key The key to the localized string.
     70      * @returns {String} The localizes string based on the current application language.
     71      */
     72     localize: function(key) {
     73         if(!M.Application.currentLanguage) {
     74             M.Application.currentLanguage = this.getLanguage();
     75         }
     76
     77         if(this[M.Application.currentLanguage] && this[M.Application.currentLanguage][key]) {
     78             return this[M.Application.currentLanguage][key];
     79         } else if(this[M.Application.defaultLanguage] && this[M.Application.defaultLanguage][key]) {
     80             M.Logger.log('Key \'' + key + '\' not defined for language \'' + M.Application.currentLanguage + '\', switched to default language \'' + M.Application.defaultLanguage + '\'', M.WARN);
     81             return this[M.Application.defaultLanguage][key];
     82         }  else if(this[this.defaultLanguage] && this[this.defaultLanguage][key]) {
     83             M.Logger.log('Key \'' + key + '\' not defined for language \'' + M.Application.currentLanguage + '\', switched to system\'s default language \'' + this.defaultLanguage + '\'', M.WARN);
     84             return this[this.defaultLanguage][key];
     85         } else {
     86             M.Logger.log('Key \'' + key + '\' not defined for both language \'' + M.Application.currentLanguage + '\' and the system\'s default language \'' + this.defaultLanguage + '\'', M.WARN);
     87         }
     88
     89     },
     90
     91     /**
     92      * This method sets the applications current language and forces it to reload.
     93      *
     94      * @param {String} language The language to be set.
     95      */
     96     setLanguage: function(language) {
     97         if(!this.isLanguageAvailable(language)) {
     98             M.Logger.log('There is no language \'' + language + '\' specified!', M.WARN);
     99             return;
    100         } else if(language && language === M.Application.currentLanguage) {
    101             M.Logger.log('Language \'' + language + '\' already selected', M.INFO);
    102             return;
    103         }
    104
    105         if(localStorage) {
    106             localStorage.setItem('$' + M.Application.name + '_lang$', language);
    107             location.reload();
    108         }
    109     },
    110
    111     /**
    112      * This method is used to get a language for the current user. This process is divided
    113      * into three steps. If one step leads to a language, this on is returned. The steps are
    114      * prioritized as follows:
    115      *
    116      * - get the user's language by checking his navigator
    117      * - use the application's default language
    118      * - use the systems's default language
    119      *
    120      * @returns {String} The user's language.
    121      */
    122     getLanguage: function() {
    123         var language = null;
    124
    125         if(localStorage) {
    126             language = localStorage.getItem('$' + M.Application.name + '_lang$');
    127         }
    128
    129         if(language) {
    130             return language;
    131         } else if(navigator) {
    132             var regexResult = /([a-zA-Z]{2,3})[\s_.-]?([a-zA-Z]{2,3})?/.exec(navigator.language);
    133             if(regexResult && this[regexResult[0]]) {
    134                 return regexResult[0].toLowerCase();
    135             } else if(regexResult && regexResult[1] && this.languageMapper[regexResult[1]]) {
    136                 var language = this.languageMapper[regexResult[1]];
    137                 return language.toLowerCase();
    138             } else if(M.Application.defaultLanguage) {
    139                 return M.Application.defaultLanguage.toLowerCase();
    140             }
    141         } else {
    142             return this.defaultLanguage;
    143         }
    144     },
    145
    146     /**
    147      * This method checks if the passed language is available within the app or not.
    148      *
    149      * @param {String} language The language to be checked.
    150      * @returns {Boolean} Indicates whether the requested language is available or not.
    151      */
    152     isLanguageAvailable: function(language) {
    153         if(this[language] && typeof(this[language]) === 'object') {
    154             return true;
    155         } else {
    156             M.Logger.log('no language \'' + language + '\' specified.', M.WARN);
    157             return false;
    158         }
    159     }
    160
    161 });