问题
my first question here - please go easy. I'm using express, express3-handlebars and i18next-node with node.js
The plan is to work with a different translation namespace depending on which view (i.e. which handlebars file) is currently being served. So if we're looking at the page called ie(.hbs), i18next will look in the namespace called ie(.json) for the relevant language. This makes organisation and coordination of translations easier.
This is how I'm currently doing it: first I send the current page into the handlebars template for rendering (even this seems unnecessary - handlebars doesn't automatically expose which file it's rendering?):
res.render( url_base_path, { layout: ("sub"), title: title, currentpage: url_base_path } );
and then I access the variable "greeting" to be translated in the namespace of the current page like so {{t "greeting" page=currentpage }}
- the annoying thing is that there are 10's of these variables on each page. Don't Repeat Yourself, anybody?
't' is defined in the express3-handlebars create() function, like so, helpers: { t: t }
and the translate function looks like this
var t = function (i18next_key, options) {
var page, result;
page = options.hash.page;
result = i18next.t(page + ":" + i18next_key);
return new hbs.handlebars.SafeString(result);
};
for the sake of full disclosure, this is what my (english) namespace file for the current page looks like
{
"greeting": "Hello, it appears you're using Internet Explorer, an outdated web browser."
}
this works, but it seems like there should be a much simpler solution.
what i really want is to be able to just type {{t "greeting"}}
into the handlebars template to achieve the same result. is this possible without overriding core handlebars functionality?
here is the i18next docs page http://i18next.com/pages/doc_features.html
回答1:
I've answered my own question - it turned out easier than I expected.
You can access the handlebars instance in my Handlebars translate helper (duh?), so in the helper: renderer = this
(for clarity), then you can just access renderer.currentpage
to get the name of the required namespace. Note, you still have to send currentpage in the render function (on res.render()
), but I'm ok with that side of it.
I've done it like this (it's probably pretty slow like this at the moment, but it works exactly how I want it to):
// Set namespace for translation
options.ns = options.ns || bestNamespaceFor( i18n_key );
result = i18n.t(i18n_key, options);
return new hbs.handlebars.SafeString(result);
function bestNamespaceFor( i18n_key ){
if ( i18n.exists(i18n_key, { ns: renderer.currentpage }) ) return renderer.currentpage;
if ( i18n.exists(i18n_key, { ns: renderer.layout }) ) return renderer.layout;
if ( i18n.exists(i18n_key, { ns: "common" }) ) return "common";
Works perfectly with {{t "my translation key" }}
and gets the right namespace no matter where I use it.
来源:https://stackoverflow.com/questions/20492766/express3-handlebars-and-18next-node-internationalisation-based-on-page