2013-10-27 19 views
5

Tôi có một ứng dụng trang đơn Marionette được xây dựng trên RequireJS cần hỗ trợ bản dịch.Tải tệp Locale động bằng cách sử dụng Requirejs

Mục tiêu của tôi là có tệp từ điển cho từng ngôn ngữ và dựa trên cấu hình của người dùng đã đăng nhập, hãy tải tệp có liên quan.

Vì hầu hết người dùng sẽ sử dụng tiếng Anh, tôi muốn nhóm từ điển tiếng Anh trong ứng dụng trong khi tạo (sử dụng r.js).

Tôi đã viết một mô-đun Translator nhỏ, mà về cơ bản kết thúc tốt đẹp jed.js (thư viện Tôi đang sử dụng cho 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(); 
}); 

Như bạn có thể thấy, các dữ liệu địa phương được nạp từ một tập tin tĩnh. Tôi muốn có thể truyền vào miền địa phương để xây dựng Translator, và dựa trên đó, tải đúng tệp JSON.

Làm cách nào có thể được thực hiện cùng với việc giữ JSON tiếng Anh đi kèm với dự án được xây dựng?

Trả lời

1

Đây là giải pháp mà tôi đã kết thúc. Nó hoạt động khá độc đáo và tôi cũng đã học về cách sử dụng $ .Deferred thật tuyệt vời!

Chìa khóa cho tôi đã sử dụng plugin văn bản yêu cầu làm trình tải trong mã.

Ngôn ngữ mặc định được đặt làm phụ thuộc, theo cách đó, cookie cũng được tạo trong bản dựng.

giải thích là trong các mã dưới đây:

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

Bạn có thể kiểm tra cài đặt người dùng, xây dựng chuỗi phụ thuộc, chuyển nó sang Translator và sau đó sử dụng nó thay vì localeData - r.js sẽ bỏ qua phụ thuộc động nhưng nên nhóm EN locale.

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

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

} 

và bên trong Translator: "locale_data": passedData || englishData.

(hoặc làm như vậy bên trong mô-đun Translator, như if (userLocale !== 'en_US') { require([path], function(locale) {...}))

Về lý thuyết nó phải làm việc, mặc dù bạn cannot use simplified CommonJS đây và nên sử dụng callback-yêu cầu, nếu không bạn sẽ nhận được Module name ... has not been loaded yet for context lỗi.

+0

Cảm ơn bạn đã trả lời, nhưng tôi đã kết thúc làm điều gì đó một chút khác nhau. Bạn có thể xem câu trả lời của tôi bên dưới – elanh

Các vấn đề liên quan