From e4ca27a7e11d4b49f44a341d87a288f74772b0f1 Mon Sep 17 00:00:00 2001 From: Dominik Hebeler <dominik@hebeler.club> Date: Thu, 13 Jul 2023 10:54:29 +0200 Subject: [PATCH] smarter language detection --- pass/app.js | 14 ++++++++++---- pass/app/Langdetector.js | 36 +++++++++++++++++++++++++++--------- pass/package-lock.json | 24 ++++++++++++++++++++++++ pass/package.json | 3 ++- 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/pass/app.js b/pass/app.js index 6b8e705..f524bb6 100644 --- a/pass/app.js +++ b/pass/app.js @@ -15,9 +15,10 @@ const i18nextmiddleware = require("i18next-http-middleware"); const mglangdetector = require("./app/Langdetector"); const langdetector = new i18nextmiddleware.LanguageDetector(); langdetector.addDetector(mglangdetector); + let ns = []; -readdirSync(path.join(__dirname, "lang", "de")).forEach((fileName) => { - const joinedPath = path.join(path.join(__dirname, "lang", "de"), fileName); +readdirSync(path.join(__dirname, "lang", "en")).forEach((fileName) => { + const joinedPath = path.join(path.join(__dirname, "lang", "en"), fileName); if (!lstatSync(joinedPath).isDirectory()) { ns.push(fileName.replace(".json", "")); } @@ -36,7 +37,12 @@ i18next debug: false, // Lang Detector Options detection: { - order: ["mg_detection"], + order: ["cookie", "mg_detection"], + lookupCookie: "web_setting_m", + lookupFromPathIndex: 0, + convertDetectedLanguage: (lng) => { + return lng.replace("_", "-"); + } }, // FS Backend Options backend: { @@ -45,7 +51,7 @@ i18next }, ns: ns, defaultNS: "index", - fallbackLng: "de", + fallbackLng: "en", initImmediate: false, preload: readdirSync(path.join(__dirname, "lang")).filter((fileName) => { const joinedPath = path.join(path.join(__dirname, "lang"), fileName); diff --git a/pass/app/Langdetector.js b/pass/app/Langdetector.js index 3ca040a..04bc7b6 100644 --- a/pass/app/Langdetector.js +++ b/pass/app/Langdetector.js @@ -1,19 +1,37 @@ module.exports = { name: 'mg_detection', lookup: (req, res, options) => { - let language = 'de'; - - if (req.hostname === "metager.org") { - language = 'en'; + // Cookie is checked at this point + // Next detection in order is the request path + let path = req.path.replace(/^\/+/, "").replace(/\/+$/, "").split("/"); + let path_matches = path[0].match(/^([a-z]{2})-([A-Z]{2})/); + if (path.length > 0 && path_matches) { + let path_tool = require("path"); + let fs = require("fs"); + let lang_folder = path_tool.join(__dirname, "../lang", path[0]); + // Check if translation exists for full locale + if (fs.existsSync(lang_folder)) { + return path[0]; + } + // Check if translation exists for language part of locale + lang_folder = path_tool.join(__dirname, "../lang", path_matches[1]); + if (fs.existsSync(lang_folder)) { + return path[0]; + } } - let localePathMatches = req.path.match(/^\/(en|de)(\-[a-zA-Z]{2})?/); - if (localePathMatches) { - language = localePathMatches[1]; + // If the path does not match we'll try to guess a locale based on Accept-Language header + let acceptLanguage = require("accept-language"); + acceptLanguage.languages([null, "de-DE", "de-AT", "de-CH", "de", "en-GB", "en-UK", "en-IE", "en-US", "en", "es-ES", "es-MX", "es"]); + let guessed_lang = acceptLanguage.get(req.headers["accept-language"]); + if (guessed_lang) { + return guessed_lang; } - if (language !== "en" && req.path.match(/^\/(ie|uk)/)) { - language = "en"; + // If all prior checks failed we'll use the default depending on the current domain + let language = 'en'; + if (req.hostname === "metager.de") { + language = 'de'; } return language; }, diff --git a/pass/package-lock.json b/pass/package-lock.json index c542ff3..2aefae8 100644 --- a/pass/package-lock.json +++ b/pass/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@paypal/paypal-js": "^5.1.1", + "accept-language": "^3.0.18", "blind-signatures": "^1.0.7", "browserify-middleware": "^8.1.1", "concat-stream": "^2.0.0", @@ -581,6 +582,15 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/accept-language": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/accept-language/-/accept-language-3.0.18.tgz", + "integrity": "sha512-sUofgqBPzgfcF20sPoBYGQ1IhQLt2LSkxTnlQSuLF3n5gPEqd5AimbvOvHEi0T1kLMiGVqPWzI5a9OteBRth3A==", + "dependencies": { + "bcp47": "^1.1.2", + "stable": "^0.1.6" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -929,6 +939,14 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/bcp47": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bcp47/-/bcp47-1.1.2.tgz", + "integrity": "sha512-JnkkL4GUpOvvanH9AZPX38CxhiLsXMBicBY2IAtqiVN8YulGDQybUydWA4W6yAMtw6iShtw+8HEF6cfrTHU+UQ==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -6757,6 +6775,12 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "optional": true }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", diff --git a/pass/package.json b/pass/package.json index 9423e28..3d0c449 100644 --- a/pass/package.json +++ b/pass/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@paypal/paypal-js": "^5.1.1", + "accept-language": "^3.0.18", "blind-signatures": "^1.0.7", "browserify-middleware": "^8.1.1", "concat-stream": "^2.0.0", @@ -44,4 +45,4 @@ "devDependencies": { "nodemon": "^2.0.20" } -} \ No newline at end of file +} -- GitLab