2018-02-06 23:31:18 +01:00
|
|
|
const { availableLanguages } = require('../../package.json');
|
|
|
|
const config = require('../config');
|
|
|
|
const fs = require('fs');
|
|
|
|
const path = require('path');
|
2019-07-30 00:26:11 +02:00
|
|
|
const { negotiateLanguages } = require('@fluent/langneg');
|
2018-02-06 23:31:18 +01:00
|
|
|
const langData = require('cldr-core/supplemental/likelySubtags.json');
|
2018-03-02 06:36:45 +01:00
|
|
|
|
|
|
|
// We return early in the middleware if the lang header is long.
|
|
|
|
// If that ever changes we should re-evaluate this regex.
|
|
|
|
// eslint-disable-next-line security/detect-unsafe-regex
|
2018-02-06 23:31:18 +01:00
|
|
|
const acceptLanguages = /(([a-zA-Z]+(-[a-zA-Z0-9]+){0,2})|\*)(;q=[0-1](\.[0-9]+)?)?/g;
|
|
|
|
|
|
|
|
function allLangs() {
|
2019-03-31 22:03:50 +02:00
|
|
|
return fs.readdirSync(path.join(__dirname, '..', '..', 'public', 'locales'));
|
2018-02-06 23:31:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const languages = config.l10n_dev ? allLangs() : availableLanguages;
|
|
|
|
|
|
|
|
module.exports = function(req, res, next) {
|
|
|
|
const header = req.headers['accept-language'] || 'en-US';
|
|
|
|
if (header.length > 255) {
|
|
|
|
req.language = 'en-US';
|
|
|
|
return next();
|
|
|
|
}
|
2019-03-13 19:30:24 +01:00
|
|
|
const langs = header.replace(/\s/g, '').match(acceptLanguages) || ['en-US'];
|
2018-02-06 23:31:18 +01:00
|
|
|
const preferred = langs
|
|
|
|
.map(l => {
|
|
|
|
const parts = l.split(';');
|
|
|
|
return {
|
|
|
|
locale: parts[0],
|
|
|
|
q: parts[1] ? parseFloat(parts[1].split('=')[1]) : 1
|
|
|
|
};
|
|
|
|
})
|
|
|
|
.sort((a, b) => b.q - a.q)
|
|
|
|
.map(x => x.locale);
|
|
|
|
req.language = negotiateLanguages(preferred, languages, {
|
|
|
|
strategy: 'lookup',
|
|
|
|
likelySubtags: langData.supplemental.likelySubtags,
|
|
|
|
defaultLocale: 'en-US'
|
|
|
|
})[0];
|
|
|
|
next();
|
|
|
|
};
|