const I18n = { currentLang: 'zh', strings: {}, languages: [ { code: 'zh', labelKey: 'lang.zh', locale: 'zh-CN', file: 'config/i18n/zh.json' }, { code: 'en', labelKey: 'lang.en', locale: 'en-US', file: 'config/i18n/en.json' }, { code: 'ko', labelKey: 'lang.ko', locale: 'ko-KR', file: 'config/i18n/ko.json' }, { code: 'ja', labelKey: 'lang.ja', locale: 'ja-JP', file: 'config/i18n/ja.json' } ], async load(lang) { const langConfig = this.languages.find(l => l.code === lang); if (!langConfig) return; const res = await fetch(langConfig.file); this.strings = await res.json(); this.currentLang = lang; document.documentElement.lang = langConfig.locale; }, t(key) { return this.strings[key] || key; }, getLocale() { const langConfig = this.languages.find(l => l.code === this.currentLang); return langConfig ? langConfig.locale : 'zh-CN'; }, applyToDOM() { document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); el.textContent = this.t(key); }); document.querySelectorAll('[data-i18n-placeholder]').forEach(el => { const key = el.getAttribute('data-i18n-placeholder'); el.placeholder = this.t(key); }); const titleEl = document.querySelector('title[data-i18n]'); if (titleEl) { document.title = this.t(titleEl.getAttribute('data-i18n')); } }, renderLangMenu(menuEl, onSelect) { menuEl.innerHTML = ''; this.languages.forEach(lang => { const item = document.createElement('div'); item.className = 'lang-menu-item' + (lang.code === this.currentLang ? ' active' : ''); item.textContent = this.t(lang.labelKey); item.addEventListener('click', () => onSelect(lang.code)); menuEl.appendChild(item); }); } };