mirror of
https://github.com/sotam0316/brain_dogfood.git
synced 2026-04-25 03:48:38 +09:00
Initial Global Release v1.0 (Localization & Security Hardening)
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* 전역 시스템 상수 (Global System Constants)
|
||||
*/
|
||||
export const Constants = {
|
||||
GROUPS: {
|
||||
DEFAULT: 'default',
|
||||
FILES: 'files',
|
||||
DONE: 'done'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 커스텀 i18n 매니저 (Custom i18n Manager)
|
||||
* - 서버 설정에 따라 locale 파일을 로드하고 화면을 번역합니다.
|
||||
*/
|
||||
export const I18nManager = {
|
||||
localeData: {},
|
||||
currentLang: 'en',
|
||||
|
||||
/**
|
||||
* 초기화 및 언어 팩 로드
|
||||
*/
|
||||
async init(lang = 'en') {
|
||||
this.currentLang = lang;
|
||||
try {
|
||||
const res = await fetch(`/static/locales/${lang}.json?v=2.2`);
|
||||
if (!res.ok) throw new Error(`Locale ${lang} not found`);
|
||||
this.localeData = await res.json();
|
||||
console.log(`🌐 i18n: Language [${lang}] loaded successfully.`);
|
||||
|
||||
// 초기 로드 시 한 번 전체 적용
|
||||
this.applyTranslations();
|
||||
} catch (err) {
|
||||
console.error('❌ i18n Load Error:', err);
|
||||
// 한국어 로드 실패 시에도 영어로 폴백 시도 가능
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 특정 키에 해당하는 번역 텍스트 또는 배열 반환
|
||||
*/
|
||||
t(key) {
|
||||
// 객체 깊은 참조 지원 (예: "groups.done")
|
||||
const value = key.split('.').reduce((obj, k) => (obj && obj[k]), this.localeData);
|
||||
return value !== undefined ? value : key; // 없으면 키 자체 반환
|
||||
},
|
||||
|
||||
/**
|
||||
* 화면 내 i18n 관련 모든 속성을 번역
|
||||
*/
|
||||
applyTranslations() {
|
||||
// 1. 일반 텍스트 번역
|
||||
document.querySelectorAll('[data-i18n]').forEach(el => {
|
||||
const key = el.dataset.i18n;
|
||||
el.textContent = this.t(key);
|
||||
});
|
||||
|
||||
// 2. Placeholder 번역
|
||||
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
|
||||
const key = el.dataset.i18nPlaceholder;
|
||||
el.placeholder = this.t(key);
|
||||
});
|
||||
|
||||
// 3. Title (Browser Tooltip) 번역
|
||||
document.querySelectorAll('[data-i18n-title]').forEach(el => {
|
||||
const key = el.dataset.i18nTitle;
|
||||
el.title = this.t(key);
|
||||
});
|
||||
|
||||
// 4. Custom Tooltip (data-tooltip) 번역
|
||||
document.querySelectorAll('[data-i18n-tooltip]').forEach(el => {
|
||||
const key = el.dataset.i18nTooltip;
|
||||
el.setAttribute('data-tooltip', this.t(key));
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user