Files
blog/src/i18n/ui.ts
T
wait4xandGLM-5.3 d00ca7e447 fix(i18n): 语言轨导航修复+重排,热力图切 GitHub(车道 E)
- 真 bug(用户实测:切 en 后点板块回中文):Header nav href 硬编码
  zh 路径,curLocale 只喂了词条——localeOf(Astro.url) 构建期自推断
  +五项+品牌链接全轨化(brand 原指 / 同病同修),aria 同步
- 导航重排(用户拍板):开源 · 文章 · 图库 · 瞬间 · 关于;瞬间
  新进导航;移动 320-430×双轨八格页面级溢出全 0(内滚阈值 350→450
  +中段地板再收;en 390-430 尾部约 55px 靠内滚——'Open Source'→
  'Projects' 改名可省 35px,留用户拍板)
- 热力图纯切 GitHub(用户拍板):GraphQL contributionsCollection
  53 周窗口(上海日界);token=宿主 0600 github-token.txt,缺位→
  WARN 降级样例数据(当前站点即样例);三级回落 token→样例→空网格
- E2E 新增 2 断言:en 页 nav 全 /en/ 前缀+brand 指 /en/(本 bug
  的回归测试)

车道:op-gitea(自验 33/33);收编验收:en/zh 序实测+三宽度溢出 0+
E2E 33/33(本地 dist 口径——staging 未含未推代码为既定纪律)

验证: pnpm astro build 34 页 exit 0;node tests/e2e.mjs 33/33;
      en/zh 导航序与 href 前缀 playwright 实测

Spec: none (Header 修复+重排+热力图换源,车道级交付)

Co-authored-by: GLM-5.3
2026-10-25 22:19:40 +08:00

