// i18n.js - Utilitaire de traduction pour Kimi APP class KimiI18nManager { constructor() { this.translations = {}; this.currentLang = "en"; this._reloadAttempted = false; } async setLanguage(lang) { this.currentLang = lang; await this.loadTranslations(lang); this.applyTranslations(); } async loadTranslations(lang) { try { const response = await fetch("kimi-locale/" + lang + ".json"); if (!response.ok) throw new Error("Translation file not found"); this.translations = await response.json(); this.currentLang = lang; } catch (e) { this.translations = {}; this.currentLang = "en"; } } t(key, params) { let str = this.translations[key] || key; if (params && typeof str === "string") { for (const [k, v] of Object.entries(params)) { str = str.replace(new RegExp(`{${k}}`, "g"), v); } } return str; } applyTranslations() { const missing = []; document.querySelectorAll("[data-i18n]").forEach(el => { const key = el.getAttribute("data-i18n"); let params = undefined; const paramsAttr = el.getAttribute("data-i18n-params"); if (paramsAttr) { try { params = JSON.parse(paramsAttr); } catch {} } const val = this.t(key, params); if (val === key && this.currentLang !== "en") { missing.push(key); } el.textContent = val; }); // Auto-reload once if new keys were added after initial load if (missing.length > 0 && !this._reloadAttempted) { this._reloadAttempted = true; this.loadTranslations(this.currentLang).then(() => { // Re-apply with fresh file requestAnimationFrame(() => this.applyTranslations()); }); } document.querySelectorAll("[data-i18n-title]").forEach(el => { const key = el.getAttribute("data-i18n-title"); el.setAttribute("title", this.t(key)); }); document.querySelectorAll("[data-i18n-placeholder]").forEach(el => { const key = el.getAttribute("data-i18n-placeholder"); el.setAttribute("placeholder", this.t(key)); }); if (document.title && this.translations["title"]) { document.title = this.translations["title"]; } } detectLanguage() { const nav = (navigator && (navigator.language || (navigator.languages && navigator.languages[0]))) || "en"; const short = String(nav).slice(0, 2).toLowerCase(); return ["en", "fr", "es", "de", "it", "ja", "zh"].includes(short) ? short : "en"; } } window.applyTranslations = function () { if (window.kimiI18nManager && typeof window.kimiI18nManager.applyTranslations === "function") { window.kimiI18nManager.applyTranslations(); } }; if (typeof document !== "undefined") { if (!window.kimiI18nManager) { window.kimiI18nManager = new KimiI18nManager(); } } window.KimiI18nManager = KimiI18nManager;