globalThis.Wegwichtel ??= {}; (function (ns) { 'use strict'; class WegwichtelI18n { 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 })); } static setLanguage(language, root = globalThis.document) { const requested = String(language).toLowerCase(); const base = requested.split('-')[0]; this.#language = this.#fallbackLanguage; if (this.#languages.has(base)) this.#language = base; if (this.#languages.has(requested)) this.#language = requested; this.apply(root); return this.#language; } static t(key, variables = {}) { 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.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 (element.dataset?.i18n) element.textContent = this.t(element.dataset.i18n); } for (const [attribute, key] of [['title', 'i18nTitle'], ['aria-label', 'i18nAriaLabel'], ['placeholder', 'i18nPlaceholder'], ['alt', 'i18nAlt']]) { for (const element of root.querySelectorAll(`[data-i18n-${attribute}]`)) { if (element.dataset?.[key] && typeof element.setAttribute === 'function') element.setAttribute(attribute, this.t(element.dataset[key])); } } } } ns.I18n = WegwichtelI18n; WegwichtelI18n.setLanguage(WegwichtelI18n.detectLanguage()); }(globalThis.Wegwichtel));