如何在 Astro 中实现国际化(i18n)?
核心答案
Astro 从 4.0 开始内置了 i18n 路由支持,不需要第三方库就能实现多语言网站。在 astro.config.mjs 中配置:
javascriptexport default defineConfig({ i18n: { locales: ['en', 'zh', 'ja'], defaultLocale: 'en', routing: { prefixDefaultLocale: false, }, }, });
这样默认语言走 /about,其他语言走 /zh/about、/ja/about。配合 astro:i18n 模块提供的 getRelativeLocaleUrl() 生成各语言链接,再用中间件做语言检测和重定向,一个完整的多语言站点就跑起来了。
路由策略怎么选?
子目录路由(/zh/about)是主流方案,配置简单、共享域名权重,适合大多数项目。子域名方案(zh.example.com)需要额外 DNS 和证书配置,只在团队和资源充足时考虑。
默认语言是否加前缀,取决于你的目标用户——如果主要受众是英语用户,prefixDefaultLocale: false 让 URL 更干净;如果各语言地位平等,统一加前缀更一致。
翻译文件怎么组织?
UI 文本用 JSON 文件按语言分目录存放:
shellsrc/i18n/ en/common.json zh/common.json ja/common.json
页面内容则用 Astro 的内容集合(Content Collections),按语言建集合或用 slug 后缀区分。读取时根据 Astro.currentLocale 过滤对应语言的内容。
SEO 要注意什么?
三件事:hreflang 标签、规范 URL、多语言站点地图。
astro<link rel="alternate" hreflang="en" href="/en" /> <link rel="alternate" hreflang="zh" href="/zh" /> <link rel="alternate" hreflang="x-default" href="/" />
配合 @astrojs/sitemap 的 i18n 配置项,自动生成多语言 sitemap。漏掉 hreflang 是最常见的错误,搜索引擎会把不同语言的页面当作重复内容。
中间件怎么处理语言检测?
typescript// src/middleware.ts import { defineMiddleware } from 'astro:middleware'; export const onRequest = defineMiddleware((context, next) => { const locale = context.url.pathname.split('/')[1]; const supported = ['en', 'zh', 'ja']; if (!supported.includes(locale)) { const browserLang = context.request.headers .get('accept-language') ?.split(',')[0].split('-')[0] || 'en'; const target = supported.includes(browserLang) ? browserLang : 'en'; return context.redirect(`/${target}${context.url.pathname}`); } context.locals.locale = locale; return next(); });
根据 Accept-Language 头判断浏览器语言,首次访问自动跳转。
追问
-
astro-i18next 和原生 i18n 有什么区别? 原生只管路由,不管翻译加载;astro-i18next 补了翻译函数和运行时,但增加了包体积。Astro 5 之后推荐原生路由 + 自建翻译工具函数。
-
SSR 模式下 i18n 有什么坑? 静态模式下每个语言预生成页面没问题;SSR 模式要注意中间件里不能阻塞渲染,语言检测逻辑必须同步完成,且需要处理 cookie 记住用户偏好。
-
RTL 语言怎么处理? 在根布局根据
locale动态设置dir属性:<html dir={isRTL ? 'rtl' : 'ltr'}>,再用 CSS 逻辑属性(margin-inline-start)替代margin-left。