我有一个单页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();
});如您所见,区域设置数据是从静态文件加载的。我希望能够将区域设置传递给Translator构造函数,并在此基础上加载正确的JSON文件。
如何通过将英语JSON与构建的项目捆绑在一起来实现呢?
发布于 2013-10-29 11:58:50
这就是我最后所做的解决方案。它运行得很好,我还学到了如何使用$.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;
});
//...
});发布于 2013-10-27 22:10:02
您应该能够检查用户设置,构造一个依赖字符串,将其传递给转换器,然后使用它代替localeData -- r.js将忽略动态依赖关系,但应该将其绑定到本地。
if ( userLocale && userLocale !== 'en_US' ) {
var localePath = 'json!locales/' + userLocale + '.json';
require([ localePath ], function( locale ) {
var translator = new Translator( locale );
});
}内部翻译:"locale_data": passedData || englishData。
(或者在翻译器模块中做同样的操作,比如if ( userLocale !== 'en_US' ) { require([path], function(locale) {...}))
从理论上讲,它应该可以工作,尽管您在这里使用了不能使用简化的CommonJS,并且应该使用回调-require,否则您将得到http://requirejs.org/docs/errors.html#notloaded错误。
https://stackoverflow.com/questions/19621586
复制相似问题