feat(viewer): album page with locale fallback and timezone display

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-18 09:52:22 +08:00
parent 04b5641901
commit adc45b1563
15 changed files with 879 additions and 61 deletions
+17 -15
View File
@@ -25,19 +25,21 @@ function resolveInitialLocale(): ViewerLocale {
return FALLBACK_LOCALE;
}
export const i18n = createI18n({
legacy: false,
locale: resolveInitialLocale(),
fallbackLocale: FALLBACK_LOCALE,
messages: { 'zh-CN': zhCN, en },
});
// 切换语言并持久化;写失败不阻断切换。
export function setLocale(locale: ViewerLocale): void {
i18n.global.locale.value = locale;
try {
localStorage.setItem(LOCALE_STORAGE_KEY, locale);
} catch {
// 忽略持久化失败
}
/**
* 构建 viewer i18n 实例(运行时单例与测试各自构造)。
* 组件测试必须每次挂载用新实例:vue-i18n 的 install 会包装 app.unmount 调
* i18n.dispose()——共享单例被任一测试卸载后全局 composer 反应性即永久失效
* (locale 写入不再传播)。运行时 main.ts 只挂载一次,不受影响。
*/
export function createViewerI18n(initialLocale: ViewerLocale = resolveInitialLocale()) {
return createI18n({
legacy: false,
locale: initialLocale,
fallbackLocale: FALLBACK_LOCALE,
messages: { 'zh-CN': zhCN, en },
});
}
export type ViewerI18n = ReturnType<typeof createViewerI18n>;
export const i18n = createViewerI18n();
+10 -2
View File
@@ -1,12 +1,20 @@
export default {
app: { title: 'Live Gallery' },
home: { hint: 'Open an album link to start viewing' },
album: { emptyNotice: 'Photos coming soon' },
album: {
loading: 'Loading…',
emptyNotice: 'Photos coming soon',
time: 'Time',
venue: 'Venue',
categories: 'Categories',
retry: 'Retry',
},
lang: { switch: 'Switch language' },
route: { tokenLabel: 'Album token', photoLabel: 'Photo' },
errors: {
albumNotFound: 'Album not found',
albumNotAvailable: 'Album unavailable',
// ALBUM_NOT_PUBLIC 专用:offline / disabled / ghost token 同码(防枚举)。
albumNotAvailable: 'Album not found or offline',
photoNotFound: 'Photo not found',
notFound: 'Page not found',
authExpired: 'Session expired',
+11 -2
View File
@@ -1,12 +1,21 @@
export default {
app: { title: '现场相册' },
home: { hint: '打开相册链接即可观看' },
album: { emptyNotice: '照片即将上线' },
album: {
loading: '加载中…',
emptyNotice: '照片即将上线',
time: '时间',
venue: '地点',
categories: '分类',
retry: '重试',
},
lang: { switch: '切换语言' },
route: { tokenLabel: '相册令牌', photoLabel: '照片' },
errors: {
albumNotFound: '相册不存在',
albumNotAvailable: '相册不可用',
// ALBUM_NOT_PUBLIC 专用:offline / publicEnabled=false / 幽灵 token 同码(防枚举),
// 文案需同时覆盖「不存在」与「已下线」两种用户可理解成因。
albumNotAvailable: '相册不存在或已下线',
photoNotFound: '照片不存在',
notFound: '页面不存在',
authExpired: '登录已过期',