2013-10-27 48 views
5

我有一個基於RequireJS的單頁Marionette應用程序,它需要支持轉換。使用Requirejs動態加載區域文件

我的目標是爲每種語言提供一個字典文件,並根據登錄用戶的配置加載相關文件。

由於大多數用戶會使用英語,因此我想在構建過程中使用應用程序中的英語詞典(使用r.js)。

我寫了一個小模塊,它基本上包裝jed.js(庫我使用的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(); 
}); 

正如你可以看到,現場數據從一個靜態文件加載。 我希望能夠將區域設置傳遞給轉換器構造函數,並基於此,加載正確的JSON文件。

如何在保持與構建項目捆綁在一起的英文JSON的情況下完成這項工作?

回答

1

這是我最終做的解決方案。 它運行得非常好,我也學會了使用$ .Deferred這非常棒!

對我來說,關鍵是使用require文本插件作爲代碼中的加載器。

默認語言環境設置爲依賴關係,這樣它也在構建中烘焙。

解釋是在下面的代碼:

//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

你應該能夠檢查用戶設置,構建一個依賴字符串,將它傳遞給Translator,然後用它來代替localeData - r.js將忽略動態依賴,但應該捆綁EN語言環境。

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

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

} 

and inside譯者:"locale_data": passedData || englishData

(或做翻譯模塊中的一樣,像if (userLocale !== 'en_US') { require([path], function(locale) {...})

理論上它應該工作,雖然你cannot use simplified CommonJS這裏應該使用回調需要,否則,你會得到Module name ... has not been loaded yet for context錯誤。

+0

感謝您的答覆,但我最後做的東西有點不同。你可以在下面看到我的答案 – elanh