跳转到内容

国际化 (i18n) 路由

Astro 的国际化 (i18n) 功能允许你为国际用户调整你的项目。这个路由 API 帮助你生成、使用和验证多语言站点产生的 URL。

Astro 的 i18n 路由允许你引入多语言内容,支持配置默认语言、计算相对页面 URL,并接受访问者浏览器提供的首选语言。你还可以为每种语言指定回退语言,以便访问者总能被引导到你站点上的现有内容。

Astro 使用中间件来实现其路由逻辑。该中间件函数被放置在首位,它会等待来自任何其他中间件和每个页面路由的每个Response,然后最终执行自己的逻辑。

这意味着来自你自己的中间件和页面逻辑的操作(例如重定向)会首先运行,你的路由会被渲染,然后 i18n 中间件才会执行它自己的操作,例如验证本地化的 URL 是否对应一个有效的路由。

你也可以选择在 Astro 的 i18n 中间件之外或替代它来添加你自己的 i18n 逻辑,这让你在仍然可以访问 astro:i18n 辅助函数的同时,对你的路由有更多的控制。

所有支持的语言列表(locales)和默认语言(defaultLocale)(必须是 locales 中列出的语言之一)都需要在 i18n 配置对象中指定。此外,你还可以配置更具体的路由和回退行为来匹配你期望的 URL。

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
locales: ["es", "en", "pt-br"],
defaultLocale: "en",
}
})

按语言组织你的内容文件夹,存放本地化内容。在 src/pages/ 内的任何位置创建单独的 /[locale]/ 文件夹,Astro 的基于文件的路由将在相应的 URL 路径上创建你的页面。

你的文件夹名称必须与 locales 中的项完全匹配。只有在你配置了 prefixDefaultLocale: true 来为你的默认语言显示本地化的 URL 路径(例如 /en/about/)时,才需要为你的 defaultLocale 包含一个本地化的文件夹。

  • 目录src
    • 目录pages
      • about.astro
      • index.astro
      • 目录es
        • about.astro
        • index.astro
      • 目录pt-br
        • about.astro
        • index.astro

配置了 i18n 路由后,你现在可以使用astro:i18n 模块中可用的辅助函数(如 getRelativeLocaleUrl())来计算站点内页面的链接。这些生成的链接将始终提供正确的、本地化的路由,并可以帮助你在站点上正确使用或检查 URL。

你仍然可以手动编写链接。

src/pages/es/index.astro
---
import { getRelativeLocaleUrl } from 'astro:i18n';
// defaultLocale is "es"
const aboutURL = getRelativeLocaleUrl("es", "about");
---
<a href="/get-started/">¡Vamos!</a>
<a href={getRelativeLocaleUrl('es', 'blog')}>Blog</a>
<a href={aboutURL}>Acerca</a>

Astro 内置的基于文件的路由会根据你在 src/pages/ 内的文件结构自动为你创建 URL 路由。

当你配置 i18n 路由时,关于此文件结构(以及生成的相应 URL 路径)的信息可供 i18n 辅助函数使用,以便它们可以生成、使用和验证你项目中的路由。这些选项中的许多可以一起使用,以实现更多的自定义和每种语言的灵活性。

你甚至可以选择手动实现自己的路由逻辑以获得更大的控制权。

新增于: astro@3.5.0

此路由选项定义你的默认语言的 URL 是否应使用语言前缀(例如 /en/about/)。

所有非默认的支持语言都使用本地化前缀(例如 /fr//french/),并且内容文件必须位于相应的文件夹中。此配置选项允许你指定默认语言是否也应遵循本地化的 URL 结构。

此设置还决定了默认语言的页面文件必须存在的位置(例如 src/pages/about/src/pages/en/about),因为所有语言的文件结构和 URL 结构必须匹配。

  • "prefixDefaultLocale: false" (默认):默认语言的 URL 将/[locale]/ 前缀。所有其他区域设置都将带有前缀。

  • "prefixDefaultLocale: true":所有 URL,包括你的默认语言,都将带有 /[locale]/ 前缀。

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
locales: ["es", "en", "fr"],
defaultLocale: "en",
routing: {
prefixDefaultLocale: false
}
}
})

这是默认值。当你的默认语言的 URL 带有 /[locale]/ 前缀,且默认语言的文件位于 src/pages/ 的根目录时,请设置此选项。

  • 目录src
    • 目录pages
      • about.astro
      • index.astro
      • 目录es
        • about.astro
        • index.astro
      • 目录fr
        • about.astro
        • index.astro
  • src/pages/about.astro 将生成路由 example.com/about/
  • src/pages/fr/about.astro 将生成路由 example.com/fr/about/
astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
locales: ["es", "en", "fr"],
defaultLocale: "en",
routing: {
prefixDefaultLocale: true
}
}
})

当所有路由的 URL 中都将带有 /locale/ 前缀,并且所有页面内容文件(包括你的 defaultLocale 的文件)都存在于本地化文件夹中时,请设置此选项。

  • 目录src
    • 目录pages
      • index.astro // 注意:此文件始终是必需的
      • 目录en
        • index.astro
        • about.astro
      • 目录es
        • about.astro
        • index.astro
      • 目录pt-br
        • about.astro
        • index.astro
  • 不带区域设置前缀的 URL(例如 example.com/about/)将返回 404 (未找到) 状态码,除非你指定了回退策略

新增于: astro@4.2.0

配置由 src/pages/index.astro 生成的主页 URL (/) 是否重定向到 /<defaultLocale>

设置 prefixDefaultLocale: true 也会在你的 routing 配置对象中自动设置 redirectToDefaultLocale: true。默认情况下,必需的 src/pages/index.astro 文件将自动重定向到你的默认区域设置的索引页面。

你可以通过设置 redirectToDefaultLocale: false 来选择退出此行为。这允许你拥有一个存在于你配置的区域设置文件夹结构之外的站点主页。

新增于: astro@4.6.0

启用此选项后,Astro 将禁用其 i18n 中间件,以便你可以实现自己的自定义逻辑。其他任何 routing 选项(例如 prefixDefaultLocale)都不能与 routing: "manual" 一起配置。

你将负责编写自己的路由逻辑,或与你自己的逻辑一起手动执行 Astro 的 i18n 中间件

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
locales: ["es", "en", "fr"],
defaultLocale: "en",
routing: "manual"
}
})

Astro 为你的中间件提供了辅助函数,因此你可以控制自己的默认路由、异常、回退行为、错误捕获等:redirectToDefaultLocale()notFound()redirectToFallback()

src/middleware.js
import { defineMiddleware } from "astro:middleware";
import { redirectToDefaultLocale } from "astro:i18n"; // function available with `manual` routing
export const onRequest = defineMiddleware(async (ctx, next) => {
if (ctx.url.startsWith("/about")) {
return next();
} else {
return redirectToDefaultLocale(302);
}
})

middleware 函数手动创建 Astro 的 i18n 中间件。这允许你扩展 Astro 的 i18n 路由,而不是完全替换它。

你可以将 middleware路由选项结合你自己的中间件一起运行,使用 sequence 工具来确定顺序。

src/middleware.js
import {defineMiddleware, sequence} from "astro:middleware";
import { middleware } from "astro:i18n"; // Astro's own i18n routing config
export const userMiddleware = defineMiddleware(async (ctx, next) => {
// this response might come from Astro's i18n middleware, and it might return a 404
const response = await next();
// the /about page is an exception and we want to render it
if (ctx.url.startsWith("/about")) {
return new Response("About page", {
status: 200
});
} else {
return response;
}
});
export const onRequest = sequence(
userMiddleware,
middleware({
redirectToDefaultLocale: false,
prefixDefaultLocale: true
})
)

新增于: astro@4.9.0

此路由选项允许你为使用@astrojs/node@astrojs/vercel适配器且配置了siteserver渲染项目,按语言自定义你的域名。

添加 i18n.domains 以将你支持的任何 locales 映射到自定义 URL。

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
site: "https://example.com",
output: "server", // required, with no prerendered pages
adapter: node({
mode: 'standalone',
}),
i18n: {
locales: ["es", "en", "fr", "ja"],
defaultLocale: "en",
routing: {
prefixDefaultLocale: false
},
domains: {
fr: "https://fr.example.com",
es: "https://example.es"
}
}
})

所有未映射的 locales 将遵循你的 prefixDefaultLocales 配置。但是,即使此值为 false,你的 defaultLocale 的页面文件也必须存在于本地化文件夹中。对于上述配置,需要一个 /en/ 文件夹。

使用上述配置

  • 文件 /fr/about.astro 将创建 URL https://fr.example.com/about
  • 文件 /es/about.astro 将创建 URL https://example.es/about
  • 文件 /ja/about.astro 将创建 URL https://example.com/ja/about
  • 文件 /en/about.astro 将创建 URL https://example.com/about

