diff --git a/bundle.js b/bundle.js index fbe5dc7..c33c3f1 100644 --- a/bundle.js +++ b/bundle.js @@ -4,7 +4,7 @@ const chokidar = require("chokidar"); const esbuild = require("esbuild"); const { exec } = require("child_process"); const { promisify } = require("util"); -const i18n = require("./site/i18n"); +const i18n = require("./i18n"); function deleteDirectory(directory) { if (fs.existsSync(directory)) { @@ -64,16 +64,18 @@ function processFile(inputFile, outputFile, filter) { const replacedData = replaceFileContents(data, path.dirname(inputFile), locale); if (locale == i18n.defaultLocale) { fs.writeFileSync(outputFile, replacedData); + console.log(`${inputFile} -> ${outputFile}`); } let pathWithLanguageCode = outputFile.substring(0, outputFile.length - extension.length) + "." + locale + extension; fs.writeFileSync(pathWithLanguageCode, replacedData); + console.log(`${inputFile} -> ${pathWithLanguageCode}`); } } else { const data = fs.readFileSync(inputFile); if (filter(inputFile, false, data)) return; fs.writeFileSync(outputFile, data); + console.log(`${inputFile} -> ${outputFile}`); } - console.log(`${inputFile} -> ${outputFile}`); } /** @@ -167,6 +169,7 @@ async function bundle(inputDir, outputDir, watch) { bundleHTML(inputDir, outputDir, false, watch, (filePath, isDir, data) => { if (isDir) return false; if (filePath.endsWith("style.css")) return true; + if (filePath.includes("/locales/")) return true; if (filePath.endsWith(".js") && !filePath.includes("socket.io.js")) return true; if (data.includes(`require("`)) return true; return false; diff --git a/site/i18n.js b/i18n.js similarity index 67% rename from site/i18n.js rename to i18n.js index 7930972..7427e13 100644 --- a/site/i18n.js +++ b/i18n.js @@ -29,38 +29,6 @@ const locales = Object.keys(translations); */ const defaultLocale = "de"; -/** - * The currently selected locale. - * @type {string} - */ -var currentLocale = defaultLocale; - -/** - * Set the globally used locale. - * Expects a 2 character language code string, one from locales. - * @param {string} locale - */ -function setLocale(locale) { - if (locales.includes(locale)) { - console.log("Locale changed to " + locale); - currentLocale = locale; - return true; - } - console.error("Attempted to setLocale to unsupported language: ", locale); - return false; -} - -/** - * Translates the key using the current global locale. - * - * @param {!string} key to translate - * @param {!Object.} [args] arguments to substitute into the translated key - * @returns {string} translated string - */ -function translate(key, args) { - return translateWithLocale(currentLocale, key, args); -} - /** * @param {!string} locale name of the language to use for translation, MUST be one of the supported languages * @param {!string} key to translate @@ -88,9 +56,6 @@ function translateWithLocale(locale, key, args) { return translation; } -exports.setLocale = setLocale; exports.defaultLocale = defaultLocale; exports.locales = locales; -exports.translate = translate; -exports.__ = translate; exports.translateWithLocale = translateWithLocale; diff --git a/site/locales/cs.json b/locales/cs.json similarity index 98% rename from site/locales/cs.json rename to locales/cs.json index 8cbd8d2..7c20ee3 100644 --- a/site/locales/cs.json +++ b/locales/cs.json @@ -78,8 +78,9 @@ "ItemsList_Name": "Název", "ItemsList_Preis": "Cena", - "Cart_Teilen": "Sdílet", + "Cart_Teilen": "Detail", "Cart_Speichern": "Uložit", + "Cart_Warenkorb {{name}}": "Nákupní košík {{name}}", "Cart_Warenkorb '{{name}}' existiert bereits. Bitte einen anderen Namen für den zu speichernden Warenkorb eingeben": "Nákupní košík '{{name}}' již existuje. Zadejte prosím jiný název", "Cart_Warenkorb '{{name}}' existiert nicht.": "Nákupní košík '{{name}}' neexistuje.", "Cart_Artikel": "Položka", diff --git a/site/locales/de.json b/locales/de.json similarity index 98% rename from site/locales/de.json rename to locales/de.json index 8db43b5..5ef9db8 100644 --- a/site/locales/de.json +++ b/locales/de.json @@ -80,6 +80,7 @@ "Cart_Teilen": "Teilen", "Cart_Speichern": "Speichern", + "Cart_Warenkorb {{name}}": "Warenkorb {{name}}", "Cart_Warenkorb '{{name}}' existiert bereits. Bitte einen anderen Namen für den zu speichernden Warenkorb eingeben": "Warenkorb '{{name}}' existiert bereits. Bitte einen anderen Namen für den zu speichernden Warenkorb eingeben", "Cart_Warenkorb '{{name}}' existiert nicht.": "Warenkorb '{{name}}' existiert nicht.", "Cart_Artikel": "Artikel", diff --git a/site/locales/en.json b/locales/en.json similarity index 98% rename from site/locales/en.json rename to locales/en.json index fd808cd..fa2d33c 100644 --- a/site/locales/en.json +++ b/locales/en.json @@ -78,8 +78,9 @@ "ItemsList_Name": "Name", "ItemsList_Preis": "Price", - "Cart_Teilen": "Share", + "Cart_Teilen": "Detail", "Cart_Speichern": "Save", + "Cart_Warenkorb {{name}}": "Shopping cart {{name}}", "Cart_Warenkorb '{{name}}' existiert bereits. Bitte einen anderen Namen für den zu speichernden Warenkorb eingeben": "Shopping cart '{{name}}' already exists. Please enter a different name for the shopping cart to be saved", "Cart_Warenkorb '{{name}}' existiert nicht.": "Shopping cart '{{name}}' does not exist.", "Cart_Artikel": "Item", diff --git a/server.js b/server.js index 4fe21d0..985fcd9 100644 --- a/server.js +++ b/server.js @@ -7,7 +7,7 @@ const csv = require("./site/js/misc"); const chokidar = require("chokidar"); const express = require("express"); const compression = require("compression"); -const i18n = require("./site/i18n"); +const i18n = require("./i18n"); function copyItemsToSite(dataDir) { const items = analysis.readJSON(`${dataDir}/latest-canonical.json.${analysis.FILE_COMPRESSOR}`); diff --git a/site/browser_i18n.js b/site/browser_i18n.js new file mode 100644 index 0000000..539e4a3 --- /dev/null +++ b/site/browser_i18n.js @@ -0,0 +1,46 @@ +const i18n = require("../i18n"); + +/** + * The currently selected locale. + * @type {?string} + */ +var currentLocale = i18n.defaultLocale; + +/** + * Set the globally used locale. + * Expects a 2 character language code string, one from locales. + * @param {string} locale + */ +function setLocale(locale) { + if (i18n.locales.includes(locale)) { + console.log("Locale changed to " + locale); + currentLocale = locale; + return true; + } + console.error("Attempted to setLocale to unsupported language: ", locale); + return false; +} + +/** + * Translates the key using the current global locale. + * + * @param {!string} key to translate + * @param {!Object.} [args] arguments to substitute into the translated key + * @returns {string} translated string + */ +function translate(key, args) { + return i18n.translateWithLocale(currentLocale, key, args); +} + +// Find the most preferred supported language +for (const langCode of 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.includes(lang)) { + setLocale(lang); + break; + } +} + +exports.__ = translate; diff --git a/site/cart.js b/site/cart.js index 85763aa..64253f6 100644 --- a/site/cart.js +++ b/site/cart.js @@ -6,7 +6,7 @@ const { STORE_KEYS, stores } = require("./model/stores"); require("./views"); const { ProgressBar } = require("./views/progress-bar"); const progressBar = new ProgressBar(STORE_KEYS.length); -const { __ } = require("./i18n"); +const { __ } = require("./browser_i18n"); let carts = null; diff --git a/site/carts.js b/site/carts.js index 50877a3..d137926 100644 --- a/site/carts.js +++ b/site/carts.js @@ -1,7 +1,7 @@ const { downloadJSON, today } = require("./js/misc"); const model = require("./model"); require("./views"); -const { __ } = require("./i18n"); +const { __ } = require("./browser_i18n"); const { STORE_KEYS } = require("./model/stores"); const { ProgressBar } = require("./views/progress-bar"); diff --git a/site/index.js b/site/index.js index dc4b4d3..f384e24 100644 --- a/site/index.js +++ b/site/index.js @@ -1,23 +1,8 @@ -const i18n = require("./i18n"); - -// Process redirects and localization before running anything else -(() => { - if (location.href.includes("heissepreise.github.io")) { - location.href = "https://heisse-preise.io"; - return; - } - - // Find the most preferred supported language - for (const langCode of 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.includes(lang)) { - i18n.setLocale(lang); - break; - } - } -})(); +// Process redirects before running anything else +if (location.href.includes("heissepreise.github.io")) { + location.href = "https://heisse-preise.io"; + return; +} const { getQueryParameter } = require("./js/misc"); const model = require("./model"); diff --git a/site/settings.js b/site/settings.js index 7dfe840..778007c 100644 --- a/site/settings.js +++ b/site/settings.js @@ -3,7 +3,7 @@ const { View } = require("./views/view"); const { Settings } = require("./model/settings"); require("./js/misc"); require("./views/custom-checkbox"); -const { __ } = require("./i18n"); +const { __ } = require("./browser_i18n"); class SettingsView extends View { constructor() { diff --git a/site/views/carts-list.js b/site/views/carts-list.js index 6f1735d..9ccfd6c 100644 --- a/site/views/carts-list.js +++ b/site/views/carts-list.js @@ -1,6 +1,6 @@ const { downloadJSON, dom } = require("../js/misc"); const { View } = require("./view"); -const { __ } = require("../i18n"); +const { __ } = require("../browser_i18n"); class CartsList extends View { constructor() { diff --git a/site/views/items-chart.js b/site/views/items-chart.js index 83c9dcb..3d5f2fe 100644 --- a/site/views/items-chart.js +++ b/site/views/items-chart.js @@ -1,7 +1,7 @@ const { STORE_KEYS } = require("../model/stores"); const { settings } = require("../model"); const { today, log, deltaTime, uniqueDates, calculateItemPriceTimeSeries } = require("../js/misc"); -const { __ } = require("../i18n"); +const { __ } = require("../browser_i18n"); const { View } = require("./view"); require("./custom-checkbox"); const moment = require("moment"); diff --git a/site/views/items-filter.js b/site/views/items-filter.js index c42f2a4..6c9377c 100644 --- a/site/views/items-filter.js +++ b/site/views/items-filter.js @@ -3,7 +3,7 @@ const { stores, STORE_KEYS, BUDGET_BRANDS } = require("../model/stores"); const { fromCategoryCode, categories } = require("../model/categories"); const { settings } = require("../model"); const { View } = require("./view"); -const { __ } = require("../i18n"); +const { __ } = require("../browser_i18n"); class ItemsFilter extends View { constructor() { diff --git a/site/views/items-list.js b/site/views/items-list.js index 551111d..84999d3 100644 --- a/site/views/items-list.js +++ b/site/views/items-list.js @@ -14,7 +14,7 @@ const { vectorizeItems, similaritySortItems } = require("../js/knn"); const { stores } = require("../model/stores"); const { View } = require("./view"); const { ItemsChart } = require("./items-chart"); -const { __ } = require("../i18n"); +const { __ } = require("../browser_i18n"); class ItemsList extends View { static priceTypeId = 0;