Files
Life-OS/public/i18n.js
T
2026-09-25 21:59:01 -05:00

41 lines
9.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Life OS internationalisation: one locale catalogue, no DOM text rewriting. */
(() => {
const en = {
app: { today: 'TODAY', timeline: 'TIMELINE', museum: 'MUSEUM', insights: 'INSIGHTS', profile: 'PROFILE', system: 'SYSTEM' },
common: { save: 'SAVE', cancel: 'CANCEL', edit: 'EDIT', delete: 'DELETE', close: 'Close', open: 'Open', minimize: 'Minimize', maximize: 'Maximize', restore: 'Restore window', energy: 'ENERGY', days: 'DAYS', never: 'NEVER' },
today: { prompt: 'How was your day?', placeholder: 'Write something about today...', archive: 'ARCHIVE TODAY', update: 'UPDATE MEMORY', weather: "TODAY'S WEATHER", energy: 'ENERGY LEVEL', film: "TODAY'S FILM", archiving: 'ARCHIVING MEMORY...', archived: 'MEMORY ARCHIVED' },
weather: { clear: 'Clear', light: 'Light', cloudy: 'Cloudy', rain: 'Rain', storm: 'Storm' },
timeline: { eyebrow: 'MEMORY ARCHIVE', emptyTitle: 'No memories yet.', emptyBody: 'Open Today when you are ready to keep one.', detail: 'MEMORY DETAIL', noNote: 'No written note.', editing: 'EDITING AS TODAY — SAVE TO UPDATE', preserved: 'PRESERVED', addMuseum: 'ADD TO MUSEUM', confirmDelete: 'CONFIRM DELETE', remove: 'Remove this memory?', irreversible: 'This cannot be undone.', deleteMemory: 'DELETE MEMORY', removed: 'MEMORY REMOVED', added: 'MEMORY PRESERVED' },
museum: { eyebrow: 'MUSEUM', title: 'Preserved moments', subtitle: 'Worth keeping for the long view.', empty: 'A museum begins with one preserved moment.', preserved: 'STATUS: PRESERVED' },
insights: { eyebrow: 'LAST 30 DAYS', title: 'Insights, quietly.', weather: 'WEATHER', average: 'AVERAGE ENERGY', active: 'MOST ACTIVE DAY', current: 'CURRENT STREAK', longest: 'Longest streak: {count} days', noEntries: 'No entries yet' },
profile: { eyebrow: 'SYSTEM PROFILE', online: 'LIFE OS ONLINE', daysOnline: 'DAYS ONLINE', memories: 'MEMORIES', museumItems: 'MUSEUM ITEMS', streak: 'CURRENT STREAK', longest: 'LONGEST STREAK', commonWeather: 'COMMON WEATHER', personal: 'PERSONAL SYSTEM', name: 'Display Name', birthday: 'Birthday (optional)', start: 'Life OS Start Date', motto: 'Personal Motto', save: 'SAVE PROFILE', saved: 'PROFILE SAVED', average: 'AVERAGE ENERGY {value} / 5' },
system: { eyebrow: 'SYSTEM SETTINGS', title: 'System, local and yours.', appearance: 'APPEARANCE', language: 'LANGUAGE', browserLanguage: 'BROWSER LANGUAGE', detectedZh: 'Detected: Chinese', detectedEn: 'Detected: English', auto: 'AUTO', data: 'DATA', storage: 'STORAGE', dataStorage: 'DATA STORAGE', export: 'EXPORT DATA', import: 'IMPORT DATA', reset: 'RESET LIFE OS', local: 'Local Storage', stored: 'Your data is stored locally in this browser.', backups: 'Create regular backups to prevent data loss.', lastBackup: 'LAST BACKUP · {value}', recommended: 'BACKUP RECOMMENDED', version: 'VERSION', theme: { dark: 'DARK', light: 'LIGHT', auto: 'AUTO' } },
dialog: { backup: 'LIFE OS BACKUP', ready: 'Ready to restore', exported: 'Exported: {date}', memories: 'Memories: {count}', museumItems: 'Museum Items: {count}', merge: 'MERGE', replaceAll: 'REPLACE ALL DATA', final: 'FINAL CONFIRMATION', replaceQuestion: 'Replace all Life OS data?', replaceWarning: 'This will replace all current Life OS data.', replace: 'REPLACE DATA', resetQuestion: 'Reset all local data?', resetWarning: 'Export a backup first if you want to keep it.', resetData: 'RESET DATA' },
feedback: { backup: 'BACKUP CREATED', invalid: 'INVALID BACKUP FILE', restored: 'SYSTEM RESTORED', restoring: 'RESTORING SYSTEM...', minimized: 'MINIMIZED — TAP THE APP ICON TO RESTORE', languageZh: 'Language set to Chinese', languageEn: 'Language set to English', followingZh: 'Following browser language: Chinese', followingEn: 'Following browser language: English' },
addon: { draftRestored: 'DRAFT RESTORED', searchTitle: 'SEARCH MEMORY ARCHIVE', searchPlaceholder: 'Search titles, notes, moods…', searchHint: 'ESC to close · click a result to open it', untitled: 'Untitled memory', noResults: 'No memories found.', syncPaused: 'CLOUD SYNC PAUSED — CHANGES STAY ON THIS DEVICE', syncReady: 'CLOUD SYNC READY', migrateQuestion: 'Move this browser’s Life OS to the cloud?', migrateBody: 'Your existing local records will become the first synced copy for this ChatGPT account.', migrate: 'MIGRATE & SYNC', fresh: 'START FRESH', migrated: 'LOCAL LIFE OS MIGRATED', cloudRestored: 'CLOUD LIFE OS RESTORED', cloudUnavailable: 'CLOUD STORAGE UNAVAILABLE — LOCAL MODE ACTIVE' }
};
const zh = {
app: { today: '今日', timeline: '时间线', museum: '人生博物馆', insights: '洞察', profile: '个人资料', system: '系统' },
common: { save: '保存', cancel: '取消', edit: '编辑', delete: '删除', close: '关闭', open: '打开', minimize: '最小化', maximize: '最大化', restore: '恢复窗口', energy: '能量', days: '天', never: '从未' },
today: { prompt: '今天过得怎么样?', placeholder: '写下今天的片段…', archive: '归档今日', update: '更新记忆', weather: '今日天气', energy: '能量等级', film: '今日电影', archiving: '正在归档…', archived: '记忆已归档' },
weather: { clear: '晴朗', light: '微光', cloudy: '多云', rain: '雨天', storm: '风暴' },
timeline: { eyebrow: '记忆档案', emptyTitle: '还没有记忆。', emptyBody: '准备好记录时,打开“今日”。', detail: '记忆详情', noNote: '尚未写下记录。', editing: '正在以今日记录编辑 — 保存即可更新', preserved: '已珍藏', addMuseum: '加入博物馆', confirmDelete: '确认删除', remove: '删除这条记忆?', irreversible: '此操作无法撤销。', deleteMemory: '删除记忆', removed: '记忆已删除', added: '记忆已珍藏' },
museum: { eyebrow: '人生博物馆', title: '被珍藏的瞬间', subtitle: '值得留给漫长回望的片段。', empty: '从一份被珍藏的记忆开始。', preserved: '状态:已珍藏' },
insights: { eyebrow: '最近 30 天', title: '安静地看见时间。', weather: '天气', average: '平均能量', active: '最活跃日', current: '当前连续记录', longest: '最长连续记录:{count} 天', noEntries: '暂无记录' },
profile: { eyebrow: '系统档案', online: 'LIFE OS 在线', daysOnline: '系统运行天数', memories: '记忆', museumItems: '博物馆藏品', streak: '当前连续记录', longest: '最长连续记录', commonWeather: '常见天气', personal: '个人系统', name: '显示名称', birthday: '生日(选填)', start: 'Life OS 启动日期', motto: '个人格言', save: '保存资料', saved: '资料已保存', average: '平均能量 {value} / 5' },
system: { eyebrow: '系统设置', title: '你的个人系统。', appearance: '外观', language: '语言', browserLanguage: '浏览器语言', detectedZh: '当前识别:中文', detectedEn: '当前识别:英语', auto: '跟随浏览器', data: '数据', storage: '存储', dataStorage: '数据存储', export: '导出数据', import: '导入数据', reset: '重置 Life OS', local: '本地存储', stored: '你的数据仅存储在此浏览器中。', backups: '定期备份,让记忆一直在。', lastBackup: '上次备份 · {value}', recommended: '建议备份', version: '版本', theme: { dark: '深色', light: '浅色', auto: '跟随系统' } },
dialog: { backup: 'Life OS 备份', ready: '准备恢复', exported: '导出时间:{date}', memories: '记忆:{count}', museumItems: '博物馆藏品:{count}', merge: '合并', replaceAll: '替换全部数据', final: '最终确认', replaceQuestion: '替换全部 Life OS 数据?', replaceWarning: '这将覆盖当前所有 Life OS 数据。', replace: '替换数据', resetQuestion: '重置所有本地数据?', resetWarning: '如需保留数据,请先导出备份。', resetData: '重置数据' },
feedback: { backup: '备份已创建', invalid: '无效备份文件', restored: '系统已恢复', restoring: '正在恢复系统…', minimized: '已最小化 — 点击任务栏图标即可恢复', languageZh: '语言已切换为中文', languageEn: 'Language set to English', followingZh: '已跟随浏览器语言:中文', followingEn: 'Following browser language: English' },
addon: { draftRestored: '草稿已恢复', searchTitle: '搜索记忆档案', searchPlaceholder: '搜索标题、记录或天气…', searchHint: '按 Esc 关闭 · 点击结果即可打开', untitled: '未命名记忆', noResults: '没有找到记忆。', syncPaused: '云端同步暂停——更改仍保留在此设备', syncReady: '云端同步已就绪', migrateQuestion: '将此浏览器的 Life OS 迁移到云端?', migrateBody: '现有本地记录将成为这个 ChatGPT 账号的第一份云端同步数据。', migrate: '迁移并同步', fresh: '从空白开始', migrated: '本地 Life OS 已迁移', cloudRestored: '云端 Life OS 已恢复', cloudUnavailable: '云端存储暂不可用——已使用本地模式' }
};
const get = (object, key) => key.split('.').reduce((value, part) => value?.[part], object);
function currentLocale() { return typeof window.lang === 'function' ? window.lang() : 'en'; }
function t(key, values = {}) {
const dictionary = currentLocale() === 'zh' ? zh : en;
const fallback = get(en, key) || key;
return String(get(dictionary, key) ?? fallback).replace(/\{(\w+)\}/g, (_, name) => values[name] ?? `{${name}}`);
}
function date(value, options) { return new Intl.DateTimeFormat(currentLocale() === 'zh' ? 'zh-CN' : 'en-US', options).format(new Date(value)); }
window.LifeI18n = { t, date, dictionaries: { en, zh } };
})();