class Localization { constructor() { Localization.defaultLocale = "en"; Localization.supportedLocales = ["en"]; Localization.translations = {}; Localization.defaultTranslations = {}; const initialLocale = Localization.supportedOrDefault(Localization.browserLocales()); Localization.setLocale(initialLocale) .then(_ => { Localization.translatePage(); }) } static isSupported(locale) { return Localization.supportedLocales.indexOf(locale) > -1; } static supportedOrDefault(locales) { return locales.find(Localization.isSupported) || Localization.defaultLocale; } static browserLocales() { return navigator.languages.map(locale => locale.split("-")[0] ); } static async setLocale(newLocale) { if (newLocale === Localization.locale) return false; const firstTranslation = !Localization.locale Localization.defaultTranslations = await Localization.fetchTranslationsFor(Localization.defaultLocale); const newTranslations = await Localization.fetchTranslationsFor(newLocale); if(!newTranslations) return false; Localization.locale = newLocale; Localization.translations = newTranslations; if (firstTranslation) { Events.fire("translation-loaded"); } } static async fetchTranslationsFor(newLocale) { const response = await fetch(`lang/${newLocale}.json`) if (response.redirected === true || response.status !== 200) return false; return await response.json(); } static translatePage() { document .querySelectorAll("[data-i18n-key]") .forEach(element => Localization.translateElement(element)); } static async translateElement(element) { const key = element.getAttribute("data-i18n-key"); const attrs = element.getAttribute("data-i18n-attrs").split(" "); for (let i in attrs) { let attr = attrs[i]; if (attr === "text") { element.innerText = Localization.getTranslation(key); } else { element.attr = Localization.getTranslation(key, attr); } } } static getTranslation(key, attr, data, useDefault=false) { const keys = key.split("."); let translationCandidates = useDefault ? Localization.defaultTranslations : Localization.translations; for (let i=0; i