Загрузка переводов (i18next) с помощью requireJS и предварительно скомпилированных шаблонов Handlebars
У меня есть установка requireJS с предварительно скомпилированными шаблонами Handlebars и моим переводом i18next в базу данных. Мне нужно сделать несколько вещей в следующем порядке:
- Загрузить мои переводы из базы данных
- Зарегистрируйте помощника в 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следующая опция вместо. Вы можете не согласиться.