Reputation: 734
Does any one knows an example or could explain here how node.js and express would have to route for a multilanguage site? I'm using i18n-node for translation and folder like routing ( /es/, /de/ , etc ) for different languages. This all are static routes but I also have routes like apiRoutes.route('/user/profile') using 'app' at the begining ( app.get('/app/user/profile') so please consider this in your answer so is NOT necesary route to : app.get('/es/app/user/profile') .
having 15 routes like this now:
app.get('/terms', function(req, res) {
res.render('terms',{
...
});
});
how it have to be set for routes like:
app.get('/es/terms', function(req, res) {
res.render('terms',{
...
});
});
Should I duplicate this routes and add for example a locale for each like:
app.get('/es/terms', function(req, res) {
res.render('terms',{
...
});
});
Or Should do something like:
if cookie['lang'] && cookie['lang'] is in locales
// then redirect to /:lang/terms
else
// show default language in /terms
if req.headers["accept-language"] && req.headers["accept-language"]
// then redirect to /:lang/terms
else
//show default language in /terms
Or there is another way I should approach this that follows good practices or is better respecting standards?
Miro's Answer in : How can I get the browser language in node.js (express.js)? says I should use app.all('*', ...
Is this all I need?, ..still, it might have a syntax error or i'm not understanding well this two parts
var rxLocal = /^\/(de|en)/i;
...
app.get(/\/(de|en)\/login/i, routes.login);
thanks in advance
Upvotes: 0
Views: 4066
Reputation: 1
You can have a middleware to extract locale before sending to your routes' handlers.
The middleware could be like:
function extractLocale(req, res, next) {
const pathParts = req.path.split("/").filter(Boolean);
const firstDir = pathParts[0];
if (checkLocalsExisted(firstDir)) {
req.lang = firstDir;
req.url = req.url.replace(`/${firstDir}`, "");
} else {
req.lang = "en";
}
next();
}
The middleware does two things:
The URL rewriting step allows subsequent routes' handlers to match the path without considering the locale prefix.
So when defining your routes' handlers, you can write them without the locale in the url, e.g.,:
app.get('/terms', function(req, res) {
const lang = req.lang;
// do lang specific things before rendering
res.render('terms',{
...
});
});
Ps. We faced the same problem before and the entire solution is documented, read more if you need.
Upvotes: 0
Reputation: 1967
You need to consider 2 things :
The HTTP protocole define the Accept-Language header to manage the local. This is a normalized method. You can access it with the req.acceptsLanguages method of express.
You can get the local from the path. In express it can be do with a parameter patter like /:local/rest/of/path
and retrieve in the request object with the req.param method.
You can also get the information from the cookies with the req.cookies properties (don't forgot to set it).
To increase the user experience you can mix the both method. For exemple get the default language from the HTTP header send by the browser but permite to the user to override this in you application and store this parameter in the cookies.
Each methods to get the local can be used from different way. I will use random of them in exemple but they are all compatible.
In case of you use a template Engine and you controller can be local agnostic. You can use a middleware to get the local information and configure the render engine.
app.use('/:local' (req, res, next) => {
let localKey = req.param('local');
res.locals = // Some ingenious method to get the locales from localKey
next();
}
Check res.locals and your engine documentation.
If the local is part of the contoller process. You can get directly is value in controller.
In case of you use a complexe method to determine the final value of the local, you can also use a middleware to determine this value and enrich the request with it.
app.use((req, res, next) => {
let local = req.cookies.local;
if(!local) local = req.acceptsLanguages();
if(!local) local = 'en-US';
req.local = local;
}
You can use both method too. It depend of what you need. Find the best way to get a maintainable code and avoid replication for your use case.
When you use middle where witch impact the controllers, be sure you declare them before your routes.
Upvotes: 3
Reputation: 20236
You can use a route parameter to get the locale from the URL, like this:
app.get('/:lang/terms', function (req, res) {
if (req.params === 'es') {
res.send('¡Hola!');
else {
res.send('Hi!');
}
});
The colon character tells Express to put whatever is between the first to slashes of the path in req.params.lang
.
See express routing documentation for details.
Upvotes: 1