2013-10-27 16 views
5

Ho un'app Marionette a pagina singola costruita su RequireJS che deve supportare le traduzioni.Carica file locale in modo dinamico utilizzando Requirejs

Il mio obiettivo è avere un file di dizionario per ogni lingua e, in base alla configurazione dell'utente connesso, caricare il file pertinente.

Poiché la maggior parte degli utenti utilizza l'inglese, desidero raggruppare il dizionario inglese nell'app durante la generazione (utilizzando r.js).

ho scritto un piccolo modulo traduttore, che avvolge sostanzialmente jed.js (biblioteca che sto utilizzando per i18n):

//in myTranslator.js 
define(function (require) { 
    "use strict"; 

    var Jed = require("jed"); 
    var localeData = require("json!locales/en_US.json"); 

    var Translator = function() { 
     var i18n = new Jed({ 
      "domain": "messages", 
      "locale_data": localeData 
     }); 
     return i18n; 
    }; 
    return Translator; 
}); 

//in app.js 
define(function(require){ 
    var Translator = require("myTranslator"); 
    var translator = new Translator(); 
}); 

Come si può vedere, i dati locale viene caricato da un file statico. Voglio essere in grado di passare le impostazioni internazionali al costruttore Translator e, in base a ciò, caricare il file JSON corretto.

Come si può fare insieme mantenendo il JSON inglese in bundle con il progetto costruito?

risposta

1

Questa è la soluzione che ho finito per fare. Ha funzionato abbastanza bene, e ho anche imparato a usare $ .Deferred che è stato fantastico!

La chiave per me stava utilizzando il plug-in di testo obbligatorio come caricatore nel codice.

Le impostazioni internazionali predefinite sono impostate come dipendenza, in questo modo viene anche elaborata nella generazione.

spiegazioni sono nel seguente codice:

//in translator.js 
define(function (require) { 
    "use strict"; 

    var $ = require("jquery"); 
    var _ = require("underscore"); 
    var Jed = require("jed"); 
    var text = require("text"); 
    var defaultDictionary = require("json!locales/en_US.json"); 

    var Translator; 

    Translator = (function() { 
     var DEFAULT_LOCALE = "en_US"; 
     var defaultLocaleData = { 
      locale: DEFAULT_LOCALE, 
      dictionary: defaultDictionary 
     }; 

     var createTranslator = function (localeData) { 
      //create the actual Jed instance with the relevant dictionary 
      var i18n = new Jed({ 
       "domain": "messages", 
       "locale_data": localeData.dictionary 
      }); 
      return i18n; 
     }; 
     var parseLocaleDictionary = function (locale, dictionary) { 
      //parse the dictionary JSON string loaded by text plugin... 
      //handle errors in parsing if needed 
     }; 
     //get to work here 
     var getTranslatorForLocale = function (locale) { 
      //$gettingData promise will be resolved when data for Jed is loaded and ready 
      var $gettingData = $.Deferred(); 
      //$creatingTranslator promise will be returned to caller and will be resolved when everything's done 
      var $creatingTranslator = $.Deferred(); 

      if (!locale || locale === DEFAULT_LOCALE) { 
       //default locale, so resolve right away because we required it already 
       $gettingData.resolve(defaultLocaleData); 
      } 
      else { 
       //need to load the dictionary from here 
       var dictionaryUrl = require.toUrl("locales/" + locale + ".json"); 
       //this is the dynamic loading 
       text.get(
        dictionaryUrl, 
        function (dictionary) { 
         //if successful, parse the JSON string and use that dictionary 
         var localeData = parseLocaleDictionary(locale, dictionary); 
         $gettingData.resolve(localeData); 
        }, 
        function (error) { 
         //on load error, use the default and resolve promise 
         $gettingData.resolve(defaultLocaleData); 
        }); 
      } 

      //once the data is ready, we can create the translator instance 
      $gettingData.done(function (localeData) { 
       var i18n = createTranslator(localeData); 
       //notify caller that translator is ready 
       $creatingTranslator.resolve(i18n); 
      }); 

      return $creatingTranslator.promise(); 
     }; 

     return { 
      //this function is returned to the user of Translator 
      getTranslator: function (locale) { 
       var $gettingTranslator = getTranslatorForLocale(locale); 
       return $gettingTranslator; 
      } 
     }; 
    }()); 

    return Translator; 
}); 
//in app.js 
define(function (require) { 
    var Translator = require("translator"); 
    //in app.js 
    var myTranslator; 
    var userLocale = "fr_FR"; 
    //this is a promise that will be resolved when translator is ready 
    var $getTranslator = Translator.getTranslator(userLocale); 
    //when translator is ready, store it 
    $getTranslator.done(function (translator) { 
     myTranslator = translator; 
    }); 
    //... 
}); 
4

Dovresti essere in grado di controllare le impostazioni utente, costruire una stringa di dipendenza, passarla a Translator e quindi usarla invece di localeData - r.js ignorerà la dipendenza dinamica ma dovrebbe raggruppare le impostazioni internazionali EN.

if (userLocale && userLocale !== 'en_US') { 

    var localePath = 'json!locales/' + userLocale + '.json'; 
    require([ localePath ], function(locale) { 
     var translator = new Translator(locale); 
    }); 

} 

e all'interno Traduttore: "locale_data": passedData || englishData.

(o fare lo stesso all'interno del modulo traduttore, come if (userLocale !== 'en_US') { require([path], function(locale) {...}))

In teoria dovrebbe funzionare, anche se si cannot use simplified CommonJS qui e dovrebbe usare callback-richiedono, altrimenti si otterrà Module name ... has not been loaded yet for context errore.

+0

Grazie per la risposta, ma ho finito per fare qualcosa di un po 'diverso. Puoi vedere la mia risposta qui sotto – elanh