使用requireJS和预编译的Handlebars模板加载翻译(i18next)

时间:2013-12-05 21:37:09

标签: requirejs amd handlebars.js i18next precompiled-templates

我在数据库中设置了requireJS个预编译Handlebars模板和我的翻译i18next。我需要按以下顺序做一些事情:

  1. 从数据库加载我的翻译
  2. 在Handlebars中注册一个帮助器,以便我的预编译模板中的值可以翻译
  3. 我的requireJS配置文件如下所示:

    require.config({
      deps: ["main"],   
      paths: {
        'handlebars.runtime': "../assets/js/libs/handlebars.runtime.amd.min",
        i18n: "../assets/js/libs/i18next-1.7.1",
    
        // Shim Plugin
        use: "../assets/js/plugins/use"
      },
    
      use: {
        i18n: {
          attach: "i18n"
        }
      } 
    });
    

    我的main.js文件如下所示,需要namespace.js

    require([
      'namespace',
      'modules/Transport'
    ], function (
      namespace,
      $,
      Transport
    ) {
      var Router = Backbone.Router.extend({
        routes: {
          '*any':                'any'
        },
    

    我的namespace.js将尝试注册Handlebars助手并使用翻译初始化i18next:

    define([
      "handlebars.runtime",
      "use!i18n"
    ], function(
      Handlebars,
      i18n
    ) {   
      var defaultLanguage = 'en';
      var translations;
      $.when(
          $.getJSON('/api/translations', function (result) {
            translations = result;
          })
      ).then(function () {
    
        i18n.init({ useCookie: false, resStore: translations, lng: defaultLanguage });
    
        Handlebars.default.registerHelper('t', function(i18n_key) {
          var result = i18n.t(i18n_key);
    
          return new Handlebars.default.SafeString(result);
        });
      });
    

    我的modules/Transport.js模块将取决于namespace.js并将加载预编译的模板。加载预编译模板时,它在Handlebars.default.templates中可用。所以我的模块看起来像这样:

    define([
      'namespace',
      'templates/compiled/transport_template'
    ], function(
      namespace,
    ) {
      i18n.t('translate something');
      var template = Handlebars.default.templates['transport_template'];
    

    我遇到的问题是我不能让requireJS首先加载翻译,然后继续注册帮助程序并在我的模块中进行一些翻译。模块和模板在完成对我的数据库的异步调用之前加载,所以我一直都没有加载错误(或帮助器或i18next模块)

    我真的很困惑,如何在加载我的模块之前先设置requireJS来加载Handlebars和i18next?

1 个答案:

答案 0 :(得分:4)

几点说明:

  • RequireJS提供了内置的shim配置属性,您可能不需要use.js。
  • i18next提供AMD模块版本(可在homepage上获得),因此您无需填充它。不确定他们是否遵循最佳做法,但它确实有效。
  • 永远不要在AMD模块中使用全局对象,始终要求将对象明确地作为依赖项。
  • 考虑到所有这一切,你已经几乎已经到了需要的地方;只要您需要在另一个模块中使用其require('i18next')函数,就可以t。剩下的问题是如何确保正确初始化i18next的问题,我在下面提供了答案。
  • 我不熟悉Handlebars,特别是它的助手功能,所以这可能只是解决你一半问题的答案。

前一段时间我不得不用i18next解决基本相同的问题;我基本上将其模块包装在另一个模块中,该模块在返回之前初始化i18next。

<强> i18next-wrapper.js

define(function (require) {
    var i18next = require('i18next-actual');
    i18next.init(...);
    return i18next;
});

为了增加透明度,您可以使用路径:

requirejs.config({
    paths: {
        'i18next-actual': 'path/to/i18next.amd-$version',
        'i18next': 'path/to/i18next-wrapper',
    }
});

这样require('i18next')像往常一样的所有用户模块都会确保它已经初始化一次,并且不需要修改实际的i18next模块。

因此,希望能够在需要它的模块之前首先解答如何加载和初始化i18next的问题。您应该可以对任何其他模块执行相同的操作。

如果您可以使用此功能,其他人可能可以帮助处理Handlebars细节,或者您也可以从这里获取它。

编辑:我忘记了i18next的异步性质。我记得包装t函数以检查initialized标志以确保i18next确实已满载(包括翻译)。虽然这很有效,但我最终认为增加的复杂性并不是立即值得的,而是决定使用getAsync: false i18next选项。你可能不同意。