i18next / i18next-express-middleware

[deprecated] can be replaced with i18next-http-middleware
https://github.com/i18next/i18next-http-middleware
MIT License
206 stars 52 forks source link

Example of i18next-express-middleware with i18next-node-remote-backend #112

Closed adyz closed 8 years ago

adyz commented 8 years ago

I tried this:

var i18next = require('i18next');
var middleware = require('i18next-express-middleware');
var backend = require('i18next-node-remote-backend');

i18next
    .use(middleware.LanguageDetector)
    .use(backend)
    .init({
        debug: false,
        detection: {
            order: ['querystring', 'cookie']
        },
        backend: {
            loadPath: 'http://example.com/translate?language={{lng}}',
            crossDomain: true
        }

    });

and it does not seem to fetch the resource when I access the http://localhosst:3000/?lng=en

If I pass the lng manually to the init options, it fetches the desired language passed to this variable, but I'd like to init the language bases on a variable like query param or cookie.

jamuhl commented 8 years ago

you don't have to init with a specific language on a webserver. think of it - every request comes from a different user with possible different language. If you set language globally you can cause errors by using the wrong language as a user two changes language during user ones request (async nature of node).

You basically should preload all the languages you support on server using the preload option on init (array of languages you want to load).

adyz commented 8 years ago

This is the way I did it, for anybody looking for a way to do this:

var i18next = require('i18next');
var middleware = require('i18next-express-middleware');
var backend = require('i18next-node-remote-backend');

i18next
    .use(middleware.LanguageDetector)
    .use(backend)
    .init({
        lngs: ['ro', 'bg', 'hu', 'hr', 'pl', 'sl', 'sk', 'cz'],
        debug: false,
        fallbackLng: false,
        backend: {
            loadPath: 'http://example.com/translate?language={{lng}}',
            crossDomain: true
        }
    });

app.use(function (req, res, next) {

    i18next.changeLanguage(req.query.lng);
    next();
});

Thank you for your help!

adyz commented 8 years ago

I guess I don't even need the express middleware now...

jamuhl commented 8 years ago

you don't need the stuff you did:

like explained

app.use(function (req, res, next) {

    i18next.changeLanguage(req.query.lng);
    next();
});

does not work as it sets language globally to a singleton....that is not save to use in node. Requests are handled async - so it's not save. Only storing the lng on request and a) accessing t function by passing lng or b) creating a clone instance of i18next per request is!!!

you really should use the middleware.handle:

var i18next = require('i18next');
var middleware = require('i18next-express-middleware');
var express = require('express');

i18next
  .use(middleware.LanguageDetector)
  .init(i18nextOptions);

var app = express();
app.use(middleware.handle(i18next, {
  ignoreRoutes: ["/foo"],
  removeLngFromUrl: false
}));

or don't be surprised if you get wrong translations as a unexpected behaviour...

recommend reading http://ejohn.org/blog/a-strategy-for-i18n-and-node/ section i18n logic to understand the problem...

adyz commented 8 years ago

Thanks for all the help, you are right!