/** * CSA Advisory - Bilingual System (Safe Mode) * Handles auto-detection (Browser > LocalStorage) and text replacement. */ const VALID_LANGS = ['en', 'it']; const DEFAULT_LANG = 'en'; async function loadTranslations(lang) { if (!VALID_LANGS.includes(lang)) lang = DEFAULT_LANG; console.log(`[i18n] Switching to: ${lang}`); try { const response = await fetch(`/static/locales/${lang}.json`); if (!response.ok) throw new Error(`Could not load ${lang}.json`); const translations = await response.json(); // 1. Apply to data-i18n elements document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); if (translations[key]) { // Determine if we should replace innerText or HTML // Safest is to replace text content to prevent XSS, but some keys might have simple bold tags. // For now, simple text replacement. if (el.children.length === 0) { el.textContent = translations[key]; } else { // If element has children (like icons), we try to find a text node or complex logic. // But our python script tags the *text container*. // If the Python script tagged a container with children, we might overwrite icons. // WE NEED TO BE CAREFUL. // Strategy: The Python script will try to tag LEAF nodes or nodes with only text. // If we encounter an element with children here, we might want to check if the translation contains HTML? // Let's assume textContent for safety unless we decide otherwise. // But wait, the Python script puts data-i18n on the element. // If
  • Text
  • is tagged, replacing content kills the icon. // The Python script should ideally tag
  • Text
  • . // 'fix_and_translate_global.py' logic was: if tag has children, might skip or tag safely. // Let's rely on the Python script to do the right thing (wrapping text in spans if needed). // If the JS sees children, it might be better to NOT touch it unless we are sure. // Correction: We will use innerHTML if the key structure seems to demand it, but standard is text. // Let's stick to innerText for safety. el.textContent = translations[key]; } } }); // 2. Persist & UI localStorage.setItem('csa_lang', lang); document.documentElement.lang = lang; // Update Switcher UI (Bold the active one) document.querySelectorAll('.lang-btn').forEach(btn => { const isTarget = btn.dataset.lang === lang; btn.classList.toggle('fw-bold', isTarget); btn.classList.toggle('text-dark', isTarget); btn.classList.toggle('text-muted', !isTarget); }); } catch (e) { console.error("[i18n] Error:", e); } } function detectLanguage() { // 1. User Preference const stored = localStorage.getItem('csa_lang'); if (stored && VALID_LANGS.includes(stored)) return stored; // 2. Browser Preference const browser = navigator.language.slice(0, 2).toLowerCase(); // 'it-IT' -> 'it' if (VALID_LANGS.includes(browser)) return browser; // 3. Default return DEFAULT_LANG; } document.addEventListener('DOMContentLoaded', () => { const lang = detectLanguage(); loadTranslations(lang); // 3. Attach Click Listeners document.querySelectorAll('.lang-btn').forEach(btn => { btn.addEventListener('click', (e) => { e.preventDefault(); const startLang = btn.getAttribute('data-lang'); loadTranslations(startLang); }); }); });