PairDrop/public_included_ws_fallback/scripts/localization.js

115 lines
3.6 KiB
JavaScript
Raw Normal View History

2023-07-06 21:29:36 +02:00
class Localization {
constructor() {
Localization.defaultLocale = "en";
Localization.supportedLocales = ["en"];
Localization.translations = {};
Localization.defaultTranslations = {};
2023-07-06 21:29:36 +02:00
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
2023-07-06 21:29:36 +02:00
Localization.defaultTranslations = await Localization.fetchTranslationsFor(Localization.defaultLocale);
2023-07-06 21:29:36 +02:00
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);
2023-07-06 21:29:36 +02:00
} else {
element.attr = Localization.getTranslation(key, attr);
2023-07-06 21:29:36 +02:00
}
}
}
static getTranslation(key, attr, data, useDefault=false) {
2023-07-06 21:29:36 +02:00
const keys = key.split(".");
let translationCandidates = useDefault
? Localization.defaultTranslations
: Localization.translations;
2023-07-06 21:29:36 +02:00
for (let i=0; i<keys.length-1; i++) {
translationCandidates = translationCandidates[keys[i]]
}
let lastKey = keys[keys.length-1];
if (attr) lastKey += "_" + attr;
let translation = translationCandidates[lastKey];
for (let j in data) {
translation = translation.replace(`{{${j}}}`, data[j]);
}
if (!translation) {
if (!useDefault) {
translation = this.getTranslation(key, attr, data, true);
console.warn(`Missing translation entry for your language ${Localization.locale.toUpperCase()}. Using ${Localization.defaultLocale.toUpperCase()} instead.`, key, attr);
console.warn("Help translating PairDrop: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/");
} else {
console.warn("Missing translation in default language:", key, attr);
}
2023-07-06 21:29:36 +02:00
}
return Localization.escapeHTML(translation);
}
static escapeHTML(unsafeText) {
let div = document.createElement('div');
div.innerText = unsafeText;
return div.innerHTML;
}
}