fix sonar findings and translation structure
This commit is contained in:
+31
-9
@@ -3,11 +3,22 @@ globalThis.Wegwichtel ??= {};
|
||||
'use strict';
|
||||
|
||||
class WegwichtelI18n {
|
||||
static #languages = new Map([['de', ns.TextsDe.messages]]);
|
||||
static #language = 'de';
|
||||
static #languages = new Map(ns.TextCatalogs);
|
||||
static #fallbackLanguage = this.#languages.keys().next().value;
|
||||
static #language = this.#fallbackLanguage;
|
||||
|
||||
static get language() { return this.#language; }
|
||||
|
||||
static detectLanguage(preferences = globalThis.navigator?.languages ?? [globalThis.navigator?.language]) {
|
||||
for (const language of preferences) {
|
||||
const requested = String(language ?? '').toLowerCase();
|
||||
if (this.#languages.has(requested)) return requested;
|
||||
const base = requested.split('-')[0];
|
||||
if (this.#languages.has(base)) return base;
|
||||
}
|
||||
return this.#fallbackLanguage;
|
||||
}
|
||||
|
||||
static register(language, messages) {
|
||||
this.#languages.set(language.toLowerCase(), Object.freeze({ ...messages }));
|
||||
}
|
||||
@@ -15,7 +26,7 @@ globalThis.Wegwichtel ??= {};
|
||||
static setLanguage(language, root = globalThis.document) {
|
||||
const requested = String(language).toLowerCase();
|
||||
const base = requested.split('-')[0];
|
||||
this.#language = 'de';
|
||||
this.#language = this.#fallbackLanguage;
|
||||
if (this.#languages.has(base)) this.#language = base;
|
||||
if (this.#languages.has(requested)) this.#language = requested;
|
||||
this.apply(root);
|
||||
@@ -23,32 +34,43 @@ globalThis.Wegwichtel ??= {};
|
||||
}
|
||||
|
||||
static t(key, variables = {}) {
|
||||
let value = this.#languages.get(this.#language)?.[key] ?? ns.TextsDe.messages[key];
|
||||
let value = this.#lookup(this.#languages.get(this.#language), key)
|
||||
?? this.#lookup(this.#languages.get(this.#fallbackLanguage), key);
|
||||
if (value == null) throw new RangeError(`Missing translation: ${key}`);
|
||||
if (typeof value === 'object') {
|
||||
const plural = new Intl.PluralRules(this.#language).select(Number(variables.count));
|
||||
value = value[plural] ?? value.other;
|
||||
}
|
||||
return value.replace(/\{([a-zA-Z0-9_]+)\}/g, (placeholder, name) => {
|
||||
return value.replaceAll(/\{(\w+)\}/g, (placeholder, name) => {
|
||||
if (!Object.hasOwn(variables, name)) return placeholder;
|
||||
return String(variables[name] ?? '');
|
||||
});
|
||||
}
|
||||
|
||||
static #lookup(catalog, key) {
|
||||
if (Object.hasOwn(catalog, key)) return catalog[key];
|
||||
let value = catalog;
|
||||
for (const part of key.split('.')) {
|
||||
if (!value || !Object.hasOwn(value, part)) return undefined;
|
||||
value = value[part];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static apply(root = globalThis.document) {
|
||||
if (!root?.querySelectorAll) return;
|
||||
if (root.documentElement) root.documentElement.lang = this.#language;
|
||||
for (const element of root.querySelectorAll('[data-i18n]')) {
|
||||
if (typeof element.getAttribute === 'function') element.textContent = this.t(element.getAttribute('data-i18n'));
|
||||
if (element.dataset?.i18n) element.textContent = this.t(element.dataset.i18n);
|
||||
}
|
||||
for (const attribute of ['title', 'aria-label', 'placeholder', 'alt']) {
|
||||
for (const [attribute, key] of [['title', 'i18nTitle'], ['aria-label', 'i18nAriaLabel'], ['placeholder', 'i18nPlaceholder'], ['alt', 'i18nAlt']]) {
|
||||
for (const element of root.querySelectorAll(`[data-i18n-${attribute}]`)) {
|
||||
if (typeof element.getAttribute === 'function' && typeof element.setAttribute === 'function') element.setAttribute(attribute, this.t(element.getAttribute(`data-i18n-${attribute}`)));
|
||||
if (element.dataset?.[key] && typeof element.setAttribute === 'function') element.setAttribute(attribute, this.t(element.dataset[key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ns.I18n = WegwichtelI18n;
|
||||
WegwichtelI18n.apply();
|
||||
WegwichtelI18n.setLanguage(WegwichtelI18n.detectLanguage());
|
||||
}(globalThis.Wegwichtel));
|
||||
|
||||
Reference in New Issue
Block a user