Reputation: 31
I am using expressjs and i18n-node (https://github.com/mashpie/i18n-node). It's working, except for elegant linking. What I have now is this:
app.all(/^\/(\w{2}\/)+(\w*)?/, function(req, res, next) {
var lang = req.params[0];
var type = req.params[1];
req.url = req.url.replace(lang, "");
if(type !== 'javascript' && type !== 'img' && type !== 'css') {
i18n.setLocale(lang.slice(0, 2));
}
next();
});
(I want /foo as well as /en/foo to work). If the language is not specified in the url, the headers are checked, and if not, it defaults to English. By the way, my solution seems less than ideal (I have to make manual checks to see if it is not static content), so if any of you have a better solution I am all ears.
Now, my real problem is making links to internal content. If a user is here: "/en/foo", a "/bar"-link should actually be "/en/bar". I am using jade (for no particular reason other than that it was the default, again open to suggestions..)
I tried adding a helper function to Jade:
app.helpers({
__i: i18n.__
,__n: i18n.__n
,link_to: function(link, text) {
//TODO: how to get request here?
// this should be defined to the absolute base path
var baseUrl = "/";
// only append locale if it is part of the existing url!
var locale = i18n.getLocale();
return '<a href="' + baseUrl + locale + '/' + link + '">' + text + '</a>';
}
});
.. but it has many problems:
What is the preferred way to do this? I've been searching and searching, but unable to find a good answer..
This is actually also a general question; i.e how do you link to other internal content, like the link_to in Rails. Simply doing a(href="someAction") is not good enough, as you want it to generate absolute URLs so that the pretty URLs do not break static content links.
Thanks!
Upvotes: 3
Views: 2526
Reputation: 3988
I paste code from an own project with i18n, I use a class for dicto and another class to search language by IP:
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
secret: "sessid",
key: 'uwsid',
store: sessionStore
}));
app.use(function (req,res,next) {
if (req.session.uid) {
req.lang = req.session.uid.lang;
next();
} else if (req.cookies.lang) {
req.lang = req.cookies.lang;
next();
} else {
var alang = typeof req.headers['accept-language'] != "undefined" ? req.headers['accept-language'].substr(0,2) : null;
var ipinfows = ipinfo.getInstance();
ipinfows.getInfo(req.connection.remoteAddress, function (err,data) {
if (err) {
req.lang = alang;
res.cookie('lang', alang);
} else if (data && data.error) {
req.lang = alang;
res.cookie('lang', alang);
} else {
console.log("seteando");
req.lang = data.lang.toLowerCase();
for (i in countryLangs) {
if (countryLangs[i].indexOf(data.lang) != -1) {
req.lang = i;
}
}
if (alang != req.lang) {
req.langdifference = alang;
}
res.cookie('lang', req.lang);
}
next();
});
}
});
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
Before of the routing app.use(app.router); you can define callbacks, in this case I search the lang and define it in a cookie. After I add an dynamicHelper to include the Dicto object into the template:
app.dynamicHelpers({
i18n: function (req,res) {
return new i18n({lang: req.lang});
}
});
With the lang define before that routing. (saving in req.lang), And I can use the i18n halper now from template (with jade):
form.uniForm(action="/account",method="post")
fieldset.inlineLabels
.ctrlHolder
label(for="nickname") #{**i18n.getText('user:nick')**}:
input(type="text",name="nickname",value=everyauth.user.nick)
p.formHint
i18n object now is the same defined on the dynamic helper.
Upvotes: 2
Reputation: 2652
As far as I understand it, express will only call the helper function once (When the template is compiled...)
In the express guide, http://expressjs.com/guide.html, check out dynamicHelpers which should be more useful for your situation (dynamicHelpers provide request and response objects).
Upvotes: 0