Reputation: 46257
I'm trying to internationalize my application that uses Express and Handlebars. Is it possible to get Handlebars partials (fragments) to load and render the localization resource file?
Noting that I've already read this question: express3-handlebars and 18next-node - internationalisation based on page?.
Here is my directory structure:
views/
index.html
login.html
fragments/
frag1.html
frag2.html
frag3.html
locales/
index.json
login.json
fragments/
frag1.json
frag2.json
frag3.json
If necessary, I can separate the JSON files in the locales/
directory to be something like this:
locales/
en-CA/
index.json
...other files
fr-CA/
index.json
...other files
Here is the relevant code in my server.js file:
// ...
hbs = exphbs.create({
extname: '.html',
layoutsDir: [
__dirname + '/views'
],
partialsDir: [
__dirname + '/views/fragments'
],
helpers: {
'json': function(context) {
return JSON.stringify(context);
},
't': function(k) {
// ?
}
}
});
app.engine('.html', hbs.engine);
app.set('view engine', 'html');
The t
helper is what I need help with. In my templates/template fragments, I have these:
<h1>{{ t 'pageTitle' }}</h1>
<p>{{ t 'foo' }}</p>
<p>{{ t 'moreThings' }}</p>
And my JSON file could look like this:
{
"pageTitle": "Hello world",
"foo": "Paragraph contents here",
"moreThings": "There are %d things"
}
Also how do I deal with the printf
parameters?
Upvotes: 1
Views: 2686
Reputation: 461
Doing internationalization in your application means doing two things:
1) Determine which locale should be used
Depending on how you determine the used locale it can be difficult to do this inside a helper. Helpers do not have access to the request object for instance. To be honest i cannot think of a good way to do this inside a helper.
Personally i use the i18n-abide middle-ware to do internationalization. They have several options to determine the locale for a given request. Once locale is determined it is added as a property to the request object. So you only need to determine the locale once for each request. An other advantage is that you have also access to the locale outside the handlebars helper.
2) Access the resource files
To access the resource files from within a helper means that you should read and parse the resource files outside the helper. Parsing resource files every time you need to translate a string really hurts performance.
Here you also should use middle-ware. You can do something like the pseudo code below.
function setup() {
// Load resource files from disk and parse them.
var resources = { /* parsed resources*/ }
return function(req, res, next) {
var locale = determineLocalFunction(req);
req.getText = function(label) {
return resources[local][label];
}
}
}
Now you can use the req.getText function every where in your code. Personally i never use language labels inside a partial. Instead i pass all the language strings needed in a partial using a data object. The reason behind this is that i think partials should be as re-usable as possible. Using hardcoded language labels inside them makes them less re-useable.
When you do want to use the getText function in your partials you can pass to getText function to your partial.
Something like this:
var objectPassedToPartial = {
getText: req.getText
}
Use it like:
{{getText 'label'}}
Read more about Mozilla's i18n-abide solution, i really love it.
Upvotes: 1