5月27日 21:06

如何在 Astro 中实现国际化(i18n)?

核心答案

Astro 从 4.0 开始内置了 i18n 路由支持,不需要第三方库就能实现多语言网站。在 astro.config.mjs 中配置:

javascript
export 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 文件按语言分目录存放:

shell
src/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/sitemapi18n 配置项,自动生成多语言 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

标签:Astro