【问题标题】:Load Locale File Dynamically using Requirejs使用 Requirejs 动态加载语言环境文件
【发布时间】:2013-10-27 18:13:32
【问题描述】:

我有一个基于 RequireJS 构建的单页 Marionette 应用程序,它需要支持翻译。

我的目标是为每种语言都有一个字典文件,并根据登录用户的配置,加载相关文件。

由于大多数用户会使用英语,我想在构建过程中将英语词典捆绑在应用程序中(使用 r.js)。

我写了一个小的 Translator 模块,它基本上包装了 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 与已构建项目捆绑在一起?

【问题讨论】:

    标签: javascript internationalization requirejs amd js-amd


    【解决方案1】:

    您应该能够检查用户设置,构建依赖字符串,将其传递给 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 );
        });
    
    }
    

    内部翻译:"locale_data": passedData || englishData.

    (或在 Translator 模块中执行相同操作,例如 if ( userLocale !== 'en_US' ) { require([path], function(locale) {...})

    理论上它应该可以工作,虽然你在这里 cannot use simplified CommonJS 应该使用回调要求,否则你会得到 Module name ... has not been loaded yet for context 错误。

    【讨论】:

    • 感谢您的回复,但我最终做了一些不同的事情。你可以在下面看到我的答案
    【解决方案2】:

    这是我最终做的解决方案。 效果非常好,而且我还学习了如何使用 $.Deferred,这很棒!

    对我来说,关键是在代码中使用 require text 插件作为加载器。

    默认语言环境设置为依赖项,这样它也会在构建中烘焙。

    解释在下面的代码中:

    //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;
        });
        //...
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-23
      • 2012-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多