Marionette.Renderer, Underscore шаблоны и интернационализация с 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>
Как показано, я разработал это, внедрив функцию translate во все шаблоны в качестве помощника вида. Это решение хорошее и чистое, поскольку оно делегирует большую часть перевода шаблонам, где, как я считаю, должно быть. Это также не требует изменения какого-либо представления, резко ограничивая количество изменений, необходимых для выполнения локализации в существующем проекте.
Еще одна приятная деталь: вы также можете вставить переменную в свою интерполяцию, что означает что-то вроде этого:
<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's scope
_id: function(baseName) {
return _this.cid + '-' + baseName;
},
}, target);
return _mixinTemplateHelpers.call(this, target);
};