Files
frontend_v2/.workbuddy/memory/2026-08-16.md
toom1996 d14dd7e2db
Some checks failed
deploy / deploy (push) Has been cancelled
update
2026-08-18 20:33:56 +08:00

6.5 KiB
Raw Blame History

2026-08-16

i18n 取语言方式重构

  • 项目 i18n 已配置(defaultLocale: 'en', locales: ['en','cn'])。注意:本文件撰写时误记 prefixDefaultLocale 为 false;当前 astro.config.mjs 实际为 prefixDefaultLocale: true(见 2026-08-18 记忆)。
  • 将 .astro 页面里 getLocaleFromUrl(Astro.url) 改为 Astro.currentLocale(Astro 路由解析,更稳健),并补类型兜底 (Astro.currentLocale as Locale) ?? DEFAULT_LOCALE。
  • 涉及文件:src/layouts/Layout.astro、src/pages/index.astro、src/pages/cn/index.astro。
  • src/i18n/utils.ts 的 getLocaleFromUrl 纯函数保留(供 .ts 模块或解析任意 URL 使用)。

结论

  • Astro.currentLocale 可替代 getLocaleFromUrl(Astro.url),但仅限 .astro 文件;纯 TS / 解析非当前页 URL 仍需自定义函数。

Astro 浏览器语言检测(重要,修正此前误解)

  • Astro 确实提供 Astro.preferredLocale / Astro.preferredLocaleList,但它是服务端按请求结合 Accept-Language 头计算的,仅 SSR 运行时有效。
  • 本项目是静态构建 + nginx 托管:build 阶段无访客、无 Accept-Language 头,运行时也无 Node 进程重算,故 preferredLocale 在静态产物里是 undefined、preferredLocaleList 回退为全部 i18n.locales,无法在运行时检测访客语言。
  • 客户端 navigator.language 脚本仍是当前静态部署下唯一运行时生效的方案。
  • 若要改用 Astro.preferredLocale + Astro.redirect():必须迁移到 SSR(加 adapter、output:'server'、nginx 后跑 Node),且需在 i18n.locales 为 cn 补 codes: ['zh','zh-CN','zh-TW','zh-HK'] 才能把浏览器 zh-CN 匹配到 cn(当前 locales:['en','cn'] 裸码匹配不到)。

Bug 修复:header 语言切换器不显示

  • 根因:src/layouts/Layout.astro 中语言切换器(LOCALES.map)原是 #auth-slot 的子节点;页脚 auth 脚本 fetchMe() 未登录返回 null → render(null) 用 slot.innerHTML 整块重写成 Login/Signup,把语言切换器一并抹掉。任何未登录访客都触发,故语言选项永远看不见。
  • 修复:(1) 将语言切换器移出 #auth-slot,独立为 #lang-switch 兄弟节点,脚本重写不再波及;(2) 未登录时不再硬编码 /login 重写 #auth-slot,保留 SSR 的带语言前缀 Login/Signup,顺带修好 /cn 页登录链接丢前缀问题。
  • 教训:header 中「语言切换器」与「登录态 UI」必须分属不同容器,避免被 auth 脚本的 innerHTML 重写误伤。

语言切换器改为下拉菜单

  • 将 header #lang-switch 从「English / 中文」并排链接改为 Alpine 下拉(x-data="{open:false}" + @click.outside + @keydown.escape.window,绝对定位 right-0、z-50,带 chevron 旋转)。选中项 font-bold,其余 opacity-60。
  • 在 src/styles/global.css 补 [x-cloak]{display:none!important}(原仅 shows/index 各自 <style> 有,Layout 作为全站模板缺此规则会导致下拉闪烁)。
  • 移除原链接间的分隔斜杠 <span class="opacity-25">/</span>。
  • 仍保留独立 #lang-switch 容器,不被 footer auth 脚本重写。

语言切换器升级:地球图标 + hover 展开

  • 把按钮内容从 {LOCALE_NAMES[locale]} + chevron 换成地球 SVG 图标(w-[18px] h-[18px],圆+经线+纬线),移除文本标签和 chevron。
  • 行为从「click 切换」改为「hover 展开」,Alpine 加 @mouseenter="open=true" + @mouseleave="open=false";click 仍保留(@click="open=!open")作为触屏兜底。
  • 关键坑:按钮与下拉之间的 mt-2 空隙会让鼠标从按钮移到下拉时 mouseleave 先触发、面板被收起。改为 top-full(紧贴按钮,无外间距),且整个切换器(图标+菜单)作为同一 Alpine 容器,鼠标在内部移动不会触发关闭。
  • 加 x-transition 做淡入淡出(150ms / 100ms)+ py-2 给菜单项留呼吸空间。
  • 后续补充:按钮在地球图标后追加当前语言名文字 {LOCALE_NAMES[locale]}(normal-case text-[12px] tracking-[0.5px] + gap-1.5),即「图标 + 当前语言」显示。

i18n URL 转换改用 astro:i18n 内置函数

  • src/i18n/utils.ts 的 useTranslatedPath 内部改为委托 astro:i18n 的 getRelativeLocaleUrl(targetLocale, clean),自动遵循 i18n 配置(prefixDefaultLocale:false → 默认语言无前缀)。
  • 同文件 getLocaleFromUrl 改为委托 getLocaleByPath(pathname)(保留 LOCALES 校验 + DEFAULT_LOCALE 兜底,try/catch)。
  • astro:i18n 可在 .ts 模块(utils.ts)中 import,前端 frontmatter 同样可用;项目 astro ^7.1.6 支持。
  • 顺手修复首页语言切换器瑕疵:Layout.astro 的 currentPath 原只剥离语言前缀,未去尾随 index.html,导致首页生成 /index.html、/cn/index.html;改为额外 if 末段==='index.html' 去掉,现首页正确生成 / 与 /cn。currentPath 仅用于语言切换器,改动只影响切换器。
  • 验证:构建通过(exit 0),产物 dist/index.html 语言切换器 href 为 / 与 /cn(首页)、/shows 与 /cn/shows(其他页)。

彻底去掉 useTranslatedPath 包装层

  • src/i18n/utils.ts:删除 useTranslatedPath 函数,移除不再使用的 getRelativeLocaleUrl 导入(仅 useTranslatedPath 引用过)。getLocaleFromUrl 仍委托 getLocaleByPath。
  • Layout.astro:frontmatter 直接 import { getRelativeLocaleUrl } from 'astro:i18n',删除 const translatePath = useTranslatedPath(locale);所有调用点(nav 5 项 + 语言切换器 getRelativeLocaleUrl(l, currentPath) + footer 登录/注册/About/Contact)直接改为 getRelativeLocaleUrl(locale, path)。行为与原先一致。

Bug 修复:中文首页切换器链接错误(format:'file' 坑)

  • 站点 build.format:'file',中文首页路由 /cn/ 产物是 dist/cn.html(英文首页是 index.html)。构建期 Astro.url.pathname 取的是产物路径 /cn.html。
  • 原 currentPath 只剥离 index.html,不处理 cn.html,导致中文首页 currentPath=/cn.html,切换器英文项误生成 /cn.html(实际是中文首页)、中文项 /cn/cn.html。
  • 修复:把"去尾随 index.html"改为"去尾随任意 .html"(_last.endsWith('.html') 则去掉末段)。现中英文首页切换器均正确:index.html → ///cn;cn.html → ///cn。
  • 教训:format:'file' 下 Astro.url.pathname 是产物文件名(含 .html),做"当前逻辑路径"推导时必须剥 .html 后缀,不能只认 index.html。