/* Translation lookup and locale-aware formatting. Copy lives in /locales/*.json. */ (() => { const dictionaries = window.LifeOSLocales || {}; const en = dictionaries.en || {}; const zh = dictionaries['zh-CN'] || {}; const PREFERENCE_KEY = 'lifeos_language_preference_v1'; const validPreference = value => ['auto', 'en', 'zh'].includes(value); const lookup = (object, path) => path.split('.').reduce((value, part) => value?.[part], object); const detectBrowserLanguage = () => { const preferences = navigator.languages?.length ? navigator.languages : [navigator.language || navigator.userLanguage || 'en']; return preferences.some(value => String(value).toLowerCase().startsWith('zh')) ? 'zh' : 'en'; }; const readPreference = () => { try { const saved = localStorage.getItem(PREFERENCE_KEY); if (validPreference(saved)) return saved; let oldSettings = {}; try { oldSettings = JSON.parse(localStorage.getItem('lifeos_settings') || '{}'); } catch {} const legacyMode = oldSettings.languageMode ?? (['en', 'zh'].includes(oldSettings.language) ? 'manual' : 'auto'); const migrated = legacyMode === 'manual' && ['en', 'zh'].includes(oldSettings.language) ? oldSettings.language : 'auto'; localStorage.setItem(PREFERENCE_KEY, migrated); return migrated; } catch { return 'auto'; } }; let preference = readPreference(); const language = () => preference === 'auto' ? detectBrowserLanguage() : preference; function t(key, values = {}) { const selected = language() === 'zh' ? zh : en; const template = lookup(selected, key) ?? lookup(en, key) ?? key; return String(template).replace(/\{(\w+)\}/g, (_, name) => values[name] ?? `{${name}}`); } function locale() { return language() === 'zh' ? 'zh-CN' : 'en-US'; } function date(value, options) { const parsed = value instanceof Date ? value : new Date(typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value) ? `${value}T12:00:00` : value); return new Intl.DateTimeFormat(locale(), options).format(parsed); } function number(value, options) { return new Intl.NumberFormat(locale(), options).format(value); } function setLanguage(value) { if (!validPreference(value)) return; preference = value; try { localStorage.setItem(PREFERENCE_KEY, value); } catch {} window.renderIcons?.(); window.renderAll?.(); window.applyLanguage?.(); window.toast?.(value === 'auto' ? (language() === 'zh' ? 'feedback.followingZh' : 'feedback.followingEn') : (value === 'zh' ? 'feedback.languageZh' : 'feedback.languageEn')); } window.lang = language; window.setLanguage = setLanguage; window.LifeI18n = { t, date, number, locale, language, preference: () => preference, dictionaries: { en, zh } }; })();