上述 URL 也将由 getAbsoluteLocaleUrl()getAbsoluteLocaleUrlList() 函数返回。

当某种语言的页面不存在时(例如,尚未翻译的页面),你可以选择显示来自另一个 locale 的回退内容,而不是显示 404 页面。当你还没有为每个路由都创建页面,但仍希望为访问者提供一些内容时,这很有用。

你的回退策略包括两部分:选择哪些语言应回退到哪些其他语言(i18n.fallback),以及选择是执行重定向还是重写来显示回退内容(i18n.routing.fallbackType,Astro v4.15.0 中新增)。

例如,当你配置 i18n.fallback: { fr: "es" } 时,Astro 将确保对于 src/pages/es/ 中存在的每个页面,都在 src/pages/fr/ 中构建一个页面。

如果任何页面尚不存在,则将根据你的 fallbackType 创建一个页面:

  • 重定向到相应的 es 路由(默认行为)。
  • 使用 /es/ 页面的内容(i18n.routing.fallbackType: "rewrite")。

例如,下面的配置将 es 设置为任何缺失的 fr 路由的回退区域。这意味着,当 src/pages/fr/my-page.astro 不存在时,访问 example.com/fr/my-page/ 的用户将看到 example.com/es/my-page/ 的内容(不会被重定向),而不是被带到 404 页面。

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
locales: ["es", "en", "fr"],
defaultLocale: "en",
fallback: {
fr: "es"
},
routing: {
fallbackType: "rewrite"
}
}
})

除了将站点支持的 locales 定义为字符串(例如 “en”、“pt-br”)之外,Astro 还允许你将任意数量的浏览器可识别的语言 codes 映射到自定义的 URL path。虽然 `locales` 可以是任何格式的字符串,只要它们与你的项目文件夹结构相对应,但 codes 必须遵循浏览器接受的语法。

locales 数组传递一个对象,其中包含一个 path 键来定义自定义 URL 前缀,以及一个 codes 键来指示映射到此 URL 的语言。在这种情况下,你的 /[locale]/ 文件夹名称必须与 path 的值完全匹配,并且你的 URL 将使用 path 的值生成。

如果你支持多种语言变体(例如 "fr""fr-BR""fr-CA"),并且希望将所有这些变体都映射到同一个 URL /fr/ 下,甚至完全自定义它(例如 /french/),这会很有用。

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
i18n: {
locales: ["es", "en", "fr"],
locales: ["es", "en", {
path: "french", // no slashes included
codes: ["fr", "fr-BR", "fr-CA"]
}],
defaultLocale: "en",
routing: {
prefixDefaultLocale: true
}
}
})

当使用astro:i18n 虚拟模块中的函数根据你的配置计算有效的 URL 路径时(例如 getRelativeLocaleUrl()),请使用 path 作为 locale 的值

此功能有一些限制:

  • site 选项是必需的。
  • output 选项必须设置为 "server"
  • 不能有任何单独的预渲染页面。

Astro 依赖以下 HTTP 标头来支持该功能:

请确保你的服务器代理/托管平台能够提供此信息。未能检索到这些标头将导致 404(状态码)页面。

Astro 的 i18n 路由允许你在按需渲染的页面中访问两个用于浏览器语言检测的属性:Astro.preferredLocaleAstro.preferredLocaleList。所有页面,包括静态预渲染页面,都可以访问 Astro.currentLocale

这些结合了浏览器的 Accept-Language 标头和你的 locales(字符串或 codes)来自动尊重访问者的首选语言。

  • Astro.preferredLocale:如果访问者浏览器的首选区域设置包含在你的 locales 数组中,Astro 可以为你的访问者计算一个首选区域设置。如果没有这样的匹配项,则此值为 undefined。

  • Astro.preferredLocaleList:一个数组,包含了浏览器请求的且你的网站支持的所有区域设置。这将生成一个你的站点和访问者之间所有兼容语言的列表。如果浏览器的请求语言在你的 locales 数组中都找不到,则该值为 []。如果浏览器未指定任何首选语言,则此值将是 i18n.locales

  • Astro.currentLocale:从当前 URL 计算出的区域设置,使用你在 locales 配置中指定的语法。如果 URL 不包含 /[locale]/ 前缀,则该值将默认为 i18n.defaultLocale

为了成功匹配访问者的偏好,请使用与浏览器使用的相同模式提供你的 codes

贡献 社区 赞助