i18next/i18next-express-middleware

Language selection not persisting

boulepick opened this issue · 2 comments

Good day to you all, i start by saying great ecosystem and great work.

I'm having a bit of issue with the language detection plugin, i'm using node.js express.js with mongoDB.

here is my setup:

const i18next = require('i18next');
const i18nextMiddleware = require('i18next-express-middleware');
const FsBackend = require('i18next-node-fs-backend');

i18next
	.use(i18nextMiddleware.LanguageDetector)
	.use(FsBackend)
	.init(
		{
	    //ignoreRoutes: ['images/', 'public/', 'css/', 'js/'], // avoid some routes from beeing handled (detect lng, set cookie,...)
	lowerCaseLng: true,
	    //preload: languages_whitelist,
	    debug: false,
	    whitelist : languages_whitelist,
	    ns: ["nav", "common"],
	    defaultNS: 'common',
	    load: 'unspecific',
	    fallbackLng : 'en',
            saveMissing:true,
	    appendNamespaceToMissingKey:true,

	    detection: {
	    	//order and from where user language should be detected
	      order: ['header', 'querystring', 'cookie', 'session', 'path', 'localStorage'],
	      //keys or params to lookup language from
	      lookupQuerystring: 'lng',
	      lookupCookie: 'i18n',
	      lookupSession: 'lng',
	      lookupPath: 'lng',
	      lookupFromPathIndex: 0,
	      lookupLocalStorage: 'lng',
	      //cache user language on
	      caches: false, //['localStorage','cookie'],
	      // optional expire and domain for set cookie
	      cookieExpirationDate: new Date().getTime() + 1000 * 60 * 60 * 24 * 365,
	      //cookieMinutes: 365*24*60, // 1 year
	      cookieDomain: 'www.mysite.com'
	    },
	    backend: {
	      // path where resources get loaded from
	      loadPath: path.join(__dirname,"/locales/{{ns}}/{{lng}}.json"),

	      // path to post missing resources
	      addPath: path.join(__dirname,"/locales/{{ns}}/{{lng}}.missing.json"),

	      // jsonIndent to use when storing json files
	      jsonIndent: 4
	    },
	    cache : {
	      // turn on or off
	      enabled: true, // prefix for stored languages
	      prefix: 'i18next_res_',
	      expirationTime: 1*24*60*60*1000 // expiration
	    }
	  }
	);

now in my route i have for example when the user is changing the language

  router.get('/login/:lang', (req, res) => {

    console.log(req.headers['accept-language']); // en-US,en;q=0.8,fr-FR;q=0.6
    console.log(req.i18n.language); // en

   req.i18n.changeLanguage(req.params.lang);
   req.i18n.loadNamespaces("login", function(e){
     var title = req.t('login:pageTitle');
     res.render('login');
  });

now this works find when the user changes the language and it renders the new page in the language chosen. howerver with a subsequent request for example now to login with a post, the language defaults back to en and do not keep the chosen language.

  //--- login user
  router.post('/login', (req, res, next) => {

    console.log(req.i18n.language); // still default language en
    console.log(req.headers['accept-language']); // en-US,en;q=0.8,fr-FR;q=0.6
     
    req.i18n.loadNamespaces("home", function(e){
      // this is rendered in english and not the chosen language
     })
    ......................
     .................

})

is this a bug or am i doing something wrong here

thank you for your input

has todo with detection order:

detection: {
	    	//order and from where user language should be detected
	      order: ['header', 'querystring', 'cookie', 'session', 'path', 'localStorage'],

...

             caches: false, //['localStorage','cookie'],

here on each subsequent request the header is first to be looked up. Further caches are set to false - so there is no mechanic to persist lng over multiple requests (beside that there is no localStorage detector on serverside). Use session or cookie.

Thanks for the quick answer, i change my setup as per your suggestions and it works. you are the best.

i18next
	.use(i18nextMiddleware.LanguageDetector)
	.use(FsBackend)
	.init(
		{
			debug: false,
	    ignoreRoutes: ['images/', 'public/', 'css/', 'js/'], // avoid some routes from beeing handled (detect lng, set cookie,...)
			lowerCaseLng: true,
	    whitelist : languages_whitelist,
	    ns: ["nav", "common"],
	    defaultNS: 'common',
	    load: 'unspecific',
	    fallbackLng : 'en',
            saveMissing:	true,
	    appendNamespaceToMissingKey:	true,

	    detection: {
	    	//order and from where user language should be detected
	      order: ['session', 'cookie'],

	      lookupCookie: 'i18n',
	      lookupSession: 'lng',

	      //cache user language on
	      caches: ['session', 'cookie'],
	      cookieMinutes: 365*24*60, // 1 year
	      cookieDomain: 'www.mysite.com'
	    },
	    backend: {
	      // path where resources get loaded from
	      loadPath: path.join(__dirname,"/locales/{{ns}}/{{lng}}.json"),
	      // path to post missing resources
	      addPath: path.join(__dirname,"/locales/{{ns}}/{{lng}}.missing.json"),
	      // jsonIndent to use when storing json files
	      jsonIndent: 4
	    },
	    cache : {
	      enabled: true, // prefix for stored languages
	      prefix: 'i18next_res_',
	      expirationTime: 1*24*60*60*1000 // expiration
	    }
	  }
	);