最近给博客加了个英文版,因为不想引入太复杂的 i18n 框架,所以采用了最朴素的方案:直接分目录。
1. 目录结构
简单粗暴,直接在 content 下面新建对应的 en 目录。
post 放中文,post-en 放英文。
src/content/├── note├── note-en # 新增├── post└── post-en # 新增2. 配置 Collection
在 src/content.config.ts 里直接把原来的 schema 复用一下就行。
// 英文翻译文章集合(复用 post schema)const postEn = defineCollection({ loader: glob({ base: "./src/content/post-en", pattern: "**/*.{md,mdx}" }), schema: ({ image }) => baseSchema.extend({ // ...配置和中文版一样 }),});
// 还有 noteEn 同理export const collections = { post, note, postEn, noteEn };3. 路由与工具
手写了个 i18n.ts 来处理路径。
核心逻辑就是判断 URL 是不是以 /en 开头。
export function getLocaleFromPath(path: string): Locale { if (path.startsWith("/en/") || path === "/en") { return "en"; } return "zh-CN";}切换语言的时候,简单的字符串替换:
export function getLocalizedPath(path: string, targetLocale: Locale): string { if (targetLocale === "en") { return `/en${path}`; } return path.replace(/^\/en/, "") || "/";}4. 翻译
UI 上的文本(像“首页”、“关于”这些)搞了个简单的字典对象。
至于文章内容,懒得手动翻,直接写了个脚本调 DeepLX。
部署的时候自动跑,检测到新的中文文章就自动生成英文版放进 post-en。
虽然会把 build 时间拖长一点(毕竟要一个个请求接口),但胜在省心,全自动。
具体实现拆成了两个文件:
src/integrations/astro-translate.ts:Astro 集成入口,在执行npm run build打包的时候自动运行,负责翻译,和写入翻译文件。src/utils/translate.ts:负责干活的工具类,封装 DeepLX API 调用。
集成脚本大概长这样:
import type { AstroIntegration } from "astro";import { translateMarkdown } from "../utils/translate"; // 核心逻辑在这
export function astroTranslate(options: { enabled?: boolean } = {}): AstroIntegration { const { enabled = true } = options;
return { name: "astro-translate", hooks: { // 在 config 完成后、content 同步前执行,确保生成的文件被正确读取 "astro:config:done": async ({ logger }) => { if (!enabled) return;
// 检查环境变量 const apiKey = process.env.DEEPLX_API_KEY; // ... 遍历文件、调用 translateMarkdown、写入文件 ... }, }, };}工具里就是纯粹的 fetch 请求,API 地址格式是 https://api.deeplx.org/<api-key>/translate:
export async function translateText(text: string, options: TranslateOptions) { const { apiKey } = options; // API URL 格式:https://api.deeplx.org/<api-key>/translate const apiUrl = `https://api.deeplx.org/${apiKey}/translate`;
const response = await fetch(apiUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text, source_lang: "ZH", target_lang: "EN" }) }); // ...}只要在 Vercel 环境变量里塞个 DEEPLX_API_KEY 就行。
BTW,看着地址栏的 /en/ 感觉还挺像模像样的。
收工。