From e9b8e403daf7373e11b29fd56096bf77dfabe223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pol=C3=A1k?= <456647@muni.cz> Date: Sun, 17 Sep 2023 15:08:42 +0200 Subject: [PATCH] Initial draft of i18n API --- bundle.js | 1 + site/i18n.js | 71 ++++++++++++++++++++++++++++++++++++++++++++ site/index.js | 13 ++++++++ site/locales/cs.json | 0 site/locales/de.json | 0 site/locales/en.json | 0 6 files changed, 85 insertions(+) create mode 100755 site/i18n.js create mode 100755 site/locales/cs.json create mode 100755 site/locales/de.json create mode 100755 site/locales/en.json diff --git a/bundle.js b/bundle.js index 76af6a0..b33f61f 100755 --- a/bundle.js +++ b/bundle.js @@ -23,6 +23,7 @@ function replaceFileContents(string, fileDir) { const pattern = /%%([^%]+)%%|\/\/\s*include\s*"([^"]+)"/g; return string.replace(pattern, (_, filename1, filename2) => { + if (filename2 != null) console.error("include is used!!!!!"); const filename = filename1 || filename2; const filenamePath = path.join(fileDir, filename); try { diff --git a/site/i18n.js b/site/i18n.js new file mode 100755 index 0000000..ee2e330 --- /dev/null +++ b/site/i18n.js @@ -0,0 +1,71 @@ +// Internationalization support +// This file is used both serverside and clientside. + +/** + * Supported languages and their translations. + * Each file contains an object with key-value pairs. + * + * Argument substitution is supported through named arguments: translate("Hello {{name}}", {name: "World"}) + * + * Plurals and arrays are currently not supported. + * + * If the key is missing in the current localization, it falls back to default localization + * and then to treating the key itself as the localization. + */ + +const translations = { + cs: require("./locales/cs.json"), + de: require("./locales/de.json"), + en: require("./locales/en.json"), +}; +/** + * @type {string[]} + */ +const locales = Object.keys(locales); +const defaultLocale = "de"; + +/** The currently selected locale. */ +var currentLocale = defaultLocale; + +/** + * Set the globally used locale. + * Expects a 2 character language code string, one from locales. + */ +function setLocale(locale) { + if (Object.hasOwn(locales, locale)) { + currentLocale = locale; + return true; + } + console.error("Attempted to setLocale to unsupported language: ", locale); + return false; +} + +/** + * @param {string} key to translate + * @param {Object?} args arguments to substitute into the translated key + * @returns translated string + */ +function translate(key, args) { + let translation = locales[currentLocale][key]; + if (translation === undefined) { + console.error("Untranslated key in ", currentLocale, ": ", key); + if (currentLocale != defaultLocale) { + translation = locales[defaultLocale][key] || key; + } else { + translation = key; + } + } + + if (typeof args === "object") { + // Do argument substitution + for (const arg in args) { + translation = translation.replaceAll("{{" + arg + "}}", args[arg]); + } + } + + return translation; +} + +exports.setLocale = setLocale; +exports.locales = locales; +exports.translate = translate; diff --git a/site/index.js b/site/index.js index db47adf..b2315ec 100644 --- a/site/index.js +++ b/site/index.js @@ -6,11 +6,24 @@ const { STORE_KEYS } = require("./model/stores"); const { ProgressBar } = require("./views/progress-bar"); const progressBar = new ProgressBar(STORE_KEYS.length); +const i18n = require("./i18n"); + (async () => { if (location.href.includes("heissepreise.github.io")) { location.href = "https://heisse-preise.io"; } + // Find the most preferred supported language + for (const langCode in navigator.languages) { + // We don't do regional codes, so take just the language code + let lang = langCode.length >= 2 ? langCode.substring(0, 2) : null; + if (lang == null) continue; + if (i18n.locales.indexOf(lang) != -1) { + i18n.setLocale(lang); + break; + } + } + await model.load(() => progressBar.addStep()); const itemsFilter = document.querySelector("items-filter"); const itemsList = document.querySelector("items-list"); diff --git a/site/locales/cs.json b/site/locales/cs.json new file mode 100755 index 0000000..e69de29 diff --git a/site/locales/de.json b/site/locales/de.json new file mode 100755 index 0000000..e69de29 diff --git a/site/locales/en.json b/site/locales/en.json new file mode 100755 index 0000000..e69de29