i18n-node icon indicating copy to clipboard operation
i18n-node copied to clipboard

Redirect every non defaultLocale route

Open LantosIstvan opened this issue 9 years ago • 12 comments

This is my i18n configuration:

locales: ['en', 'hu'],
fallbacks: { en: 'hu' },
defaultLocale: 'en',

i18n initialized to the routes with this middleware:

const langRouter = (req, res, next) => {
  const paramsLang = req.params.lang;
  const resLocals = res.locals;
  if (/^(en|hu)$/.exec(paramsLang)) {
    i18n.setLocale([req, resLocals], paramsLang);
    resLocals.language = `/${paramsLang}`;
  }
  next();
};

app.all('/:lang/*', langRouter);
app.use('/:lang', langRouter);

In the past I redirected every route this way for example when someone requested the frontpage:

app.use('/:lang', index);
app.use('/', (req, res) =>
  res.status(302).redirect(`/${req.getLocale()}`)
);

Now I try to only redirect the /hu route:

app.use('/hu', index);
app.use('/', (req, res, next) => {
  if (req.headers['accept-language'] === 'hu') {
    return res.status(302).redirect('/hu');
  }
  return next();
});
app.use('/', index);

This is not works, not redirecting the frontpage. Another problem is the frontpage (and the entire site) translated to Hungarian.

What I want is the users will be redirected to /hu route when their browsers are set to hungarian language. The / route should always return the defaultLocale (english).

So these routes always be english:

/
/blog
/contact

And I want to redirect to these routes only those users whose browsers set to hungarian:

/hu
/hu/blog
/hu/contact

How can this be achieved?

LantosIstvan avatar Oct 26 '16 16:10 LantosIstvan

i18n doesn't do any redirecting or setting of languages. It reacts on your implementation. As res.locals are to get modified by any middleware it is definetly hard to tell, what exactly is happening with that setup until res is used to finally respond to the users request.

Plus I think that double declaration won't work:

app.use('/', (req, res, next) => {
  if (req.headers['accept-language'] === 'hu') {
    return res.status(302).redirect('/hu');
  }
  return next();
});
app.use('/', index);

i18n needs a sequence of i18n.configure once initially followed by a i18n.init on every request. If your middleware calls i18n.setLocaleprior to i18n.init it wont affect anything at all.

mashpie avatar Oct 26 '16 16:10 mashpie

for multilingual routing, you should consider https://github.com/mashpie/i18n-node#i18n__l

mashpie avatar Oct 26 '16 16:10 mashpie

That's how it works in my app too, i18n.configure initialised before i18n.init. I just not wanted to copy here the entire thing:

i18n.configure({
  locales: ['en', 'hu'],
  fallbacks: { en: 'hu' },
  defaultLocale: 'en',
  queryParameter: 'lang',
  directory: path.join(__dirname, '/locales'),
  directoryPermissions: '755',
  autoReload: true,
  updateFiles: true,
  objectNotation: false,
  api: {
    __: '__',
    __n: '__n',
  },
});
app.use(i18n.init);

LantosIstvan avatar Oct 26 '16 16:10 LantosIstvan

I think this is related: https://github.com/mashpie/i18n-node/issues/216

I also want on my default routes like / only load the defaultLocale.

LantosIstvan avatar Oct 26 '16 17:10 LantosIstvan

ok, next how does your reqobject look like in differrent routes, compared to that one documented in https://github.com/mashpie/i18n-node#i18ninit

And why are you explicitly ommit res in i18n.setLocale([req, resLocals], paramsLang); which will result in "no res object knows the current locale set here" and might lead to display en translations only.

mashpie avatar Oct 26 '16 17:10 mashpie

Just to sort out: You want:

/hu/... => should be setLocale('hu)

anything else:

/home => setLocale('en)
/contact => setLocale('en)

plus if I hit any "en" route with "hu" browser it should redirect to /hu/<request_uri>

mashpie avatar Oct 26 '16 17:10 mashpie

Correct. I want something like that.

The routes without any /en/* or /hu/*, like / or /blog always return english. If someone hit an /en/*route it shouldn't be redirected to /hu/*, only if he hit /*.

I copy here every related code in the order they presented in my app:

const express = require('express');
const bodyParser = require('body-parser');
const methodOverride = require('method-override');
const i18n = require('i18n');

const index = require('./routes/index');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('_method'));

i18n.configure({
  locales: ['en', 'hu'],
  fallbacks: { en: 'hu' },
  defaultLocale: 'en',
  queryParameter: 'lang',
  directory: path.join(__dirname, '/locales'),
  directoryPermissions: '755',
  autoReload: true,
  updateFiles: true,
  objectNotation: false,
  api: {
    __: '__',
    __n: '__n',
  },
});
app.use(i18n.init);

const langRouter = (req, res, next) => {
  if (/^(en|hu)$/.exec(req.params.lang)) {
    i18n.setLocale([req, res.locals], req.params.lang);
    res.locals.language = `/${req.params.lang}`;
  }
  next();
};
app.all('/:lang/*', langRouter);
app.use('/:lang', langRouter);

app.use('/hu', index);
app.use('/', (req, res, next) => {
  if (req.headers['accept-language'] === 'hu') {
    return res.status(302).redirect('/hu');
  }
  return next();
});
app.use('/', index);

I changed back req.params and req.locals. The reason was that airbnb javascript linter complained about no-param-reassign.

LantosIstvan avatar Oct 26 '16 17:10 LantosIstvan

ok, let me take some time to code up a working example

mashpie avatar Oct 26 '16 17:10 mashpie

Thank You!

LantosIstvan avatar Oct 26 '16 17:10 LantosIstvan

Hi, did you find out how to achieve this?. I am also looking for it.

I want:

/hu/... => should be setLocale('hu)

anything else:

/home => setLocale('en)
/contact => setLocale('en)

plus if I hit any "en" route with "hu" browser it should redirect to /hu/<request_uri>

mrrovot avatar Oct 04 '18 01:10 mrrovot

In the last 2 years? Honestly, I haven't used i18n-node at all, moreover, I moved to API design.

In the basic, yes, I wanted something similar.

LantosIstvan avatar Oct 04 '18 09:10 LantosIstvan

maybe @mashpie

mrrovot avatar Oct 04 '18 18:10 mrrovot