Загрузка переводов (i18next) с помощью requireJS и предварительно скомпилированных шаблонов Handlebars

У меня есть установка requireJS с предварительно скомпилированными шаблонами Handlebars и моим переводом i18next в базу данных. Мне нужно сделать несколько вещей в следующем порядке:

  1. Загрузить мои переводы из базы данных
  2. Зарегистрируйте помощника в Handlebars, чтобы мои значения в моих предварительно скомпилированных шаблонах могли быть переведены

Мой файл конфигурации 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 ответ

Пара заметок:

  • RequireJS предоставляет встроенный shim свойство конфигурации, вам может не понадобиться use.js.
  • i18next предоставляет версию модуля AMD (доступна на их домашней странице), поэтому вам не нужно ее подбирать. Не уверен, что они следуют лучшим практикам, но это работает.
  • Никогда не используйте глобальные объекты в модуле 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 i18следующая опция вместо. Вы можете не согласиться.

Другие вопросы по тегам