diff --git a/src/content/docs/zh-cn/guides/internationalization.mdx b/src/content/docs/zh-cn/guides/internationalization.mdx index 85bdfdf80916b..5c1bf63483ea8 100644 --- a/src/content/docs/zh-cn/guides/internationalization.mdx +++ b/src/content/docs/zh-cn/guides/internationalization.mdx @@ -60,7 +60,7 @@ export default defineConfig({ ### 创建链接 -配置了 i18n 路由后,你现在可以使用诸如 [`astro:i18n` 模块](/zh-cn/reference/api-reference/#国际化astroi18n) 中提供的 [`getRelativeLocaleUrl()`](/zh-cn/reference/api-reference/#getrelativelocaleurl) 辅助函数来计算站点内页面的链接。这些生成的链接将始终提供正确的、本地化的路由,并且可以帮助你正确地使用或检查站点上的 URL。 +配置了 i18n 路由后,你现在可以使用诸如 [`astro:i18n` 模块](/zh-cn/reference/modules/astro-i18n/) 中提供的 [`getRelativeLocaleUrl()`](/zh-cn/reference/modules/astro-i18n/#getrelativelocaleurl) 辅助函数来计算站点内页面的链接。这些生成的链接将始终提供正确的、本地化的路由,并且可以帮助你正确地使用或检查站点上的 URL。 你也可以选择手动编写链接。 @@ -196,7 +196,7 @@ export default defineConfig({ }) ``` -Astro 为你的中间件提供了辅助函数,以便你可以控制自己的默认路由、异常、回退行为、错误捕获等:[`redirectToDefaultLocale()`](/zh-cn/reference/api-reference/#redirecttodefaultlocale)、[`notFound()`](/zh-cn/reference/api-reference/#notfound) 和 [`redirectToFallback()`](/zh-cn/reference/api-reference/#redirecttofallback): +Astro 为你的中间件提供了辅助函数,以便你可以控制自己的默认路由、异常、回退行为、错误捕获等:[`redirectToDefaultLocale()`](/zh-cn/reference/modules/astro-i18n/#redirecttodefaultlocale)、[`notFound()`](/zh-cn/reference/modules/astro-i18n/#notfound) 和 [`redirectToFallback()`](/zh-cn/reference/modules/astro-i18n/#redirecttofallback): ```js title="src/middleware.js" @@ -215,7 +215,7 @@ export const onRequest = defineMiddleware(async (ctx, next) => { [`middleware`](#中间件函数) 函数手动创建 Astro 的 i18n 中间件。这允许你扩展 Astro 的 i18n 路由,而不是完全替换它。 -你可以将带有 [路由选项](#routing)的 `middleware` 与你自己的中间件结合使用,通过使用 [`sequence`](/zh-cn/reference/api-reference/#sequence) 工具来确定顺序运行 `middleware`: +你可以将带有 [路由选项](#routing)的 `middleware` 与你自己的中间件结合使用,通过使用 [`sequence`](/zh-cn/reference/modules/astro-middleware/#sequence) 工具来确定顺序运行 `middleware`: ```js title="src/middleware.js" import { defineMiddleware, sequence } from "astro:middleware"; @@ -341,7 +341,7 @@ export default defineConfig({ }) ``` -当使用来自 [`astro:i18n` 虚拟模块](/zh-cn/reference/api-reference/#国际化astroi18n) 的函数根据你的配置计算有效的 URL 路径时(例如 `getRelativeLocaleUrl()`),[请使用 `path` 作为 `locale` 的值](/zh-cn/reference/api-reference/#getlocalebypath)。 +当使用来自 [`astro:i18n` 虚拟模块](/zh-cn/reference/modules/astro-i18n/) 的函数根据你的配置计算有效的 URL 路径时(例如 `getRelativeLocaleUrl()`),[请使用 `path` 作为 `locale` 的值](/zh-cn/reference/modules/astro-i18n/#getlocalebypath)。 #### 限制 diff --git a/src/content/docs/zh-cn/guides/middleware.mdx b/src/content/docs/zh-cn/guides/middleware.mdx index 3c6e9e734a707..a04a2c83f7b69 100644 --- a/src/content/docs/zh-cn/guides/middleware.mdx +++ b/src/content/docs/zh-cn/guides/middleware.mdx @@ -16,7 +16,7 @@ import Since from '~/components/Since.astro'; 1. 创建 `src/middleware.js|ts`(或者,你也可以创建 `src/middleware/index.js|ts`) -2. 在这个文件中,导出一个接收 [`context` 对象](#context-对象) 的 [`onRequest()`](/zh-cn/reference/api-reference/#onrequest) 函数。注意这里不能是默认导出。 +2. 在这个文件中,导出一个接收 [`context` 对象](#context-对象) 的 [`onRequest()`](/zh-cn/reference/modules/astro-middleware/#onrequest) 函数。注意这里不能是默认导出。 ```js title="src/middleware.js" export function onRequest (context, next) { @@ -158,7 +158,7 @@ declare namespace App { ## 中间件链式调用 -可以使用 [`sequence()`](/zh-cn/reference/api-reference/#sequence) 按指定顺序连接多个中间件: +可以使用 [`sequence()`](/zh-cn/reference/modules/astro-middleware/#sequence) 按指定顺序连接多个中间件: ```js title="src/middleware.js" import { sequence } from "astro:middleware"; diff --git a/src/content/docs/zh-cn/reference/modules/astro-i18n.mdx b/src/content/docs/zh-cn/reference/modules/astro-i18n.mdx new file mode 100644 index 0000000000000..ac59c747fb6f7 --- /dev/null +++ b/src/content/docs/zh-cn/reference/modules/astro-i18n.mdx @@ -0,0 +1,334 @@ +--- +title: 国际化 API 参考 +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 6 +--- +import Since from '~/components/Since.astro'; +import ReadMore from '~/components/ReadMore.astro'; + +

+ +此模块提供了一些函数,帮助你使用项目配置的语言环境设置创建 URL。 + +使用 i18n 路由为你的项目创建路由将依赖于你设置的某些配置值,这些值会影响你的页面路由。使用这些函数创建路由时,请确保考虑到你的个人设置,包括: + +- [`base`](/zh-cn/reference/configuration-reference/#base) +- [`trailingSlash`](/zh-cn/reference/configuration-reference/#trailingslash) +- [`build.format`](/zh-cn/reference/configuration-reference/#buildformat) +- [`site`](/zh-cn/reference/configuration-reference/#site) + +另外,请注意,这些函数为你的 `defaultLocale` 创建的返回 URL 将反映你的 `i18n.routing` 配置。 + +有关功能和使用示例,请参阅[我们的 i18n 路由指南](/zh-cn/guides/internationalization/)。 + +## 从 `astro:i18n` 导入 + +```js +import { + getRelativeLocaleUrl, + getAbsoluteLocaleUrl, + getRelativeLocaleUrlList, + getAbsoluteLocaleUrlList, + getPathByLocale, + getLocaleByPath, + redirectToDefaultLocale, + redirectToFallback, + notFound, + middleware, + requestHasLocale, + } from 'astro:i18n'; +``` + +### `getRelativeLocaleUrl()` + +

+ +**类型:**`(locale: string, path?: string, options?: GetLocaleOptions) => string` +

+ +`getRelativeLocaleUrl(locale: string, path?: string, options?: GetLocaleOptions): string` + +使用此函数来检索一个语言环境的相对路径。如果该语言环境不存在,Astro 会抛出一个错误。 + +```astro +--- +getRelativeLocaleUrl("fr"); +// 返回 /fr + +getRelativeLocaleUrl("fr", ""); +// 返回 /fr + +getRelativeLocaleUrl("fr", "getting-started"); +// 返回 /fr/getting-started + +getRelativeLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog" +}); +// 返回 /blog/fr-ca/getting-started + +getRelativeLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog", + normalizeLocale: false +}); +// 返回 /blog/fr_CA/getting-started +--- +``` + +### `getAbsoluteLocaleUrl()` + +

+ +**类型:**`(locale: string, path: string, options?: GetLocaleOptions) => string` +

+ +当 [`site`] 配置了值时,使用这个函数来检索一个语言环境的绝对路径。如果 [`site`] 没有被配置,该函数将返回一个相对 URL。如果语言环境不存在,Astro 会抛出一个错误。 + + +```astro title="src/pages/index.astro" +--- +// 如果 `site` 被设置为 `https://example.com` + +getAbsoluteLocaleUrl("fr"); +// 返回 https://example.com/fr + +getAbsoluteLocaleUrl("fr", ""); +// 返回 https://example.com/fr + +getAbsoluteLocaleUrl("fr", "getting-started"); +// 返回 https://example.com/fr/getting-started + +getAbsoluteLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog" +}); +// 返回 https://example.com/blog/fr-ca/getting-started + +getAbsoluteLocaleUrl("fr_CA", "getting-started", { + prependWith: "blog", + normalizeLocale: false +}); +// 返回 https://example.com/blog/fr_CA/getting-started +--- +``` + +### `getRelativeLocaleUrlList()` + +

+ +**类型:**`(path?: string, options?: GetLocaleOptions) => string[]` +

+ +像使用 [`getAbsoluteLocaleUrl`](#getrelativelocaleurl) 那样使用此函数,返回所有语言环境的绝对路径列表。 + +### `getAbsoluteLocaleUrlList()` + +

+ +**类型:**`(path?: string, options?: GetLocaleOptions) => string[]` +

+ +像使用 [`getAbsoluteLocaleUrl`](/zh-cn/guides/internationalization/#自定义语言环境路径) 那样使用此函数,返回所有语言环境的绝对路径列表。 + +### `getPathByLocale()` + +

+ +**类型:**`(locale: string) => string` +

+ +当配置了[自定义语言环境路径](/zh-cn/guides/internationalization/#自定义语言环境路径)时,此函数返回与一个或多个 `codes` 关联的 `path`。 + +```js title="astro.config.mjs" +export default defineConfig({ + i18n: { + locales: ["es", "en", { + path: "french", + codes: ["fr", "fr-BR", "fr-CA"] + }] + } +}) +``` + +```astro title="src/pages/index.astro" +--- +import { getPathByLocale } from 'astro:i18n'; + +getPathByLocale("fr"); // 返回 "french" +getPathByLocale("fr-CA"); // 返回 "french" +--- +``` + +### `getLocaleByPath()` + +

+ +**类型:**`(path: string) => string` +

+ +此函数返回与语言环境 `path` 关联的 `code`。 + +```js title="astro.config.mjs" +export default defineConfig({ + i18n: { + locales: ["es", "en", { + path: "french", + codes: ["fr", "fr-BR", "fr-CA"] + }] + } +}) +``` + +```astro title="src/pages/index.astro" +--- +import { getLocaleByPath } from 'astro:i18n'; + +getLocaleByPath("french"); // 返回 "fr",因为这是首个配置的代码 +--- +``` + +### `redirectToDefaultLocale()` + +

+ +**类型:**`(context: APIContext, statusCode?: ValidRedirectStatus) => Promise`
+ +

+ +:::note +仅当 `i18n.routing` 设置为 `"manual"` 时可用。 +::: + +此函数返回一个 `Response`,将重定向到配置的 `defaultLocale`。它接受一个可选的有效重定向状态码。 + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { redirectToDefaultLocale } from "astro:i18n"; + +export const onRequest = defineMiddleware((context, next) => { + if (context.url.pathname.startsWith("/about")) { + return next(); + } else { + return redirectToDefaultLocale(context, 302); + } +}) +``` + +### `redirectToFallback()` + +

+ +**类型:**`(context: APIContext, response: Response) => Promise`
+ +

+ +:::note +仅当 `i18n.routing` 设置为 `"manual"` 时可用。 +::: + +此函数允许你在自己的中间件中使用你的 [`i18n.fallback` 配置](/zh-cn/reference/configuration-reference/#i18nfallback)。 + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { redirectToFallback } from "astro:i18n"; + +export const onRequest = defineMiddleware(async (context, next) => { + const response = await next(); + if (response.status >= 300) { + return redirectToFallback(context, response) + } + return response; +}) +``` + +### `notFound()` + +

+ +**类型:**`(context: APIContext, response?: Response) => Promise | undefined`
+ +

+ +:::note +仅当 `i18n.routing` 设置为 `"manual"` 时可用。 +::: + +当以下情况发生时,在你的路由中间件中使用此函数来返回一个 404 错误: +- 当前路径不是根路径。例如:`/` 或 `/` +- URL 中不包含语言环境代码 + +当传递了一个 `Response`,由此函数发出的新 `Response` 将包含原始响应的相同头信息。 + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { notFound } from "astro:i18n"; + +export const onRequest = defineMiddleware((context, next) => { + const pathNotFound = notFound(context); + if (pathNotFound) { + return pathNotFound; + } + return next(); +}) +``` + +### `middleware()` + +

+ +**类型:**`(options: { prefixDefaultLocale: boolean, redirectToDefaultLocale: boolean }) => MiddlewareHandler`
+ +

+ +:::note +仅当 `i18n.routing` 设置为 `"manual"` 时可用。 +::: + +此函数允许你以编程方式创建 Astro i18n 中间件。 + +当你仍然想要使用默认的 i18n 逻辑,但只在你的网站添加少数例外时,这个功能非常有用。 + +```js title="middleware.js" +import { middleware } from "astro:i18n"; +import { sequence, defineMiddleware } from "astro:middleware"; + +const customLogic = defineMiddleware(async (context, next) => { + const response = await next(); + + // 在这里解析响应后的自定义逻辑。 + // 可以捕获来自 Astro i18n 中间件的响应。 + + return response; +}); + +export const onRequest = sequence(customLogic, middleware({ + prefixDefaultLocale: true, + redirectToDefaultLocale: false +})) +``` + +### `requestHasLocale()` + +

+ +**类型:**`(context: APIContext) => boolean`
+ +

+ +:::note +仅当 `i18n.routing` 设置为 `"manual"` 时可用。 +::: + +检查当前 URL 是否包含已配置的语言环境代码。在内部,此函数将使用 `APIContext#url.pathname`。 + +```js title="middleware.js" +import { defineMiddleware } from "astro:middleware"; +import { requestHasLocale } from "astro:i18n"; + +export const onRequest = defineMiddleware(async (context, next) => { + if (requestHasLocale(context)) { + return next(); + } + return new Response("Not found", { status: 404 }); +}) +``` diff --git a/src/content/docs/zh-cn/reference/modules/astro-middleware.mdx b/src/content/docs/zh-cn/reference/modules/astro-middleware.mdx new file mode 100644 index 0000000000000..5c0ecd3837ef2 --- /dev/null +++ b/src/content/docs/zh-cn/reference/modules/astro-middleware.mdx @@ -0,0 +1,122 @@ +--- +title: 中间件 API 参考 +i18nReady: true +tableOfContents: + minHeadingLevel: 2 + maxHeadingLevel: 6 +--- +import Since from '~/components/Since.astro'; +import ReadMore from '~/components/ReadMore.astro'; + +

+ +中间件使你能拦截请求和响应,并在每次渲染页面或端点时动态注入行为。有关功能和用法示例,请参考 [中间件指南](/zh-cn/guides/middleware/)。 + +## 从 `astro:middleware` 导入 + +```js +import { + sequence, + createContext, + trySerializeLocals, + defineMiddleware, + } from 'astro:middleware'; +``` + +### `defineMiddleware()` + +你可以导入并使用 `defineMiddleware()` 实用函数来提供类型安全: + +```ts +// src/middleware.ts +import { defineMiddleware } from "astro:middleware"; + +// `context` 和 `next` 会自动被类型化 +export const onRequest = defineMiddleware((context, next) => { + +}); +``` + +### `sequence()` + +

+ +**类型:**`(...handlers: MiddlewareHandler[]) => MiddlewareHandler` +

+ +一个接受中间件函数作为参数的函数,它将按照它们传递的顺序执行它们。 + +```js title="src/middleware.js" +import { sequence } from "astro:middleware"; + +async function validation(_, next) {...} +async function auth(_, next) {...} +async function greeting(_, next) {...} + +export const onRequest = sequence(validation, auth, greeting); +``` + +### `createContext()` + +

+ +**类型:**`(context: CreateContext) => APIContext`
+ +

+ +一个底层 API,用于创建一个 [`APIContext`](/zh-cn/reference/api-reference/#端点上下文) 以传递给 Astro 中间件的 `onRequest()` 函数。 + +此函数可以由集成/适配器用于执行 Astro 中间件。 + +### `trySerializeLocals()` + +

+ +**类型:**`(value: unknown) => string`
+ +

+ +一个底层 API,它接受任何值并尝试返回它的序列化版本(一个字符串)。如果该值无法序列化,该函数将抛出一个运行时错误。 + +## 中间件导出 + +在 `src/middleware.js` 中定义项目的中间件时,导出以下用户定义的函数: + +### `onRequest()` + +**类型:**`(context: APIContext, next: MiddlewareNext) => Promise | Response | Promise | void` + +一个在 `src/middleware.js` 里的必须导出的函数,它将在每次渲染页面或端点时被调用。它接受两个参数:[context](#context) 和 [next()](#next)。`onRequest()` 必须返回一个 `Response`:要么直接返回,要么通过调用 `next()` 返回。 + +```js title="src/middleware.js" +export function onRequest (context, next) { + // 拦截一个请求的响应数据 + // 可选修改响应 + // 直接返回一个 Response 对象,或者调用 `next()` 的结果 + return next(); +}; +``` + +你的 `onRequest()` 函数将使用以下参数调用: + +#### `context` + +

+ +**类型:**`APIContext` +

+ +`onRequest()` 的第一个参数是一个上下文对象。它反映了许多 `Astro` 全局属性。 + +有关更多信息,请参阅 [端点上下文](/zh-cn/reference/api-reference/#端点上下文)。 + +#### `next()` + +

+ +**类型:**`(rewritePayload?: string | URL | Request) => Promise`
+

+ +`onRequest()` 的第二个参数是一个调用链中的所有后续中间件,并返回一个 `Response` 的函数。例如,其他中间件可以修改响应的 HTML 主体,等待 `next()` 的结果将允许你的中间件响应这些更改。 + +自从 Astro v4.13.0,`next()` 接受一个可选的 URL 路径参数,形式为字符串、`URL` 或 `Request`,用于[重写](/zh-cn/guides/routing/#重写)当前请求而不重新触发新的渲染阶段。