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

51 lines
6.5 KiB
Markdown
Raw Permalink 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.

# 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。