const osLocale = require("os-locale"); const fs = require("fs"); const path = require("path"); let cache = { defaultLocale: "en", availableLocales: [], canonicalLocales: [], locales: [] }; let i18n = {}; i18n.__ = function(name) { i18n.getLocale(); let string = i18n.getLocaleData(cache.locale)[name] || i18n.getLocaleData(cache.defaultLocale)[name]; if (!string) { let underscoreIndex = cache.locale.indexOf("_"); if (underscoreIndex !== -1) { let localeBaseCode = cache.locale.substring(0, underscoreIndex); if (i18n.localeExists(localeBaseCode)) { string = i18n.getLocaleData(localeBaseCode)[name]; } } } if (string) { if (arguments.length === 1) { return string; } else { for (let i = 0, l = arguments.length - 1; i < l; i++) { string = string.replace("$" + i, arguments[1 + i]); } return string; } } else { console.warn(`String "${name}" does not exist.`) } }; i18n.localeExists = function(locale) { return i18n.getAvailableLocales().indexOf(locale) !== -1; }; i18n.getLocaleData = function(locale) { if (!cache.locales[locale]) { cache.locales[locale] = i18n.readLocaleFile(locale); } return cache.locales[locale]; }; i18n.readLocaleFile = function(locale) { let localeData = JSON.parse(fs.readFileSync( path.join(__dirname, "..", "locales", locale + ".json"), { encoding: "utf8" } )); if (localeData.__redirect__) { let redirectedLocaleData = JSON.parse(fs.readFileSync( path.join(__dirname, "..", "locales", localeData.__redirect__ + ".json"), { encoding: "utf8" } )); redirectedLocaleData.__is_redirected__ = true; redirectedLocaleData.__canonical__ = localeData.__redirect__; return redirectedLocaleData; } else { return localeData; } }; i18n.doDOMReplacement = function() { let elems0 = document.getElementsByClassName("i18n"); for (let i = 0, l = elems0.length; i < l; i++) { elems0[i].innerHTML = i18n.__(elems0[i].dataset.i18nName); } let elems1 = document.getElementsByClassName("i18n-attr"); for (let i = 0, l = elems1.length; i < l; i++) { let mappings = elems1[i].dataset.i18nMap.split(";"); for (let j = 0, m = mappings.length; j < m; j++) { let keyVal = mappings[j].split(":"); elems1[i].setAttribute(keyVal[0], i18n.__(keyVal[1])); } } }; i18n.setLocale = function(locale) { if (i18n.localeExists(locale)) { cache.locale = locale; return true; } return false; }; i18n.getLocale = function() { if (!cache.locale) { let systemLocale = osLocale.sync(); let availableLocales = i18n.getAvailableLocales(); if (availableLocales.indexOf(systemLocale) !== -1) { cache.locale = systemLocale; } else if (availableLocales.indexOf(systemLocale.split("_")[0]) !== -1) { cache.locale = systemLocale.split("_")[0]; } else { var looseLocaleMatch; for (let i = 0, l = availableLocales.length; i < l; i++) { if (availableLocales[i].split("_")[0] === systemLocale.split("_")[0]) { looseLocaleMatch = availableLocales[i]; break; } } if (looseLocaleMatch) { cache.locale = looseLocaleMatch; } else { cache.locale = cache.defaultLocale; } } } return cache.locale; }; i18n.getCanonicalLocale = function() { i18n.getLocale(); if (!cache.locales[cache.locale]) { cache.locales[cache.locale] = i18n.readLocaleFile(cache.locale); } if (cache.locales[cache.locale].__canonical__) { return cache.locales[cache.locale].__canonical__; } else { return cache.locale; } }; i18n.getAvailableLocales = function(canonicalOnly) { if (!cache.availableLocales.length) { let filenames = fs.readdirSync(path.join(__dirname, "..", "locales")); for (let i = 0, l = filenames.length; i < l; i++) { cache.availableLocales.push(filenames[i].split(".")[0]); } } if (canonicalOnly) { return i18n.getCanonicalLocales(); } else { return cache.availableLocales; } }; i18n.getCanonicalLocales = function() { i18n.getAvailableLocales(); if (!cache.canonicalLocales.length) { for (let i = 0, l = cache.availableLocales.length; i < l; i++) { if (!i18n.readLocaleFile(cache.availableLocales[i]).hasOwnProperty("__is_redirected__")) { cache.canonicalLocales.push(cache.availableLocales[i]); } } } return cache.canonicalLocales; }; i18n.getDefaultLocale = function() { return cache.defaultLocale; }; module.exports = i18n;