I have a requireJS setup with precompiled Handlebars templates and my translations i18next in a database. I need to do a few things in the following order:
- Load my translations from a database
- Register a helper in Handlebars so my values in my precompiled templates can be translated
My requireJS config file looks like this:
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"
}
}
});
My main.js
file looks like this, which requires namespace.js
:
require([
'namespace',
'modules/Transport'
], function (
namespace,
$,
Transport
) {
var Router = Backbone.Router.extend({
routes: {
'*any': 'any'
},
My namespace.js
will try to register the Handlebars helper and initialize i18next with the translations:
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);
});
});
My modules/Transport.js
module, will depend on namespace.js
and will load the precompiled template. When loading the precompiled template, it becomes available in Handlebars.default.templates
. SO my module looks like this:
define([
'namespace',
'templates/compiled/transport_template'
], function(
namespace,
) {
i18n.t('translate something');
var template = Handlebars.default.templates['transport_template'];
The problem I have is that I can't make requireJS to first load the translations and after that proceed with registering the helper and do some translations in my modules. The modules and templates get loaded before the async call to my database is completed, so I get errors all the time that stuff isn't loaded (or the helper, or i18next module)
I am really confused here, how can I setup requireJS to load Handlebars and i18next first, before loading my modules?
A couple of notes:
shim
configuration property, you might not need use.js.require('i18next')
whenever you need to use itst
function in another module. A remaining issue is the question of how to ensure that i18next is properly initialized, for which I provide an answer below.I had to solve essentially the same issue with i18next a while ago; I basically wrapped its module in another module that initializes i18next before returning it.
i18next-wrapper.js
For added transparency, you can play with paths:
That way all user modules that
require('i18next')
as usual will be sure that it's initialized once, and the actual i18next module doesn't have to be modified.So that hopefully answers your question of how to load and initialize i18next first before the modules that require it. You should be able to do the same with any other module.
If you can use this, somebody else might be able to help with the Handlebars specifics, or maybe you can take it from here.
Edit: I forgot about the async nature of i18next. I remember wrapping the
t
function to check for aninitialized
flag to ensure that i18next was indeed fully loaded (including translations). While this worked, I ultimately figured that the added complexity wasn't immediately worth it and decided to use thegetAsync: false
i18next option instead. You might disagree.