Here is a solution that works for me. I wanted to site to be in Chinese by default. I also have 2 language change buttons in the navbar (flag images) that go to /en & /zh routes, which set the cookie and redirect the user back to the page they came from.
Tested it with incognito window and by clearing the cookie and refreshing the site. First load in ZH and language change works by adding/changing the cookie value.
I also had to init i18n BEFORE using req.setLocale() in my middleware.
const express = require('express');
const hbs = require('express-hbs');
const i18n = require('i18n');
const app = express();
const cookieParser = require('cookie-parser');
const indexRoutes = require('./routes/indexRoutes');
app.engine(
'hbs',
hbs.express4({
partialsDir: __dirname + '/views/partials/',
helpers: {
__: function () {
return i18n.__.apply(this, arguments);
},
__n: function () {
return i18n.__n.apply(this, arguments);
},
},
})
);
app.set('view engine', 'hbs');
app.use(express.json());
app.use(cookieParser());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
i18n.configure({
locales: ['zh', 'en'],
defaultLocale: 'zh',
cookie: 'locale',
directory: __dirname + '/locales',
directoryPermissions: '755',
autoReload: true,
updateFiles: true,
objectNotation: true,
api: {
__: '__', //now req.__ becomes req.__
__n: '__n', //and req.__n can be called as req.__n
},
});
app.use(i18n.init);
app.use((req, res, next) => {
if (req.cookies.locale === undefined) {
res.cookie('locale', 'zh', { maxAge: 900000, httpOnly: true });
req.setLocale('zh');
}
next();
});
app.get('/zh', (req, res) => {
res.cookie('locale', 'zh', { maxAge: 900000, httpOnly: true });
res.redirect('back');
});
app.get('/en', (req, res) => {
res.cookie('locale', 'en', { maxAge: 900000, httpOnly: true });
res.redirect('back');
});
app.use('/', indexRoutes);
app.listen(process.env.PORT || 3000, () =>
console.log(`Server up on ${process.env.PORT || 3000}`)
);