From cf42081614722dcf45a5efe0eeb34f19421d0e79 Mon Sep 17 00:00:00 2001 From: wait4xx Date: Sun, 25 Oct 2026 09:14:47 +0800 Subject: [PATCH] =?UTF-8?q?chore(spec):=20=E5=88=9B=E5=BB=BA=20add-blog-i1?= =?UTF-8?q?8n=20=E4=BB=BB=E5=8A=A1=E5=8C=85=EF=BC=88Phase=203=20=E5=85=AB?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E4=B8=89=E8=BD=A6=E9=81=93=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spec: 2026-10-25_add-blog-i18n Co-authored-by: GLM-5.3 --- .spec/specs/2026-10-25_add-blog-i18n/spec.md | 78 +++++++++++++++++++ .spec/specs/2026-10-25_add-blog-i18n/tasks.md | 56 +++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 .spec/specs/2026-10-25_add-blog-i18n/spec.md create mode 100644 .spec/specs/2026-10-25_add-blog-i18n/tasks.md diff --git a/.spec/specs/2026-10-25_add-blog-i18n/spec.md b/.spec/specs/2026-10-25_add-blog-i18n/spec.md new file mode 100644 index 0000000..3346ec6 --- /dev/null +++ b/.spec/specs/2026-10-25_add-blog-i18n/spec.md @@ -0,0 +1,78 @@ +# Phase 3:双语骨架 + 腾讯 TMT 翻译管线 - 项目范围 + + + +## 1. 问题定义 +- **项目目标**:全站中英实时切换(预构建达成毫秒级):/en/ 路由 + UI 字典 + hreflang + 腾讯云 TMT 构建前翻译管线(.en.md 入仓、可锁定、AI 标注) +- **目标用户**:站长(中文写作)/ 英文读者(一键切换) +- **核心价值**:「所有内容实时转英语」由双语预构建实现,零运行时翻译成本 + +## 2. 假设与待确认 + +### 2.1 已确认事实 +- 腾讯密钥已落位 ~/docker_apps/blog/tencent-translate-credentials.txt(0600,标签 Secert* 拼写容错处理) +- Astro 内置 i18n 路由(defaultLocale zh、prefixDefaultLocale false → zh 原路径 / en 前缀 /en/) +- 内容量小(6 文 21 图 1 瞬间),TMT 免费额度(500 万字符/月)完全覆盖 +- 评论共键已定(ArtalkComments pageKey 同 slug) + +### 2.2 关键假设 +- TMT TextTranslate 单请求上限 2000 字符,长文需分块(按段落聚合) +- TMT 译文对文学内容质量有限,AI 标注 + 可人工润色锁定是补偿机制 + +### 2.3 待确认问题 +- [x] 翻译引擎由 LLM 改腾讯 TMT(用户拍板,与 Zotero 插件同款凭据)→ 结论:按 TMT 执行 + +### 2.4 可选解释与取舍 +- content/posts-en/ 独立集合(slug 与 zh 1:1 映射)> 同目录 .en.md 后缀(glob loader 模式更简单、无重名歧义)-> 选独立集合 +- 非文章页(图库/瞬间/关于)/en/ 侧 UI 字典切换 + 内容回退中文标注 > 全量翻译(瞬间/图库 caption 量大价值低)-> 选 UI 切换+回退 + +### 2.5 已证伪路径 +- 无 + +## 3. 功能范围 + +### 3.1 核心功能(MVP) +- [ ] T1 astro i18n 配置 + locale 管道 +- [ ] T2 UI 字典 + 组件串接(Header/Footer/SearchDialog/图库/瞬间/关于) +- [ ] T3 语言切换组件(Header,中英互跳同路径 /en/ 前缀) +- [ ] T4 /en/ 页面骨架(index/archives 文章路由真实双语,其余页 UI 英文化+内容回退标注) +- [ ] T5 TMT 翻译管线(TC3 签名/分块/frontmatter 处理/.en.md 生成/锁定/dry-run) +- [ ] T6 存量 6 文翻译执行 + AI 译文标注组件 +- [ ] T7 hreflang 双向 + 双语 RSS + sitemap locale 覆盖 +- [ ] T8 构建验收(/en/ 路由全量产物 + 翻译产物抽检) + +### 3.2 扩展功能 +- 瞬间/图库 caption 的批量翻译(二期按需) + +### 3.3 不在范围内 +- 上线切换(Phase 4)、Halo 退役(Phase 5) + +## 4. 最小实现路径 +- 最简单可行方案:posts-en 独立集合 + TMT 管线脚本(幂等增量:未变文章不重译)+ /en/ 薄页面复用现有组件 +- 暂不引入:runtime i18n 框架、cookie 语言记忆(切换即跳转,浏览器语言检测二期) +- 不做的抽象/配置化:不多语言框架化(zh/en 硬两语) + +## 5. 技术决策 +- 技术栈:Astro i18n 内置路由 + python TC3 直签(零 SDK 依赖) +- 证据协议:evidence: runs +- 本轮允许改动:astro.config.mjs、src/、content/posts-en/、scripts/translate/、.spec/ +- 本轮不应触碰:content/posts(zh 源只读)、infra/、生产 +- Git integration branch:`spec/2026-10-25_add-blog-i18n` + +### 5.1 验证策略 +- 范围级别:package +- 变更对象:i18n 配置、src 组件、posts-en 集合、翻译脚本 +- 快速检查:`pnpm astro build` +- 集成检查:/en/ 路由产物存在(index+6 文章页)+ hreflang 头存在 + rss.en 产出 +- 全项目检查:staging 更新 + rollback-dryrun 仍绿;仅在构建链或部署脚本变更时升级范围重跑 +- 升级触发:只有改动构建链、部署脚本或 nginx 相关面时,才升级验证范围并记录理由 + +## 6. 成功标准与验证方式 +- [ ] /en/ 与 /en/archives/{6 slug}/ 路由产物全存在 -> verify: task_0008 +- [ ] 翻译管线幂等(重跑零新增 API 调用,锁文件/哈希比对) -> verify: task_0005 +- [ ] AI 译文标注出现在 /en/ 文章页 -> verify: task_0006 +- [ ] hreflang 双向 + en RSS 产出 -> verify: task_0007 + +## 7. 风险与约束 +- TMT 签名实现错误(TC3 步骤繁)→ 脚本内自检模式(--selftest 打印签名串供比对官方文档) -> 管线任务内覆盖 +- 文学译文质量 → AI 标注 + 人工可改 posts-en 文件后 frontmatter locked: true 跳过重译 -> 机制内置 diff --git a/.spec/specs/2026-10-25_add-blog-i18n/tasks.md b/.spec/specs/2026-10-25_add-blog-i18n/tasks.md new file mode 100644 index 0000000..9472c8e --- /dev/null +++ b/.spec/specs/2026-10-25_add-blog-i18n/tasks.md @@ -0,0 +1,56 @@ +# Phase 3:双语骨架 + 腾讯 TMT 翻译管线 - 任务拆解 + +## 使用规则 +- 每个任务 boundary/verify 齐备;verify 首个反引号 span 为执行命令;迁移教训:verify 只读断言(不重跑生成器) + +## 阶段一:实现 + +- [ ] T1 astro i18n 配置 + locale 管道 + - claim: orchestrator + - boundary: 只改 astro.config.mjs(i18n 段)与 src/lib/locale.ts(当前语言工具) + - verify: `pnpm astro build` + +- [ ] T2 UI 字典 + 组件串接 + - depends-on: task_0001 + - claim: op-gitea(mesh 车道,预约 src/i18n/ 与 Footer/SearchDialog/gallery/moments/about) + - boundary: 新建 src/i18n/ui.ts(zh/en 字典)并串接 Footer/SearchDialog/gallery/moments/about 页的静态文案;不碰 Header/BaseLayout(orchestrator 的语言切换在那) + - verify: `pnpm astro build && grep -q "zh" dist/index.html` + +- [ ] T3 语言切换组件(Header 中英互跳) + - depends-on: task_0001 + - claim: orchestrator + - boundary: 只改 src/components/Header.astro 与 src/lib/locale.ts + - verify: `pnpm astro build && grep -q 'href="/en/"' dist/index.html` + +- [ ] T4 /en/ 页面骨架 + AI 译文标注组件 + - depends-on: task_0001 + - claim: orchestrator + - boundary: 新建 src/pages/en/{index.astro,archives/[...slug].astro,archives/index.astro,gallery,moments,about}(复用组件+locale prop);src/components/AiTranslatedBadge.astro;posts-en 集合定义进 content.config.ts + - verify: `pnpm astro build && test -f dist/en/index.html` + +- [ ] T5 TMT 翻译管线 + - claim: op-artalk(mesh 车道,预约 scripts/translate/) + - boundary: 新建 scripts/translate/{tencent_tmt.py,translate_posts.py}:TC3-HMAC-SHA256 签名(--selftest 模式打印中间量)、段落分块(<2000 字符)、frontmatter 透传(title 翻译、locked:true 跳过)、.en.md 生成到 content/posts-en/、原文哈希记录防重译;凭据从宿主 0600 文件读(标签 Secert* 容错);不碰 src/、astro 配置 + - verify: `python3 scripts/translate/translate_posts.py --dry-run` + +- [ ] T6 存量翻译执行 + 标注落页 + - depends-on: task_0004, task_0005 + - claim: op-artalk(执行)+ orchestrator(验收) + - boundary: 真实调用 TMT 译 6 文入 content/posts-en/;/en/archives 模板挂 AiTranslatedBadge(T4 已备) + - verify: `test $(ls content/posts-en/*.md 2>/dev/null | wc -l) -eq 6` + +- [ ] T7 hreflang + 双语 RSS + sitemap locale + - depends-on: task_0004 + - claim: orchestrator + - boundary: BaseLayout 注入 hreflang 双向;src/pages/en/rss.xml.ts;sitemap 配置 i18n + - verify: `pnpm astro build && grep -q hreflang dist/index.html && test -f dist/en/rss.xml` + +- [ ] T8 构建验收 + staging + - depends-on: task_0002, task_0003, task_0004, task_0006, task_0007 + - claim: orchestrator + - boundary: build.sh 跑 staging;抽检 /en/ 三页(首页/一文/图库)渲染 + - verify: `bash infra/deploy/build.sh && test -f ~/docker_apps/blog/www-staging/en/index.html` + +--- + +**当前进度**:由脚本计算,无需手动维护