/** * BreakPilot Studio - i18n Module * * Internationalisierungs-Funktionen: * - t(key): Übersetzungsfunktion * - setLanguage(lang): Sprache wechseln * - applyLanguage(): UI-Texte aktualisieren * - getCurrentLang(): Aktuelle Sprache abrufen * * Refactored: 2026-01-19 */ import { translations, rtlLanguages, defaultLanguage, availableLanguages } from './translations.js'; // Aktuelle Sprache (aus localStorage oder Standard) let currentLang = localStorage.getItem('bp_language') || defaultLanguage; /** * Übersetzungsfunktion * @param {string} key - Übersetzungsschlüssel * @returns {string} - Übersetzter Text oder Fallback */ export function t(key) { const lang = translations[currentLang] || translations[defaultLanguage]; return lang[key] || translations[defaultLanguage][key] || key; } /** * Aktuelle Sprache abrufen * @returns {string} - Sprachcode (de, en, tr, etc.) */ export function getCurrentLang() { return currentLang; } /** * Prüft ob aktuelle Sprache RTL ist * @returns {boolean} */ export function isRTL() { return rtlLanguages.includes(currentLang); } /** * Sprache wechseln * @param {string} lang - Neuer Sprachcode */ export function setLanguage(lang) { if (translations[lang]) { currentLang = lang; localStorage.setItem('bp_language', lang); applyLanguage(); return true; } console.warn(`Language '${lang}' not available`); return false; } /** * Wendet die aktuelle Sprache auf alle UI-Elemente an */ export function applyLanguage() { // RTL-Unterstützung if (isRTL()) { document.body.classList.add('rtl'); document.documentElement.setAttribute('dir', 'rtl'); } else { document.body.classList.remove('rtl'); document.documentElement.setAttribute('dir', 'ltr'); } // Alle Elemente mit data-i18n-Attribut aktualisieren document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); const translated = t(key); // Verschiedene Element-Typen behandeln if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') { el.placeholder = translated; } else { el.textContent = translated; } }); // Elemente mit data-i18n-title für Tooltips document.querySelectorAll('[data-i18n-title]').forEach(el => { const key = el.getAttribute('data-i18n-title'); el.title = t(key); }); // Elemente mit data-i18n-value für value-Attribute document.querySelectorAll('[data-i18n-value]').forEach(el => { const key = el.getAttribute('data-i18n-value'); el.value = t(key); }); // Custom Event für andere Module window.dispatchEvent(new CustomEvent('languageChanged', { detail: { language: currentLang } })); } /** * Aktualisiert spezifische UI-Texte (Legacy-Kompatibilität) * Diese Funktion wird von älterem Code verwendet der direkt UI-IDs referenziert */ export function updateUITexts() { // Sidebar const sidebarAreas = document.querySelector('.sidebar h4'); if (sidebarAreas) sidebarAreas.textContent = t('sidebar_areas'); // Breadcrumb / Brand const brandSub = document.querySelector('.brand-sub'); if (brandSub) brandSub.textContent = t('brand_sub'); // Tab Labels const navCompare = document.getElementById('nav-compare'); if (navCompare) navCompare.textContent = t('nav_compare'); const navTiles = document.getElementById('nav-tiles'); if (navTiles) navTiles.textContent = t('nav_tiles'); // Buttons const uploadBtn = document.getElementById('uploadBtn'); if (uploadBtn) { const textSpan = uploadBtn.querySelector('.btn-text'); if (textSpan) textSpan.textContent = t('btn_upload'); } const deleteBtn = document.getElementById('deleteBtn'); if (deleteBtn) { const textSpan = deleteBtn.querySelector('.btn-text'); if (textSpan) textSpan.textContent = t('btn_delete'); } // Card Headers document.querySelectorAll('.card-header').forEach(header => { const icon = header.querySelector('i'); const iconHTML = icon ? icon.outerHTML : ''; // Original / Cleaned Sections if (header.closest('.scan-section')?.classList.contains('original-scan')) { header.innerHTML = iconHTML + ' ' + t('original_scan'); } else if (header.closest('.scan-section')?.classList.contains('cleaned-scan')) { header.innerHTML = iconHTML + ' ' + t('cleaned_version'); } }); // Tiles - MC const mcTile = document.querySelector('.mc-tile'); if (mcTile) { const title = mcTile.querySelector('.tile-content h3'); if (title) title.textContent = t('mc_title'); const desc = mcTile.querySelector('.tile-content p'); if (desc) desc.textContent = t('mc_desc'); } // Tiles - Cloze const clozeTile = document.querySelector('.cloze-tile'); if (clozeTile) { const title = clozeTile.querySelector('.tile-content h3'); if (title) title.textContent = t('cloze_title'); const desc = clozeTile.querySelector('.tile-content p'); if (desc) desc.textContent = t('cloze_desc'); } // Tiles - Q&A const qaTile = document.querySelector('.qa-tile'); if (qaTile) { const title = qaTile.querySelector('.tile-content h3'); if (title) title.textContent = t('qa_title'); const desc = qaTile.querySelector('.tile-content p'); if (desc) desc.textContent = t('qa_desc'); } // Tiles - Mindmap const mindmapTile = document.querySelector('.mindmap-tile'); if (mindmapTile) { const title = mindmapTile.querySelector('.tile-content h3'); if (title) title.textContent = t('mindmap_title'); const desc = mindmapTile.querySelector('.tile-content p'); if (desc) desc.textContent = t('mindmap_desc'); } // Footer const imprintLink = document.querySelector('footer a[href*="imprint"]'); if (imprintLink) imprintLink.textContent = t('imprint'); const privacyLink = document.querySelector('footer a[href*="privacy"]'); if (privacyLink) privacyLink.textContent = t('privacy'); const contactLink = document.querySelector('footer a[href*="contact"]'); if (contactLink) contactLink.textContent = t('contact'); // Process Button const fullProcessBtn = document.getElementById('fullProcessBtn'); if (fullProcessBtn) { const textSpan = fullProcessBtn.querySelector('.btn-text'); if (textSpan) textSpan.textContent = t('btn_full_process'); } // Status Bar const statusText = document.getElementById('statusText'); if (statusText && statusText.textContent === 'Bereit' || statusText?.textContent === 'Ready') { statusText.textContent = t('status_ready'); } } /** * Initialisiert das Sprachwahl-UI * @param {string} containerId - ID des Containers für Sprachauswahl */ export function initLanguageSelector(containerId = 'language-selector') { const container = document.getElementById(containerId); if (!container) return; // Dropdown erstellen container.innerHTML = ` `; // Event Handler const select = document.getElementById('language-select'); if (select) { select.addEventListener('change', (e) => { setLanguage(e.target.value); }); } } /** * Formatiert einen Status-Text mit Platzhaltern * @param {string} key - Übersetzungsschlüssel * @param {Object} vars - Variablen zum Einsetzen * @returns {string} - Formatierter Text */ export function tFormat(key, vars = {}) { let text = t(key); Object.entries(vars).forEach(([k, v]) => { text = text.replace(new RegExp(`\\{${k}\\}`, 'g'), v); }); return text; } // Re-export für Convenience export { translations, rtlLanguages, defaultLanguage, availableLanguages };