Marionette.Renderer, Подчеркивание шаблонов и интернационализация с помощью i18next

В настоящее время мы нуждаемся в добавлении интернационализации в приложение среднего размера с использованием шаблонов Backbone.Marionette и подчеркивания.

После тщательного исследования появляются два допустимых варианта:

  • underi18n, который обеспечивает прямую интеграцию с подчеркиванием, но не имеет плюрализации, что становится необходимым для поддержки более французского и английского
  • i18next, который предоставляет мощный API, но только прямую интеграцию с шаблонами ручек

Нам нужно в более долгосрочной перспективе локализовать еще на многих языках (надеюсь,!), поэтому underi18n, вероятно, не оправдает себя, и единственные жизнеспособные решения тогда выделяются как i18next.

Прежде чем идти дальше, я расскажу о своих двух вопросах, а затем предоставил полный контекст и исследовательский процесс, который я прошел.

  • Как я могу централизовать локализацию моих шаблонов с помощью i18next и Marionette
  • Как я могу вставить глобальный помощник во все мои шаблоны подчеркивания

Централизовать локализацию шаблонов

Одна вещь, которую я нахожу очень назойливой с i18n, - это то, как вы должны называть ее во всех своих функциях onRender, что означает добавление вызова в каждый из наших десятков текущих просмотров и всех наших будущих просмотров. Как я вижу, исправьте меня, если я ошибаюсь, это будет выглядеть так:

MyView = Marionette.ItemView.extend({
 template: myUnlocalizedTemplate,
 onRender: function () {
 /* ... some logic ... */
 this.$el.i18n();
 }
 /* And everything else... */
});

и повторяться снова и снова.

Я нахожу это очень неудобным с точки зрения внедрения и обслуживания, поэтому я начал копаться в Backbone и Marionette, помня о прошлом проекте, был некоторый способ создания шаблонов для предварительной обработки. Я натыкаюсь на Marionette.Renderer, который кажется правильным инструментом для работы. Но прежде чем входить в полную установку и реализацию i18next, я хочу убедиться, что я на правильном пути. Потому что, если я могу ясно видеть, как underi18n и _.template(under18n.template(myTemplate, t)); могут быть хорошо интегрированы с Renderer и предоставить мне глобальное решение для предварительной обработки и локализации моих шаблонов, я не уверен в том, как идти с i18next в этом случае. Тот факт, что я не мог найти ни одного примера того, кто это делает, также беспокоит меня, все ли либо идут с шаблонами рулей, либо вручную вызывают .i18n() в каждом представлении? На данный момент нет элементов jquery, на которых можно связать перевод, поэтому я довольно озадачен тем, как это возможно.

Было бы очень благодарным ответом что-либо, предоставляющее пример того, что я пытаюсь выполнить, дальнейшая документация или советы по пути!

2 ответа

Наконец-то я нашел хороший выход из этого. Вот оно, как я надеюсь, может помочь другим в этой ситуации.

/* Some initializer
 * ...
 */
// Init i18n and
// Start the app in the callback
$(function() { 
 i18n.init({
 function (t) {
 App.start();
 }
 });
});
// Following in the initialize:after
// We'll override the default Marionette.Renderer.render function
App.on('initialize:after', function() {
 overwriteRenderer();
});
function overwriteRenderer() {
 // Simply use a closure to close over the current render function
 var render = Marionette.Renderer.render;
 // Then override it
 Marionette.Renderer.render = function (template, data){
 // Extend data to inject our translate helper 
 data = _.extend(data, {_t: i18n.t});
 // And finally return the result of calling the original render function
 // With our injected helper
 return render(template, data);
 };
}
// Then in any template, simply use it as follow
// Do not forget the `=` to output the translation in the final DOM
<div>
 <%= _t("my_key", {options: "my options"} %>
</div>

Как показано, я работал над этим, вводя функцию перевода во весь шаблон в качестве помощника вида. Это решение является приятным и чистым, поскольку оно передает большую часть перевода в шаблоны, где я считаю, что это должно быть. Он не требует изменения какого-либо представления, что резко ограничивает количество изменений, необходимых для выполнения локализации в существующем проекте.

Одной из аккуратных деталей является также возможность вставки переменной в вашу интерполяцию, что означает что-то вроде этого:

<div>
 <%= myVar %>
</div>

можно превратить в нечто подобное, для интерполяции

<div>
 <%= _t("my_key", {option: myVar} %>
</div>

Или даже

<div>
 <%= _t("my_key", {option: _t(myDynamicKey)} %>
</div>

И в файле po

msgid "my_translation_with_interpolation"
msgstr "My translation with __option__"

Позволяет динамически вводить ключ, который будет локализован, а затем интерполирован в исходной строке.

Надеюсь, что это поможет кому-то другому.


Другое решение, если вам нужен доступ к экземпляру вида в хелперах:

// Global template helpers in Marionette
var _mixinTemplateHelpers = Marionette.View.prototype.mixinTemplateHelpers;
Marionette.View.prototype.mixinTemplateHelpers = function(target) {
 var _this = this;
 target = _.extend({
 // generate a unique id in the view scope
 _id: function(baseName) {
 return _this.cid + '-' + baseName;
 },
 }, target);
 return _mixinTemplateHelpers.call(this, target);
};

licensed under cc by-sa 3.0 with attribution.