/** * LOCALIZATION SYSTEM * Multi-language support with JSON translation files */ class LocalizationSystem { constructor() { this.currentLang = 'en'; // Default language this.translations = {}; this.supportedLanguages = ['slo', 'en', 'de', 'it', 'cn']; // Load from localStorage const savedLang = localStorage.getItem('novafarma_language'); if (savedLang && this.supportedLanguages.includes(savedLang)) { this.currentLang = savedLang; } else { // AUTO-DETECT OS LANGUAGE (first launch) this.currentLang = this.detectOSLanguage(); console.log(`🌍 Auto-detected language: ${this.getCurrentLanguageName()}`); localStorage.setItem('novafarma_language', this.currentLang); } this.loadTranslations(); } /** * AUTO-DETECT OS LANGUAGE */ detectOSLanguage() { // Get browser/system language const browserLang = navigator.language || navigator.userLanguage || 'en'; const langCode = browserLang.toLowerCase().split('-')[0]; // e.g. 'en-US' → 'en' console.log(`🖥️ System language detected: ${browserLang} (${langCode})`); // Map to supported language const langMap = { 'sl': 'slo', // Slovenian 'en': 'en', // English 'de': 'de', // German 'it': 'it', // Italian 'zh': 'cn', // Chinese 'cn': 'cn' // Chinese (alternative) }; const detected = langMap[langCode] || 'en'; console.log(`✅ Mapped to game language: ${detected}`); return detected; } /** * GET CURRENT LANGUAGE NAME */ getCurrentLanguageName() { return this.getLanguageName(this.currentLang); } loadTranslations() { // Embedded translations (inline for simplicity) this.translations = { 'slo': { // UI 'ui.inventory': 'Inventar', 'ui.crafting': 'Izdelovanje', 'ui.health': 'Zdravje', 'ui.hunger': 'Lakota', 'ui.oxygen': 'Kisik', 'ui.day': 'Dan', 'ui.season': 'Letni čas', 'ui.hp': 'ZDR', 'ui.hun': 'LAK', 'ui.h2o': 'H2O', 'ui.xp': 'IZK', 'ui.lv': 'NIV', // Items 'item.wood': 'Les', 'item.stone': 'Kamen', 'item.seeds': 'Semena', 'item.wheat': 'Pšenica', 'item.corn': 'Koruza', // Actions 'action.plant': 'Posadi', 'action.harvest': 'Požanji', 'action.craft': 'Izdelaj', 'action.build': 'Zgradi', // Seasons 'season.spring': 'Pomlad', 'season.summer': 'Poletje', 'season.autumn': 'Jesen', 'season.winter': 'Zima', // Pause Menu 'pause.title': 'PAVZA', 'pause.resume': '▶ Nadaljuj', 'pause.save': '💾 Shrani igro', 'pause.settings': '⚙️ Nastavitve', 'pause.quit': '🚪 Izhod v meni', 'pause.hint': 'Pritisni ESC za nadaljevanje', // Messages 'msg.demo_end': 'Demo končan! Hvala za igranje.', 'msg.freezing': '❄️ Zmrzuješ!', 'msg.overheating': '🔥 Pregrevanje!' }, 'en': { // UI 'ui.inventory': 'Inventory', 'ui.crafting': 'Crafting', 'ui.health': 'Health', 'ui.hunger': 'Hunger', 'ui.oxygen': 'Oxygen', 'ui.day': 'Day', 'ui.season': 'Season', 'ui.hp': 'HP', 'ui.hun': 'HUN', 'ui.h2o': 'H2O', 'ui.xp': 'XP', 'ui.lv': 'LV', // Items 'item.wood': 'Wood', 'item.stone': 'Stone', 'item.seeds': 'Seeds', 'item.wheat': 'Wheat', 'item.corn': 'Corn', // Actions 'action.plant': 'Plant', 'action.harvest': 'Harvest', 'action.craft': 'Craft', 'action.build': 'Build', // Seasons 'season.spring': 'Spring', 'season.summer': 'Summer', 'season.autumn': 'Autumn', 'season.winter': 'Winter', // Pause Menu 'pause.title': 'PAUSED', 'pause.resume': '▶ Resume', 'pause.save': '💾 Save Game', 'pause.settings': '⚙️ Settings', 'pause.quit': '🚪 Quit to Menu', 'pause.hint': 'Press ESC to resume', // Messages 'msg.demo_end': 'Demo Ended! Thanks for playing.', 'msg.freezing': '❄️ Freezing!', 'msg.overheating': '🔥 Overheating!' }, 'de': { // UI 'ui.inventory': 'Inventar', 'ui.crafting': 'Handwerk', 'ui.health': 'Gesundheit', 'ui.hunger': 'Hunger', 'ui.oxygen': 'Sauerstoff', 'ui.day': 'Tag', 'ui.season': 'Jahreszeit', 'ui.hp': 'LP', 'ui.hun': 'HUN', 'ui.h2o': 'H2O', 'ui.xp': 'EP', 'ui.lv': 'ST', // Items 'item.wood': 'Holz', 'item.stone': 'Stein', 'item.seeds': 'Samen', 'item.wheat': 'Weizen', 'item.corn': 'Mais', // Actions 'action.plant': 'Pflanzen', 'action.harvest': 'Ernten', 'action.craft': 'Herstellen', 'action.build': 'Bauen', // Seasons 'season.spring': 'Frühling', 'season.summer': 'Sommer', 'season.autumn': 'Herbst', 'season.winter': 'Winter', // Pause Menu 'pause.title': 'PAUSIERT', 'pause.resume': '▶ Fortsetzen', 'pause.save': '💾 Spiel speichern', 'pause.settings': '⚙️ Einstellungen', 'pause.quit': '🚪 Zum Menü', 'pause.hint': 'ESC drücken zum Fortsetzen', // Messages 'msg.demo_end': 'Demo beendet! Danke fürs Spielen.', 'msg.freezing': '❄️ Du erfrierst!', 'msg.overheating': '🔥 Überhitzung!' }, 'it': { // UI 'ui.inventory': 'Inventario', 'ui.crafting': 'Artigianato', 'ui.health': 'Salute', 'ui.hunger': 'Fame', 'ui.oxygen': 'Ossigeno', 'ui.day': 'Giorno', 'ui.season': 'Stagione', 'ui.hp': 'PS', 'ui.hun': 'FAM', 'ui.h2o': 'H2O', 'ui.xp': 'ESP', 'ui.lv': 'LIV', // Items 'item.wood': 'Legno', 'item.stone': 'Pietra', 'item.seeds': 'Semi', 'item.wheat': 'Grano', 'item.corn': 'Mais', // Actions 'action.plant': 'Pianta', 'action.harvest': 'Raccogli', 'action.craft': 'Crea', 'action.build': 'Costruisci', // Seasons 'season.spring': 'Primavera', 'season.summer': 'Estate', 'season.autumn': 'Autunno', 'season.winter': 'Inverno', // Pause Menu 'pause.title': 'IN PAUSA', 'pause.resume': '▶ Riprendi', 'pause.save': '💾 Salva gioco', 'pause.settings': '⚙️ Impostazioni', 'pause.quit': '🚪 Esci al menu', 'pause.hint': 'Premi ESC per riprendere', // Messages 'msg.demo_end': 'Demo terminata! Grazie per aver giocato.', 'msg.freezing': '❄️ Stai congelando!', 'msg.overheating': '🔥 Surriscaldamento!' }, 'cn': { // UI 'ui.inventory': '库存', 'ui.crafting': '制作', 'ui.health': '健康', 'ui.hunger': '饥饿', 'ui.oxygen': '氧气', 'ui.day': '天数', 'ui.season': '季节', 'ui.hp': '生命', 'ui.hun': '饥饿', 'ui.h2o': '水', 'ui.xp': '经验', 'ui.lv': '等级', // Items 'item.wood': '木材', 'item.stone': '石头', 'item.seeds': '种子', 'item.wheat': '小麦', 'item.corn': '玉米', // Actions 'action.plant': '种植', 'action.harvest': '收获', 'action.craft': '制作', 'action.build': '建造', // Seasons 'season.spring': '春天', 'season.summer': '夏天', 'season.autumn': '秋天', 'season.winter': '冬天', // Pause Menu 'pause.title': '暂停', 'pause.resume': '▶ 继续', 'pause.save': '💾 保存游戏', 'pause.settings': '⚙️ 设置', 'pause.quit': '🚪 退出到菜单', 'pause.hint': '按ESC继续', // Messages 'msg.demo_end': '演示结束!感谢游玩。', 'msg.freezing': '❄️ 你在冻僵!', 'msg.overheating': '🔥 过热!' } }; } /** * Get translated string * @param {string} key - Translation key (e.g. 'ui.inventory') * @param {string} fallback - Fallback text if translation missing */ t(key, fallback = key) { const lang = this.translations[this.currentLang]; if (lang && lang[key]) { return lang[key]; } // Fallback to English const enLang = this.translations['en']; if (enLang && enLang[key]) { return enLang[key]; } return fallback; } /** * LOAD INTRO TEXTS FROM JSON */ async loadIntroTexts() { try { const response = await fetch('assets/localization.json'); const data = await response.json(); // Merge intro texts into translations for (const lang in data) { if (!this.translations[lang]) { this.translations[lang] = {}; } // Add intro polaroid texts if (data[lang].intro_polaroids) { this.translations[lang].intro_polaroids = data[lang].intro_polaroids; } // Add menu texts if (data[lang].menu) { Object.assign(this.translations[lang], data[lang].menu); } // Add title/subtitle if (data[lang].game_title) { this.translations[lang].game_title = data[lang].game_title; } if (data[lang].subtitle) { this.translations[lang].subtitle = data[lang].subtitle; } } console.log('✅ Intro texts loaded from JSON'); return true; } catch (error) { console.warn('⚠️ Could not load localization.json:', error); return false; } } /** * GET INTRO POLAROID TEXT */ getIntroText(polaroidKey) { const lang = this.translations[this.currentLang]; if (lang && lang.intro_polaroids && lang.intro_polaroids[polaroidKey]) { return lang.intro_polaroids[polaroidKey]; } // Fallback to English const enLang = this.translations['en']; if (enLang && enLang.intro_polaroids && enLang.intro_polaroids[polaroidKey]) { return enLang.intro_polaroids[polaroidKey]; } return polaroidKey; // Return key if not found } /** * GET VOICE FILE PATH (switches language folder) */ getVoicePath(character, index, format = 'mp3') { const langSuffix = this.currentLang === 'en' ? 'en' : 'sl'; // Map language codes to voice folders if (this.currentLang === 'slo') { // Slovenian voices in /sl/ folder return `assets/audio/voiceover/sl/${character}_${String(index).padStart(2, '0')}.${format}`; } else { // English voices (default for DE, IT, CN too) return `assets/audio/voiceover/en/${character}_en_${String(index).padStart(2, '0')}.${format}`; } } /** * CHECK IF VOICE FILE EXISTS FOR CURRENT LANGUAGE */ hasVoiceForLanguage(character, index) { // Slovenian and English have full voiceovers // Other languages fall back to English return this.currentLang === 'slo' || this.currentLang === 'en'; } /** * Set current language */ setLanguage(langCode) { if (this.supportedLanguages.includes(langCode)) { this.currentLang = langCode; localStorage.setItem('novafarma_language', langCode); console.log(`🌍 Language changed to: ${langCode}`); return true; } return false; } getCurrentLanguage() { return this.currentLang; } getSupportedLanguages() { return this.supportedLanguages.map(code => ({ code, name: this.getLanguageName(code) })); } getLanguageName(code) { const names = { 'slo': 'Slovenščina', 'en': 'English', 'de': 'Deutsch', 'it': 'Italiano', 'cn': '中文' }; return names[code] || code; } /** * INJECT EXTERNAL JSON DATA (loaded via Phaser) */ setExternalData(data) { try { // Merge intro texts into translations for (const lang in data) { if (!this.translations[lang]) { this.translations[lang] = {}; } // Add intro polaroid texts if (data[lang].intro_polaroids) { this.translations[lang].intro_polaroids = data[lang].intro_polaroids; } // Add menu texts if (data[lang].menu) { Object.assign(this.translations[lang], data[lang].menu); } // Add title/subtitle if (data[lang].game_title) { this.translations[lang].game_title = data[lang].game_title; } if (data[lang].subtitle) { this.translations[lang].subtitle = data[lang].subtitle; } } console.log('✅ Localization data injected successfully'); return true; } catch (error) { console.warn('⚠️ Could not inject localization data:', error); return false; } } } // Global instance window.LocalizationSystem = LocalizationSystem;