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);
|
});
|
}
|
};
|