116 lines
7.6 KiB
TypeScript
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.
/**
* UI 双语字典:组件静态文案的单一事实源。
* 约定:key 稳定小写蛇形;zh 是源语言(先有),en 跟随;
* 车道协作:op-gitea 扩展本表并串接五组件(Footer/SearchDialog/gallery/moments/about)。
*/
export type Locale = 'zh' | 'en';
const dict = {
skip_to_content: { zh: '跳到正文', en: 'Skip to content' },
nav_posts: { zh: '文章', en: 'Posts' },
nav_gallery: { zh: '图库', en: 'Gallery' },
nav_about: { zh: '关于', en: 'About' },
nav_opensource: { zh: '开源', en: 'Open Source' },
search_label: { zh: '搜索', en: 'Search' },
search_placeholder: { zh: '搜索文章…(Esc 关闭)', en: 'Search posts… (Esc to close)' },
search_hint: { zh: '索引由 Pagefind 构建期生成 · 静态站零后端', en: 'Index built by Pagefind · zero-backend static site' },
footer_copyright: { zh: '©', en: '©' },
reading_time_min: { zh: '分钟', en: 'min' },
category_reading: { zh: '阅读', en: 'Reading' },
category_tech: { zh: '技术', en: 'Tech' },
category_photo: { zh: '照片', en: 'Photo' },
latest_photos: { zh: '最新影像', en: 'Latest photos' },
enter_gallery: { zh: '进入图库 →', en: 'Gallery →' },
open_source_projects: { zh: '开源 · Projects', en: 'Open Source · Projects' },
self_hosted: { zh: '自托管', en: 'self-hosted' },
prev_post: { zh: '上一篇', en: 'Previous' },
next_post: { zh: '下一篇', en: 'Next' },
ai_translated_note: {
zh: '本文由机器翻译自中文原文,欢迎指正。',
en: 'Machine-translated from the Chinese original. Corrections welcome.',
},
// ===== T2 车道(op-gitea):Footer/SearchDialog/gallery/moments/about 静态文案 =====
// footer_icp 是法定备案标识,英文页照抄不译
search_no_results: { zh: '无结果', en: 'No results' },
footer_icp: { zh: '陕ICP备2026014860号-1', en: '陕ICP备2026014860号-1' },
gallery_title: { zh: '图库', en: 'Gallery' },
gallery_filter_legend: { zh: '分组筛选', en: 'Filter by group' },
gallery_filter_all: { zh: '全部', en: 'All' },
gallery_filter_street: { zh: '街拍', en: 'Street' },
gallery_filter_landscape: { zh: '风景', en: 'Landscape' },
// {n}/{title}/{exif} 为占位符,调用点 .replace() 填值
gallery_count: { zh: '共 {n} 张 · EXIF 构建期自动提取', en: '{n} photos · EXIF extracted at build time' },
gallery_view_aria: { zh: '查看大图:{title}', en: 'View photo: {title}' },
gallery_view_aria_exif: { zh: '({exif})', en: ' ({exif})' },
gallery_lightbox_label: { zh: '照片查看', en: 'Photo viewer' },
gallery_lightbox_close: { zh: '关闭(Esc)', en: 'Close (Esc)' },
gallery_lightbox_prev: { zh: '上一张(←)', en: 'Previous (←)' },
gallery_lightbox_next: { zh: '下一张(→)', en: 'Next (→)' },
gallery_lightbox_original: { zh: '原图', en: 'Original' },
gallery_lightbox_download: { zh: '下载', en: 'Download' },
moments_title: { zh: '瞬间', en: 'Moments' },
moments_note: { zh: '零碎的记录:随手拍、一句话感想、开源动态。', en: 'Fragmented notes: casual shots, one-liners, and open-source updates.' },
about_title: { zh: '关于', en: 'About' },
about_tracks_title: { zh: '兴趣版图', en: 'Interests' },
about_track_reading_name: { zh: '阅读', en: 'Reading' },
about_track_reading_desc: { zh: '文学与戏剧为主,读到哪写到哪。', en: 'Mostly literature and drama; I write as I read.' },
about_track_tech_name: { zh: '技术', en: 'Tech' },
about_track_tech_desc: { zh: 'Linux、容器与自托管,把家里的小机器折腾成顺手的工具。', en: 'Linux, containers, and self-hosting — turning the little machines at home into handy tools.' },
about_track_photo_name: { zh: '摄影', en: 'Photography' },
about_track_photo_desc: { zh: '街拍与山野,随身一台无反,在等光的间隙按快门。', en: 'Street and landscapes with a mirrorless camera, pressing the shutter while waiting for the light.' },
about_build_aria: { zh: '本站构建说明', en: 'Site build notes' },
about_build_title: { zh: '本站如何构建', en: 'How this site is built' },
about_build_desc: {
zh: '页面由 Astro 静态生成,不含运行时框架 JS;内容住在自托管 gitea——本地编辑器与 gitea 网页写的是同一个 git 仓库,push 之后由 homelab 自动构建发布;评论走自托管 Artalk。页脚 built from 一行链到本次构建对应的 commit,构建过程透明可追溯。',
en: 'Pages are statically generated by Astro with no runtime framework JS. Content lives on a self-hosted gitea — my local editor and the gitea web UI write to the same git repository, and each push is built and published automatically by the homelab. Comments run on self-hosted Artalk. The built-from line in the footer links to the commit behind this build, keeping the process transparent and traceable.',
},
// ===== 热力图(Phase 4 T2 车道):文案全部页面层注入,组件保持 locale 无关 =====
heatmap_title: { zh: '开源活动', en: 'Open Source Activity' },
// {n} 为总贡献次数占位符,调用点 .replace() 填值
heatmap_summary: { zh: '最近一年 {n} 次贡献', en: '{n} contributions in the last year' },
heatmap_less: { zh: '少', en: 'Less' },
heatmap_more: { zh: '多', en: 'More' },
heatmap_note: { zh: '数据来自 GitHub · 构建期生成', en: 'via GitHub · generated at build time' },
// ===== B 车道:Footer 极客双页入口(stack/colophon 页内文案各自内联,不入本表) =====
footer_stack: { zh: '装备', en: 'stack' },
footer_colophon: { zh: '制作', en: 'colophon' },
// ===== C 车道:Keyboard 帮助表全量词条(组件 Astro.url 构建期自推断 locale) =====
kbd_title: { zh: '键盘快捷键', en: 'Keyboard shortcuts' },
kbd_palette: { zh: '命令面板', en: 'Command palette' },
kbd_theme_toggle: { zh: '切换明暗', en: 'Toggle light / dark' },
kbd_this_help: { zh: '本帮助', en: 'This help' },
kbd_gh_home: { zh: '首页', en: 'Home' },
kbd_ga_posts: { zh: '文章', en: 'Posts' },
kbd_gg_gallery: { zh: '图库', en: 'Gallery' },
kbd_gm_moments: { zh: '瞬间', en: 'Moments' },
kbd_terminal: { zh: '终端彩蛋', en: 'Terminal easter egg' },
kbd_esc_close: { zh: '关闭浮层', en: 'Close dialogs' },
kbd_hint: { zh: '提示:/terminal 终端彩蛋等你探索', en: 'Tip: the /terminal easter egg awaits' },
// ===== 命令面板(Phase 4 T1 车道):动作/导航/分组与键位提示 =====
nav_home: { zh: '首页', en: 'Home' },
nav_moments: { zh: '瞬间', en: 'Moments' },
cmd_palette_label: { zh: '命令面板', en: 'Command palette' },
cmd_group_actions: { zh: '动作', en: 'Actions' },
cmd_group_nav: { zh: '导航', en: 'Navigation' },
cmd_group_search: { zh: '搜索结果', en: 'Search results' },
cmd_toggle_theme: { zh: '切换明暗主题', en: 'Toggle dark mode' },
// 语言动作按当前页面语言命名目标语(zh 页提示切到 English,反之亦然)
cmd_switch_lang: { zh: '切换到 English', en: 'Switch to Chinese' },
cmd_open_gitea: { zh: '打开 gitea 源码仓', en: 'Open the gitea repo' },
cmd_copy_rss: { zh: '复制 RSS 地址', en: 'Copy RSS address' },
cmd_copied: { zh: '已复制 ✓', en: 'Copied ✓' },
cmd_hint: { zh: '↑↓ 选择 · Enter 执行 · Esc 关闭', en: '↑↓ navigate · Enter run · Esc close' },
} as const;
export type UiKey = keyof typeof dict;
/** 取串:locale 缺省 zh;未知 key 原样返回(编译期 tsc 已挡)。 */
export function t(key: UiKey, locale: Locale = 'zh'): string {
return dict[key][locale] ?? dict[key].zh;
}