diff --git a/.github/workflows/preview-docs.yml b/.github/workflows/preview-docs.yml
index 675808397..15b123a81 100644
--- a/.github/workflows/preview-docs.yml
+++ b/.github/workflows/preview-docs.yml
@@ -30,9 +30,13 @@ jobs:
id: generate-docs
env:
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
- HEAD_REF: ${{ github.head_ref }}
run: |
- OUTPUT=$(fern generate --docs --preview --id "$HEAD_REF" --instance fern-api.docs.buildwithfern.com/learn 2>&1) || true
+ # Omit --id so each run gets a fresh preview hash. Pinning the id to the
+ # branch name makes the CLI reuse the same preview deploy across pushes,
+ # which masks staleness when reviewers re-test after a force-push or a
+ # CDN cache pin to old content. A throwaway preview per push is cheap
+ # and lines up 1:1 with the comment posted by this workflow.
+ OUTPUT=$(fern generate --docs --preview --instance fern-api.docs.buildwithfern.com/learn 2>&1) || true
echo "$OUTPUT"
URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()')
echo "preview_url=$URL" >> $GITHUB_OUTPUT
@@ -80,5 +84,4 @@ jobs:
uses: thollander/actions-comment-pull-request@v2.4.3
with:
filePath: comment.md
- comment_tag: preview-docs
- mode: upsert
+ mode: create
diff --git a/fern/docs.yml b/fern/docs.yml
index 077b5db90..66300e89b 100644
--- a/fern/docs.yml
+++ b/fern/docs.yml
@@ -10,6 +10,11 @@ instances:
title: Fern Documentation
+translations:
+ - lang: en
+ default: true
+ - lang: zh
+
ai-search:
location:
- docs
diff --git a/fern/fern.config.json b/fern/fern.config.json
index c9d7305b4..788fb6032 100644
--- a/fern/fern.config.json
+++ b/fern/fern.config.json
@@ -1,4 +1,4 @@
{
"organization": "fern",
- "version": "4.62.3"
+ "version": "5.7.5"
}
diff --git a/fern/products/cli-api-reference/cli-changelog/2026-05-01.mdx b/fern/products/cli-api-reference/cli-changelog/2026-05-01.mdx
index 027c5e208..f29765b95 100644
--- a/fern/products/cli-api-reference/cli-changelog/2026-05-01.mdx
+++ b/fern/products/cli-api-reference/cli-changelog/2026-05-01.mdx
@@ -37,7 +37,7 @@ spec.
## 5.6.1
-**`(fix):`** Fix translated docs pages failing to resolve shared snippets (`` and ``).
+**`(fix):`** Fix translated docs pages failing to resolve shared snippets (Markdown and Code `src` includes).
Snippet references are now resolved before registering translations, with locale-aware loading that prefers
translated snippets (e.g., `translations/zh/snippets/foo.mdx`) when available.
diff --git a/fern/translations/zh/fern/docs.yml b/fern/translations/zh/fern/docs.yml
new file mode 100644
index 000000000..89056eef2
--- /dev/null
+++ b/fern/translations/zh/fern/docs.yml
@@ -0,0 +1,55 @@
+products:
+ - display-name: 首页
+ path: ./products/home/home.yml
+ subtitle: 提升开发者体验的产品
+
+ - slug: sdks
+ display-name: SDK
+ path: ./products/sdks/sdks.yml
+ subtitle: 生成多种语言的客户端库
+
+ - slug: docs
+ display-name: 文档
+ path: ./products/docs/docs.yml
+ subtitle: 生成精美的交互式文档网站
+
+ - slug: dashboard
+ display-name: 仪表板
+ path: ./products/dashboard/dashboard.yml
+ subtitle: 管理您的 Fern 项目和设置
+
+ - slug: cli-api-reference
+ display-name: CLI 参考
+ path: ./products/cli-api-reference/cli-api-reference.yml
+ subtitle: 管理和配置您的 Fern 项目
+
+ - slug: api-definitions
+ display-name: API 定义
+ path: ./products/api-def/api-def.yml
+ subtitle: 导入和配置您的 API 规范
+
+ - display-name: OpenAPI
+ subtitle: 定义 REST 和 webhook API
+
+ - display-name: AsyncAPI
+ subtitle: 定义事件驱动和 WebSocket API
+
+ - display-name: OpenRPC
+ subtitle: 定义 JSON-RPC API
+
+ - display-name: gRPC
+ subtitle: 使用 Protocol Buffers 定义 API
+
+ - display-name: Fern 定义
+ subtitle: 使用 Fern 的 YAML 格式定义 API
+
+navbar-links:
+ - type: minimal
+ text: 预约演示
+ url: https://buildwithfern.com/book-demo?utm_source=fern-docs
+ - type: secondary
+ text: 登录
+ url: https://dashboard.buildwithfern.com/login?utm_source=fern-docs
+ - type: filled
+ text: 免费开始
+ url: https://dashboard.buildwithfern.com/sign-up?redirect_on_login=%2Fget-started&utm_source=fern-docs
diff --git a/fern/translations/zh/fern/products/api-def/api-def.yml b/fern/translations/zh/fern/products/api-def/api-def.yml
new file mode 100644
index 000000000..b08ac7372
--- /dev/null
+++ b/fern/translations/zh/fern/products/api-def/api-def.yml
@@ -0,0 +1,169 @@
+navigation:
+ - section: 概览
+ contents:
+ - page: 什么是 API 定义?
+ - page: 项目结构
+ - section: OpenAPI
+ slug: openapi
+ contents:
+ - page: 概览
+ - page: 覆盖层(Overlays)
+ - page: 覆盖(Overrides)
+ - page: 身份验证
+ - page: 服务器
+ - page: 同步您的规范
+ slug: sync-your-open-api-specification
+ - section: 端点
+ slug: endpoints
+ contents:
+ - page: HTTP JSON 端点
+ slug: http
+ - page: Webhooks
+ - page: 多部分表单上传
+ slug: multipart
+ - page: 服务器发送事件
+ slug: sse
+ - section: 扩展
+ slug: extensions
+ contents:
+ - page: 概览
+ - page: API 版本
+ - page: 受众
+ - page: 可用性
+ - page: 基础路径
+ - page: 默认值
+ - page: 枚举描述、名称和可用性
+ slug: enum-descriptions-and-names
+ - page: 请求与响应示例
+ - page: API Explorer 控制
+ - page: 全局请求头
+ - page: 忽略元素
+ - page: SDK 方法名称
+ slug: method-names
+ - page: SDK 变量
+ - page: 标签显示名称
+ - page: 参数名称
+ - page: 属性名称
+ - page: 幂等性
+ - page: 分页
+ - page: 重试行为
+ - page: Schema 名称
+ - page: 服务器名称和 URL 模板化
+ - section: 集成您的服务器框架
+ slug: frameworks
+ contents:
+ - page: FastAPI
+ slug: fastapi
+ - page: generators.yml 参考
+ - section: AsyncAPI
+ slug: asyncapi
+ contents:
+ - page: 概览
+ - page: 覆盖(Overrides)
+ - page: 身份验证
+ - page: 服务器
+ - page: 同步您的规范
+ slug: sync-your-async-api-specification
+ - section: 通道
+ slug: channels
+ contents:
+ - page: 发布/订阅操作
+ slug: pubsub
+ - page: 消息格式
+ slug: messages
+ - page: 消息绑定
+ slug: bindings
+ - section: 扩展
+ slug: extensions
+ contents:
+ - page: 概览
+ - page: 受众
+ - page: 可用性
+ - page: 请求与响应示例
+ - page: 忽略元素
+ - page: 服务器名称
+ - section: OpenRPC
+ slug: openrpc
+ contents:
+ - page: 概览
+ - page: 覆盖(Overrides)
+ - page: 身份验证
+ - page: 服务器
+ - page: 同步您的规范
+ slug: sync-your-open-rpc-specification
+ - section: 方法
+ slug: methods
+ contents:
+ - page: JSON-RPC 方法
+ slug: rpc-methods
+ - section: 扩展
+ slug: extensions
+ contents:
+ - page: 概览
+ - page: 受众
+ - page: 可用性
+ - page: 请求与响应示例
+ - page: 忽略元素
+ - page: SDK 方法名称
+ slug: method-names
+ - page: SDK 组名称
+ - page: 服务器名称
+ - section: gRPC
+ slug: grpc
+ contents:
+ - page: 概览
+ - page: 覆盖(Overrides)
+ - page: 身份验证
+ - page: 服务器
+ - page: 同步您的规范
+ slug: sync-your-g-rpc-specification
+ - section: 服务
+ slug: services
+ contents:
+ - page: gRPC 服务
+ slug: grpc-services
+ - page: 流式传输
+ slug: streaming
+ - page: 错误处理
+ slug: errors
+ - page: generators.yml 参考
+ - section: Fern 定义
+ slug: ferndef
+ contents:
+ - page: 概览
+ - page: 身份验证
+ - page: 类型
+ - section: 端点
+ contents:
+ - page: 概览
+ - page: HTTP JSON 端点
+ slug: http
+ - page: 多部分表单上传
+ slug: multipart
+ - page: 字节
+ slug: bytes
+ - page: 服务器发送事件
+ slug: sse
+ - section: 高级
+ contents:
+ - page: Webhooks
+ - page: WebSockets
+ slug: websockets
+ - page: 错误
+ - page: 导入
+ - page: 示例
+ - page: 受众
+ - page: 可用性
+ - section: api.yml 参考
+ slug: api-yml
+ contents:
+ - page: 概览
+ - page: 环境
+ - page: 全局请求头
+ - page: 错误
+ - section: 集成
+ contents:
+ - page: 包
+ - page: 依赖其他 API
+ - page: 导出到 OpenAPI
+ slug: export-openapi
diff --git a/fern/translations/zh/fern/products/cli-api-reference/cli-api-reference.yml b/fern/translations/zh/fern/products/cli-api-reference/cli-api-reference.yml
new file mode 100644
index 000000000..7b8e49765
--- /dev/null
+++ b/fern/translations/zh/fern/products/cli-api-reference/cli-api-reference.yml
@@ -0,0 +1,8 @@
+navigation:
+ - section: CLI 参考
+ contents:
+ - page: 开始使用 Fern CLI
+ slug: overview
+ - page: 全局选项
+ slug: options
+ - page: 命令
diff --git a/fern/translations/zh/fern/products/dashboard/dashboard.yml b/fern/translations/zh/fern/products/dashboard/dashboard.yml
new file mode 100644
index 000000000..2fe07d4ce
--- /dev/null
+++ b/fern/translations/zh/fern/products/dashboard/dashboard.yml
@@ -0,0 +1,15 @@
+navigation:
+ - section: 入门
+ contents:
+ - page: 概览
+ - section: 配置
+ contents:
+ - page: 成员权限
+ slug: permissions
+ - page: 连接 GitHub 仓库
+ slug: github-repo
+ - page: 设置 SSO
+ slug: sso
+ - page: 密码保护
+ - page: 自定义域名
+ - page: PDF 导出
diff --git a/fern/translations/zh/fern/products/docs/docs.yml b/fern/translations/zh/fern/products/docs/docs.yml
new file mode 100644
index 000000000..385746cf9
--- /dev/null
+++ b/fern/translations/zh/fern/products/docs/docs.yml
@@ -0,0 +1,248 @@
+navigation:
+ - section: 入门
+ contents:
+ - page: 概览
+ - page: 工作原理
+ - page: 快速开始
+ - page: 自助设置
+ - page: 项目结构
+ - section: 配置
+ contents:
+ - page: 概览
+ - page: 站点级设置
+ slug: site-level-settings
+ - section: 导航
+ contents:
+ - page: 章节、页面与文件夹
+ slug: navigation
+ - page: 标签页与标签变体
+ slug: tabs
+ - page: 版本
+ - page: 产品
+ - page: 更新日志页面
+ slug: changelogs
+ - page: 页面级设置
+ slug: page-level-settings
+ - section: 编写内容
+ contents:
+ - page: Markdown 基础
+ slug: markdown-basics
+ - page: Markdown 中的富媒体
+ slug: markdown-media
+ - section: 组件
+ contents:
+ - page: 概览
+ - page: 折叠面板
+ slug: accordions
+ - page: 锚点
+ - page: 旁注
+ - page: 徽章
+ slug: badges
+ - page: 按钮
+ - page: 提示框
+ slug: callouts
+ - page: 卡片
+ slug: cards
+ - page: 代码块
+ slug: code-blocks
+ - page: 复制
+ - page: 下载
+ - page: 端点请求片段
+ slug: request-snippet
+ - page: 端点响应片段
+ slug: response-snippet
+ - page: 端点 Schema 片段
+ - page: Webhook 负载片段
+ slug: webhook-payload-snippet
+ - page: 文件
+ slug: files
+ - page: 框架
+ slug: frames
+ - page: 图标
+ slug: icons
+ - page: If
+ slug: if
+ - page: 缩进
+ slug: indent
+ - page: 参数字段
+ slug: parameter-fields
+ - page: 可运行端点
+ - page: Schema
+ - page: Schema 片段
+ slug: schema-snippet
+ - page: 步骤
+ slug: steps
+ - page: 表格
+ slug: tables
+ - page: 标签页
+ slug: tabs
+ - page: 工具提示
+ slug: tooltips
+ - page: 版本
+ slug: versions
+ - page: Fern 编辑器
+ slug: fern-editor
+ - page: 可复用片段
+ - page: 组件演示
+ slug: demo
+ - section: AI 功能
+ contents:
+ - page: 概览
+ - page: Fern Writer
+ - page: AI 生成的示例
+ slug: ai-examples
+ - section: llms-txt
+ contents:
+ - page: 概览
+ slug: llms-txt
+ - page: 自定义 LLM 输出
+ - page: Agent 指令
+ - page: 分析与集成
+ slug: llms-txt-analytics
+ - page: MCP 服务器
+ slug: mcp-server
+ - section: Ask Fern
+ slug: ask-fern
+ contents:
+ - page: 概览
+ slug: overview
+ - section: 设置
+ contents:
+ - page: Slack 应用
+ slug: slack-app
+ - page: 自定义指引
+ slug: guidance
+ - page: 额外内容来源
+ slug: content-sources
+ - page: 独立搜索小部件
+ slug: search-widget
+ - section: 预览与发布
+ contents:
+ - page: 预览更改
+ - page: 发布您的文档
+ - page: 设置您的域名
+ - section: 自定义
+ contents:
+ - page: 公告横幅
+ - page: 嵌入模式
+ - page: 隐藏内容
+ - page: 隐藏页面示例
+ slug: hidden-page
+ - page: 搜索
+ - page: 用户反馈
+ - page: 自定义 CSS 与 JS
+ - page: CSS 选择器参考
+ - page: 自定义 React 组件
+ - page: 页眉与页脚
+ - page: 全局主题
+ - section: 本地化
+ contents:
+ - page: 概览
+ - section: 无障碍
+ contents:
+ - page: 概览
+ - page: 键盘快捷键
+ - section: API 参考
+ contents:
+ - page: 概览
+ - section: 生成
+ contents:
+ - page: REST API 参考
+ slug: generate-api-ref
+ - page: Webhook 参考
+ slug: generate-webhook-ref
+ - page: WebSocket 参考
+ slug: generate-websocket-ref
+ - page: OpenRPC 参考
+ slug: generate-openrpc-ref
+ - page: gRPC 参考
+ slug: generate-grpc-ref
+ - page: GraphQL 参考
+ slug: generate-graphql-ref
+ - page: 库参考
+ slug: library-reference
+ - section: 自定义
+ contents:
+ - page: 自定义 API 参考布局
+ - page: 受众
+ - page: 在 API 参考中编写 Markdown
+ - section: 代码探索
+ contents:
+ - page: SDK 代码片段
+ - page: HTTP 代码片段
+ - page: API Explorer
+ slug: api-explorer
+ - section: SEO 与 GEO
+ slug: seo
+ contents:
+ - page: 概览
+ - page: 设置 SEO 元数据
+ - page: 配置 slug
+ - page: 重定向
+ - section: 身份验证
+ contents:
+ - page: 概览
+ - section: 设置
+ slug: setup
+ contents:
+ - page: 密码保护
+ - page: SSO
+ - page: JWT
+ slug: jwt
+ - page: OAuth
+ slug: oauth
+ - section: 功能
+ slug: features
+ contents:
+ - page: 基于角色的访问控制 (RBAC)
+ slug: rbac
+ - page: API 密钥注入
+ - section: 安全
+ contents:
+ - page: 概览
+ - section: 自托管
+ contents:
+ - page: 概览
+ - page: 设置自托管文档
+ slug: set-up
+ - page: 身份验证
+ slug: authentication
+ - page: 预览
+ slug: previews
+ - page: 健康检查端点
+ - section: 分析与集成
+ slug: integrations
+ contents:
+ - page: 概览
+ - page: Intercom
+ slug: support/intercom
+ - page: Google
+ slug: analytics/google
+ - page: PostHog
+ slug: analytics/posthog
+ - page: Fullstory
+ slug: analytics/fullstory
+ - page: Segment
+ slug: analytics/segment
+ - page: Mixpanel
+ slug: analytics/mixpanel
+ - page: Postman
+ - page: Context7
+ slug: context7
+ - page: LaunchDarkly 功能标志
+ - section: 开发者工具
+ contents:
+ - page: 编排 GitHub 发布
+ - page: 自动更新最后更新日期
+ - page: Cursor
+ - page: GitLab
+ - page: Vale
+ - page: 查看 Markdown
+ - page: 下载 OpenAPI 规范
+ slug: openapi-spec
+ - page: 下载 AsyncAPI 规范
+ slug: asyncapi-spec
+ - section: 资源
+ contents:
+ - page: Stainless 与 Fern 对比
+ slug: stainless-comparison
diff --git a/fern/translations/zh/fern/products/home/home.yml b/fern/translations/zh/fern/products/home/home.yml
new file mode 100644
index 000000000..3b818db6a
--- /dev/null
+++ b/fern/translations/zh/fern/products/home/home.yml
@@ -0,0 +1,2 @@
+navigation:
+ - page: 首页
diff --git a/fern/translations/zh/fern/products/sdks/sdks.yml b/fern/translations/zh/fern/products/sdks/sdks.yml
new file mode 100644
index 000000000..44435b1b9
--- /dev/null
+++ b/fern/translations/zh/fern/products/sdks/sdks.yml
@@ -0,0 +1,171 @@
+navigation:
+ - section: 概览
+ contents:
+ - page: 简介
+ - page: 工作原理
+ - page: 快速开始
+ slug: quickstart
+ - section: 使用 SDK
+ slug: overview
+ contents:
+ - page: 项目结构
+ slug: project-structure
+ - page: 添加自定义代码
+ slug: custom-code
+ - page: 功能特性
+ slug: capabilities
+ - page: Fern Autorelease
+ slug: autorelease
+ - section: 生成器
+ contents:
+ - section: TypeScript
+ slug: typescript
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 npm
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - page: 动态身份验证
+ slug: dynamic-authentication
+ - page: 启用 serde 层
+ slug: serde-layer
+ - section: Python
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 PyPI
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - page: 动态身份验证
+ slug: dynamic-authentication
+ - page: aiohttp 支持
+ slug: aiohttp-support
+ - section: Go
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 作为 Go 模块发布
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - section: Java
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 Maven Central
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - section: .NET
+ slug: csharp
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 NuGet
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - page: 版本兼容性
+ - section: PHP
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 Packagist
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - section: Ruby
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 RubyGems
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - page: 添加自定义代码
+ slug: custom-code
+ - section: Swift
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 作为 Swift 包发布
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - section: Rust
+ contents:
+ - page: 生成 SDK
+ slug: quickstart
+ - page: 发布到 crates.io
+ slug: publishing
+ - page: 配置
+ slug: configuration
+ - section: Postman
+ contents:
+ - page: 快速开始
+ slug: quickstart
+ - page: 发布到 Postman
+ slug: publishing
+ - section: SDK 设计
+ slug: deep-dives
+ contents:
+ - page: SDK 用户特性
+ slug: sdk-user-features
+ - page: 自定义 README
+ slug: readme
+ - page: 自定义方法名称
+ slug: customize-method-names
+ - page: 按受众过滤端点
+ slug: audiences
+ - page: 服务器 URL 模板化
+ slug: server-url-templating
+ - page: Webhook 签名验证
+ slug: webhook-signature-verification
+ - section: 请求行为
+ slug: deep-dives
+ contents:
+ - page: 全局请求头
+ slug: global-headers
+ - page: 动态身份验证
+ slug: dynamic-authentication
+ - page: 自动分页
+ slug: auto-pagination
+ - page: 幂等性请求头
+ slug: idempotency
+ - page: 带退避的重试
+ slug: retries-with-backoff
+ - section: 预览与测试
+ slug: deep-dives
+ contents:
+ - page: 本地 SDK 预览
+ slug: local-previews
+ - page: 测试
+ slug: testing
+ - section: 托管
+ slug: deep-dives
+ contents:
+ - page: 自托管 SDK
+ slug: self-hosted
+ - section: 参考
+ contents:
+ - page: generators.yml
+ slug: generators-yml
+ - section: 资源
+ contents:
+ - page: Fern 与 OpenAPI Generator 对比
+ slug: openapi-generator
diff --git a/fern/translations/zh/products/api-def/asyncapi/auth.mdx b/fern/translations/zh/products/api-def/asyncapi/auth.mdx
new file mode 100644
index 000000000..fce6b483e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/auth.mdx
@@ -0,0 +1,185 @@
+---
+title: 身份验证
+subtitle: 为事件驱动的 API 建模身份验证方案,如 Bearer、Basic 和 API Key。
+sidebar-title: 身份验证
+---
+
+
+身份验证方案的配置在 AsyncAPI 的 `components.securitySchemes` 部分中进行。
+
+```yml title="asyncapi.yml" {2-3}
+components:
+ securitySchemes:
+ ...
+```
+
+
+要在所有操作中应用安全方案,请在 AsyncAPI 规范的 `security` 部分引用 `securityScheme`。
+
+```yml title="asyncapi.yml" {3, 5-6}
+components:
+ securitySchemes:
+ AuthScheme:
+ ...
+security:
+ - AuthScheme: []
+```
+
+
+## Bearer 安全方案
+
+首先在 `asyncapi.yml` 中定义一个 `bearer` 安全方案:
+
+```yml title="asyncapi.yml" {3-5}
+components:
+ securitySchemes:
+ BearerAuth:
+ type: http
+ scheme: bearer
+```
+
+这将生成一个 SDK,用户需要提供一个名为 `token` 的必需参数。
+
+```ts index.ts
+const client = new Client({
+ token: "ey34..."
+})
+```
+
+如果你想控制变量命名和要扫描的环境变量,请使用以下配置:
+
+```yml title="asyncapi.yml" {4-6}
+components:
+ securitySchemes:
+ BearerAuth:
+ type: http
+ scheme: bearer
+ x-fern-token:
+ name: authToken
+ env: AUTH_TOKEN
+```
+
+## API Key 安全方案
+
+首先在 `asyncapi.yml` 中定义一个 `apiKey` 安全方案:
+
+```yml title="asyncapi.yml" {3-6}
+components:
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+```
+
+这将生成一个 SDK,用户需要提供一个名为 `apiKey` 的必需参数。
+
+```ts index.ts
+const client = new Client({
+ apiKey: "my-api-key"
+})
+```
+
+### 自定义 API Key 变量名称
+
+如果你想控制变量命名和要扫描的环境变量,请使用以下配置:
+
+```yml title="asyncapi.yml" {5-7}
+components:
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ x-fern-api-key:
+ name: customApiKey
+ env: CUSTOM_API_KEY
+ in: header
+ name: X-API-Key
+```
+
+## Basic 安全方案
+
+首先在 `asyncapi.yml` 中定义一个 `basic` 安全方案:
+
+```yml title="asyncapi.yml" {3-5}
+components:
+ securitySchemes:
+ BasicAuth:
+ type: http
+ scheme: basic
+```
+
+这将生成一个 SDK,用户需要提供 `username` 和 `password`。
+
+```ts index.ts
+const client = new Client({
+ username: "john@example.com",
+ password: "password123"
+})
+```
+
+### 自定义基本认证变量名称
+
+如果你想控制变量命名和要扫描的环境变量,请使用以下配置:
+
+```yml title="asyncapi.yml" {4-7}
+components:
+ securitySchemes:
+ BasicAuth:
+ type: http
+ scheme: basic
+ x-fern-username:
+ name: email
+ env: EMAIL
+ x-fern-password:
+ name: pass
+ env: PASSWORD
+```
+
+## OAuth2 安全方案
+
+
+
+AsyncAPI 规范支持 OAuth2 身份验证:
+
+```yml title="asyncapi.yml" {3-11}
+components:
+ securitySchemes:
+ OAuth2:
+ type: oauth2
+ flows:
+ authorizationCode:
+ authorizationUrl: https://example.com/oauth/authorize
+ tokenUrl: https://example.com/oauth/token
+ scopes:
+ read: Read access to resources
+ write: Write access to resources
+```
+
+这将生成一个支持事件驱动操作的 OAuth2 流程的 SDK。
+
+## 多个安全方案
+
+你可以指定多个安全方案并将它们应用于不同的操作:
+
+```yml title="asyncapi.yml" {2-12, 16-17}
+components:
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+ BearerAuth:
+ type: http
+ scheme: bearer
+ OAuth2:
+ type: oauth2
+ flows: ...
+
+operations:
+ sendMessage:
+ security:
+ - ApiKeyAuth: []
+ - BearerAuth: []
+```
+
+这允许不同的操作根据需要使用不同的身份验证方法。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/automation.mdx b/fern/translations/zh/products/api-def/asyncapi/automation.mdx
new file mode 100644
index 000000000..3afc1cd16
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/automation.mdx
@@ -0,0 +1,204 @@
+---
+title: 同步你的 AsyncAPI 规范
+subtitle: 自动同步你的 AsyncAPI 规范变更,保持 SDK 和文档的最新状态
+sidebar-title: 同步你的 AsyncAPI 规范
+---
+
+保持你的 AsyncAPI 规范与代码库同步对于维护准确的 SDK 和文档至关重要。Fern 提供了几种自动化选项来简化这个过程。
+
+## GitHub Actions
+
+使用 Fern 的 GitHub Action 在你的 AsyncAPI 规范发生变更时自动更新 SDK 和文档:
+
+```yaml title=".github/workflows/fern.yml"
+name: Fern
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ fern-check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Check AsyncAPI spec
+ uses: fern-api/action@v0
+ with:
+ command: check
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+
+ fern-generate:
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Generate SDKs and docs
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## Webhook 集成
+
+设置 webhook 以在 AsyncAPI 规范更新时触发 SDK 生成:
+
+```yaml title="generators.yml" {4-8}
+api:
+ specs:
+ - spec: asyncapi.yml
+ github:
+ repository: your-org/your-repo
+ webhooks:
+ - url: https://your-api.com/webhooks/fern
+ events: [generate]
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@your-org/sdk"
+```
+
+## 从源自动同步
+
+配置 Fern 自动从各种源拉取你的 AsyncAPI 规范:
+
+### 从 URL
+```yaml title="generators.yml" {3-4}
+api:
+ specs:
+ - spec: https://api.yourcompany.com/asyncapi.yml
+ auto-sync: true
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+### 从 git 仓库
+```yaml title="generators.yml" {3-7}
+api:
+ specs:
+ - spec:
+ git:
+ repository: https://github.com/your-org/api-specs
+ path: asyncapi/api.yml
+ branch: main
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+## CI/CD 集成
+
+### CircleCI
+```yaml title=".circleci/config.yml" {15-23}
+version: 2.1
+
+orbs:
+ fern: fernapi/fern@1.0
+
+workflows:
+ version: 2
+ build-and-test:
+ jobs:
+ - build
+ - test:
+ requires:
+ - build
+ - fern/generate:
+ requires:
+ - test
+ filters:
+ branches:
+ only: main
+ context:
+ - fern-context
+```
+
+### GitLab CI
+```yaml title=".gitlab-ci.yml" {13-20}
+stages:
+ - build
+ - test
+ - generate
+
+variables:
+ FERN_TOKEN: $FERN_TOKEN
+
+build:
+ stage: build
+ script:
+ - echo "Building application..."
+
+generate-sdks:
+ stage: generate
+ image: fernapi/fern:latest
+ script:
+ - fern generate
+ only:
+ - main
+```
+
+## 定时更新
+
+设置定时更新以确保你的 SDK 保持最新:
+
+```yaml title=".github/workflows/scheduled-update.yml"
+name: Scheduled AsyncAPI Update
+
+on:
+ schedule:
+ - cron: '0 2 * * 1' # Every Monday at 2 AM UTC
+ workflow_dispatch:
+
+jobs:
+ update-specs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Update AsyncAPI specs
+ run: |
+ curl -o fern/asyncapi/asyncapi.yml https://api.yourcompany.com/asyncapi.yml
+
+ - name: Generate with latest spec
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## 监控变更
+
+跟踪你的 AsyncAPI 规范的变更:
+
+```yaml title="generators.yml" {4-9}
+api:
+ specs:
+ - spec: asyncapi.yml
+ change-detection:
+ enabled: true
+ breaking-changes: error
+ notifications:
+ slack: ${{ secrets.SLACK_WEBHOOK }}
+ email: team@yourcompany.com
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+这确保了对你的 AsyncAPI 规范的任何破坏性变更都会被检测到,并且在变更传播到你的 SDK 和文档之前通知相应的团队成员。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/channels/bindings.mdx b/fern/translations/zh/products/api-def/asyncapi/channels/bindings.mdx
new file mode 100644
index 000000000..d8493b72e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/channels/bindings.mdx
@@ -0,0 +1,215 @@
+---
+title: Message Bindings
+subtitle: 为 WebSocket、MQTT、Kafka 和其他协议配置协议特定设置
+sidebar-title: Message Bindings
+---
+
+AsyncAPI 中的绑定允许您为服务器、通道、操作和消息指定协议特定信息。这使您能够为不同的消息协议提供详细配置。
+
+```yml title="asyncapi.yml" {6-12}
+channels:
+ user/notifications:
+ address: user/notifications
+ messages:
+ UserNotification:
+ $ref: '#/components/messages/UserNotification'
+ bindings:
+ ws:
+ method: GET
+ query:
+ type: object
+ properties:
+ token:
+ type: string
+ description: Authentication token
+```
+
+## WebSocket 绑定
+
+为实时通信配置 WebSocket 特定设置:
+
+```yml title="asyncapi.yml" {4-10}
+channels:
+ chat/room:
+ address: chat/room/{roomId}
+ bindings:
+ ws:
+ method: GET
+ headers:
+ type: object
+ properties:
+ Authorization:
+ type: string
+ query:
+ type: object
+ properties:
+ userId:
+ type: string
+ roomId:
+ type: string
+
+operations:
+ sendMessage:
+ action: send
+ channel:
+ $ref: '#/channels/chat~1room'
+ bindings:
+ ws:
+ type: request
+ method: message
+```
+
+## MQTT 绑定
+
+为 IoT 和消息应用程序配置 MQTT 特定设置:
+
+```yml title="asyncapi.yml" {4-8}
+channels:
+ device/telemetry:
+ address: device/{deviceId}/telemetry
+ bindings:
+ mqtt:
+ qos: 1
+ retain: true
+ messageExpiryInterval: 3600
+
+servers:
+ mqtt-broker:
+ host: mqtt.example.com
+ protocol: mqtt
+ bindings:
+ mqtt:
+ clientId: device-client
+ cleanSession: false
+ keepAlive: 60
+ will:
+ topic: device/status
+ payload: "offline"
+ qos: 1
+ retain: true
+```
+
+## Kafka 绑定
+
+为高吞吐量事件流配置 Kafka 特定设置:
+
+```yml title="asyncapi.yml" {4-12}
+channels:
+ user.events:
+ address: user.events
+ bindings:
+ kafka:
+ topic: user.events
+ partitions: 10
+ replicas: 3
+ topicConfiguration:
+ cleanup.policy: ["delete"]
+ retention.ms: 604800000
+ segment.ms: 86400000
+
+operations:
+ publishUserEvent:
+ action: send
+ channel:
+ $ref: '#/channels/user.events'
+ bindings:
+ kafka:
+ groupId: user-event-processors
+ key:
+ type: string
+ description: User ID for partitioning
+```
+
+## 服务器绑定
+
+配置协议特定的服务器设置:
+
+```yml title="asyncapi.yml" {6-16}
+servers:
+ websocket-server:
+ host: ws.example.com
+ protocol: wss
+ description: WebSocket server with SSL
+ bindings:
+ ws:
+ headers:
+ type: object
+ properties:
+ X-API-Version:
+ type: string
+ const: "v1"
+
+ kafka-cluster:
+ host: kafka.example.com:9092
+ protocol: kafka
+ bindings:
+ kafka:
+ schemaRegistryUrl: https://schema-registry.example.com
+ schemaRegistryVendor: confluent
+```
+
+## 消息绑定
+
+配置特定协议如何处理消息:
+
+```yml title="asyncapi.yml" {8-15}
+components:
+ messages:
+ OrderEvent:
+ name: OrderEvent
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/Order'
+ bindings:
+ kafka:
+ key:
+ type: string
+ description: Order ID for consistent partitioning
+ headers:
+ type: object
+ properties:
+ eventType:
+ type: string
+ enum: [created, updated, cancelled]
+ mqtt:
+ qos: 2
+ retain: false
+```
+
+## HTTP 绑定
+
+用于基于 HTTP 的协议,如 Server-Sent Events:
+
+```yml title="asyncapi.yml" {4-8}
+channels:
+ events/stream:
+ address: /events/stream
+ bindings:
+ http:
+ type: response
+ method: GET
+ query:
+ type: object
+ properties:
+ lastEventId:
+ type: string
+ description: Last received event ID for resumption
+
+operations:
+ streamEvents:
+ action: send
+ channel:
+ $ref: '#/channels/events~1stream'
+ bindings:
+ http:
+ type: response
+ statusCode: 200
+ headers:
+ type: object
+ properties:
+ Content-Type:
+ type: string
+ const: text/event-stream
+```
+
+绑定提供了灵活性,可以利用协议特定功能,同时在不同传输机制之间维护统一的 API 规范。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/channels/messages.mdx b/fern/translations/zh/products/api-def/asyncapi/channels/messages.mdx
new file mode 100644
index 000000000..c6d6362a0
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/channels/messages.mdx
@@ -0,0 +1,171 @@
+---
+title: 消息格式
+subtitle: 为事件驱动通信定义消息模式、内容类型和结构
+sidebar-title: 消息格式
+---
+
+AsyncAPI 中的消息在 `components.messages` 部分定义,并从频道和操作中引用。它们定义了通过事件驱动 API 交换的数据的结构和格式。
+
+```yml title="asyncapi.yml" {2-12}
+components:
+ messages:
+ UserEvent:
+ name: UserEvent
+ title: User Event Message
+ summary: Event triggered by user actions
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/UserEventPayload'
+ headers:
+ $ref: '#/components/schemas/MessageHeaders'
+```
+
+## 消息负载
+
+负载定义了消息数据的结构:
+
+```yml title="asyncapi.yml" {4-6}
+components:
+ messages:
+ OrderCreated:
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/Order'
+ schemas:
+ Order:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: Unique order identifier
+ customerId:
+ type: string
+ description: Customer who placed the order
+ items:
+ type: array
+ items:
+ $ref: '#/components/schemas/OrderItem'
+ total:
+ type: number
+ format: decimal
+ description: Total order amount
+ createdAt:
+ type: string
+ format: date-time
+ description: When the order was created
+ required:
+ - id
+ - customerId
+ - items
+ - total
+```
+
+## 消息头
+
+您可以定义与消息一起发送的头:
+
+```yml title="asyncapi.yml" {6-8}
+components:
+ messages:
+ NotificationEvent:
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/Notification'
+ headers:
+ $ref: '#/components/schemas/NotificationHeaders'
+ schemas:
+ NotificationHeaders:
+ type: object
+ properties:
+ messageId:
+ type: string
+ description: Unique message identifier
+ timestamp:
+ type: string
+ format: date-time
+ description: Message timestamp
+ source:
+ type: string
+ description: Source service that generated the message
+ priority:
+ type: string
+ enum: [low, medium, high, urgent]
+ description: Message priority level
+```
+
+## 内容类型
+
+AsyncAPI 支持各种消息内容类型:
+
+```yml title="asyncapi.yml" {4,10,16}
+components:
+ messages:
+ JsonMessage:
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/JsonPayload'
+
+ BinaryMessage:
+ contentType: application/octet-stream
+ payload:
+ type: string
+ format: binary
+
+ TextMessage:
+ contentType: text/plain
+ payload:
+ type: string
+```
+
+## 消息示例
+
+提供具体示例以帮助开发者理解您的消息格式:
+
+```yml title="asyncapi.yml" {8-18}
+components:
+ messages:
+ UserSignup:
+ name: UserSignup
+ title: User Signup Event
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/User'
+ examples:
+ - name: StandardSignup
+ summary: Regular user signup
+ payload:
+ id: "123e4567-e89b-12d3-a456-426614174000"
+ email: "john@example.com"
+ name: "John Doe"
+ signupSource: "web"
+ createdAt: "2024-01-15T10:30:00Z"
+```
+
+## 消息特性
+
+使用特性在多个消息之间共享通用消息属性:
+
+```yml title="asyncapi.yml" {2-12, 15-19}
+components:
+ messageTraits:
+ commonHeaders:
+ headers:
+ type: object
+ properties:
+ messageId:
+ type: string
+ timestamp:
+ type: string
+ format: date-time
+
+ messages:
+ UserEvent:
+ traits:
+ - $ref: '#/components/messageTraits/commonHeaders'
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/UserEventPayload'
+```
+
+这种方法有助于在消息定义中保持一致性,同时减少重复。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/channels/pubsub.mdx b/fern/translations/zh/products/api-def/asyncapi/channels/pubsub.mdx
new file mode 100644
index 000000000..690373f3f
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/channels/pubsub.mdx
@@ -0,0 +1,106 @@
+---
+title: 发布/订阅操作
+description: 为事件驱动的 API 定义 AsyncAPI 发布/订阅操作。包含消息示例和双向通道的分步教程。
+sidebar-title: 发布/订阅操作
+---
+
+AsyncAPI 中的操作定义在 `operations` 键下,通道定义在 `channels` 键下。以下是定义发布和订阅操作的示例:
+
+```yml title="asyncapi.yml" maxLines=0 {2-22}
+channels:
+ user/notifications:
+ address: user/notifications
+ messages:
+ UserNotification:
+ $ref: '#/components/messages/UserNotification'
+
+operations:
+ onUserNotification:
+ action: receive
+ channel:
+ $ref: '#/channels/user~1notifications'
+ summary: Receive user notifications
+ description: Subscribe to user notification events
+ sendUserNotification:
+ action: send
+ channel:
+ $ref: '#/channels/user~1notifications'
+ summary: Send user notification
+ description: Publish a user notification event
+```
+
+## 消息示例
+
+您可以通过在消息定义中使用 `examples` 键来提供消息示例:
+
+```yaml title="asyncapi.yml" {8-15}
+components:
+ messages:
+ UserNotification:
+ name: UserNotification
+ title: User Notification
+ summary: Notification sent to a user
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/Notification'
+ examples:
+ - name: EmailNotification
+ summary: Example email notification
+ payload:
+ userId: "123e4567-e89b-12d3-a456-426614174000"
+ type: "email"
+ message: "Welcome to our service!"
+ priority: "medium"
+```
+
+## 发布操作
+
+发布操作表示您的服务发送到通道的消息:
+
+```yml title="asyncapi.yml" {2-8}
+operations:
+ publishOrderStatus:
+ action: send
+ channel:
+ $ref: '#/channels/order~1status'
+ summary: Publish order status update
+ description: Send order status updates to subscribers
+ message:
+ $ref: '#/components/messages/OrderStatus'
+```
+
+## 订阅操作
+
+订阅操作表示您的服务从通道接收的消息:
+
+```yml title="asyncapi.yml" {2-8}
+operations:
+ subscribeToUserSignups:
+ action: receive
+ channel:
+ $ref: '#/channels/user~1signup'
+ summary: Subscribe to user signups
+ description: Receive notifications when users sign up
+ message:
+ $ref: '#/components/messages/UserSignup'
+```
+
+## 双向通信
+
+您可以为同一个通道定义发布和订阅操作,以启用双向通信:
+
+```yml title="asyncapi.yml" {2-15}
+operations:
+ sendChatMessage:
+ action: send
+ channel:
+ $ref: '#/channels/chat~1room'
+ summary: Send chat message
+ description: Send a message to a chat room
+ receiveChatMessage:
+ action: receive
+ channel:
+ $ref: '#/channels/chat~1room'
+ summary: Receive chat message
+ description: Receive messages from a chat room
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/extensions/audiences.mdx b/fern/translations/zh/products/api-def/asyncapi/extensions/audiences.mdx
new file mode 100644
index 000000000..4fd52138d
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/extensions/audiences.mdx
@@ -0,0 +1,160 @@
+---
+title: 使用受众筛选您的 API
+headline: 使用受众筛选您的 API (AsyncAPI)
+subtitle: 使用 `x-fern-audiences` 筛选相关的操作、通道和消息模式
+sidebar-title: 使用受众筛选 API
+---
+
+
+
+
+受众是对事件驱动 API 进行分段以服务不同消费者的有用工具。常见的受众示例包括 `public` 和 `beta`。
+
+
+ 记住在指定受众后要筛选您的 SDK 和文档。如果**未指定受众**,将不会进行任何筛选。
+
+
+
+
+以下示例配置 SDK 筛选到 `public` 受众:
+
+```yaml title="generators.yml" {3-4}
+groups:
+ sdks:
+ audiences:
+ - public
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+
+
+以下示例配置文档筛选到 `public` 受众:
+
+```yaml title="docs.yml" {3-4}
+navigation:
+ - api: API Reference
+ audiences:
+ - public
+```
+
+
+
+
+
+## 筛选操作
+
+在操作中添加 `x-fern-audiences` 来控制特定受众包含哪些操作:
+
+```yaml title="asyncapi.yml" {5-6, 12-13}
+operations:
+ sendPublicNotification:
+ action: send
+ channel:
+ $ref: '#/channels/public~1notifications'
+ x-fern-audiences:
+ - public
+ sendBetaAlert:
+ action: send
+ channel:
+ $ref: '#/channels/beta~1alerts'
+ x-fern-audiences:
+ - beta
+```
+
+## 筛选通道
+
+您还可以按受众筛选整个通道:
+
+```yaml title="asyncapi.yml" {6-7, 13-14}
+channels:
+ public/events:
+ address: public/events
+ messages:
+ PublicEvent:
+ $ref: '#/components/messages/PublicEvent'
+ x-fern-audiences:
+ - public
+ internal/events:
+ address: internal/events
+ messages:
+ InternalEvent:
+ $ref: '#/components/messages/InternalEvent'
+ x-fern-audiences:
+ - internal
+```
+
+## 筛选消息模式
+
+将特定消息模式筛选到不同受众:
+
+```yaml title="asyncapi.yml" {5-6, 13-14}
+components:
+ messages:
+ PublicUserEvent:
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/PublicUser'
+ x-fern-audiences:
+ - public
+ AdminUserEvent:
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/AdminUser'
+ x-fern-audiences:
+ - admin
+ schemas:
+ PublicUser:
+ type: object
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ email:
+ type: string
+ x-fern-audiences:
+ - public
+ AdminUser:
+ allOf:
+ - $ref: '#/components/schemas/PublicUser'
+ - type: object
+ properties:
+ role:
+ type: string
+ permissions:
+ type: array
+ items:
+ type: string
+ x-fern-audiences:
+ - admin
+```
+
+## 筛选模式属性
+
+您可以筛选模式内的单个属性:
+
+```yaml title="asyncapi.yml" {9-10, 13-14}
+components:
+ schemas:
+ UserEvent:
+ type: object
+ properties:
+ id:
+ type: string
+ email:
+ type: string
+ x-fern-audiences:
+ - internal
+ publicName:
+ type: string
+ x-fern-audiences:
+ - public
+ internalNotes:
+ type: string
+ x-fern-audiences:
+ - internal
+```
+
+这使您能够为不同受众提供相同事件模式的不同视图,向每个消费者只显示相关信息。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/extensions/availability.mdx b/fern/translations/zh/products/api-def/asyncapi/extensions/availability.mdx
new file mode 100644
index 000000000..43dbf2f0e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/extensions/availability.mdx
@@ -0,0 +1,19 @@
+---
+title: 可用性
+headline: 可用性 (AsyncAPI)
+description: 使用 `x-fern-availability` 扩展标记功能在特定 SDK 版本中的可用性
+sidebar-title: 可用性
+---
+
+标记功能在特定 SDK 版本中的可用性:
+
+```yaml title="asyncapi.yml" {6-8}
+operations:
+ newFeature:
+ action: send
+ channel:
+ $ref: '#/channels/new~1feature'
+ x-fern-availability:
+ status: beta
+ message: "This feature is in beta and may change"
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/extensions/examples.mdx b/fern/translations/zh/products/api-def/asyncapi/extensions/examples.mdx
new file mode 100644
index 000000000..f9809b1bf
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/extensions/examples.mdx
@@ -0,0 +1,34 @@
+---
+title: 请求和响应示例
+headline: 请求和响应示例 (AsyncAPI)
+description: 使用 `x-fern-examples` 向 AsyncAPI 规范添加消息示例。通过真实世界的载荷示例改善 SDK 文档。
+og:title: AsyncAPI 请求和响应示例
+sidebar-title: 请求和响应示例
+---
+
+
+为更好的 SDK 文档提供额外示例:
+
+```yaml title="asyncapi.yml" {8-20}
+components:
+ messages:
+ UserEvent:
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/User'
+ x-fern-examples:
+ - name: NewUserSignup
+ summary: Example of a new user signup event
+ payload:
+ id: "user_123"
+ email: "john@example.com"
+ name: "John Doe"
+ status: "active"
+ - name: UserDeactivation
+ summary: Example of user deactivation event
+ payload:
+ id: "user_456"
+ email: "jane@example.com"
+ name: "Jane Smith"
+ status: "inactive"
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/extensions/ignore.mdx b/fern/translations/zh/products/api-def/asyncapi/extensions/ignore.mdx
new file mode 100644
index 000000000..c115f3b08
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/extensions/ignore.mdx
@@ -0,0 +1,27 @@
+---
+title: 忽略操作、通道或模式
+headline: 忽略操作、通道或模式 (AsyncAPI)
+description: 了解如何使用 x-fern-ignore 在 AsyncAPI SDK 生成中排除特定的操作、通道或模式。
+sidebar-title: 忽略操作、通道或模式
+---
+
+
+使用 `x-fern-ignore` 在 SDK 生成中排除特定的操作、通道或模式:
+
+```yaml title="asyncapi.yml" {6-7, 13-14}
+operations:
+ debugOperation:
+ action: send
+ channel:
+ $ref: '#/channels/debug'
+ x-fern-ignore: true
+ summary: Debug operation (internal only)
+
+channels:
+ internal/debug:
+ address: internal/debug
+ x-fern-ignore: true
+ messages:
+ DebugMessage:
+ $ref: '#/components/messages/DebugMessage'
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/extensions/server-name.mdx b/fern/translations/zh/products/api-def/asyncapi/extensions/server-name.mdx
new file mode 100644
index 000000000..e86ac4e9a
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/extensions/server-name.mdx
@@ -0,0 +1,21 @@
+---
+title: 服务器名称
+headline: 服务器名称 (AsyncAPI)
+description: 在 AsyncAPI 规范中使用 `x-fern-server-name` 扩展配置自定义服务器名称。设置生产和测试服务器标签。
+sidebar-title: 服务器名称
+---
+
+
+为服务器指定自定义名称:
+
+```yaml title="asyncapi.yml" {4-5}
+servers:
+ production:
+ host: api.yourcompany.com
+ x-fern-server-name: Production
+ protocol: wss
+ staging:
+ host: staging.api.yourcompany.com
+ x-fern-server-name: Staging
+ protocol: wss
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/overview.mdx b/fern/translations/zh/products/api-def/asyncapi/overview.mdx
new file mode 100644
index 000000000..0d5dc96fb
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/overview.mdx
@@ -0,0 +1,183 @@
+---
+title: 什么是 AsyncAPI 规范?
+description: AsyncAPI 是用于文档化事件驱动 API 的标准
+sidebar-title: 什么是 AsyncAPI 规范?
+---
+
+
+
+ Fern 支持为 TypeScript、Python、Java 和 C# 生成 AsyncAPI SDK。[提交 issue](https://github.com/fern-api/fern/issues) 来请求支持其他语言。
+
+
+AsyncAPI 规范是开发人员用来文档化事件驱动 API 的框架。该规范使用 JSON 或 YAML 编写,包含您的所有通道、消息、模式和身份验证方案。Fern 与 AsyncAPI 规范 [v2.6.0](https://www.asyncapi.com/docs/reference/specification/v2.6.0) 和 [v3.0.0](https://www.asyncapi.com/docs/reference/specification/v3.0.0) 兼容。
+
+以下是一个 AsyncAPI 文件的示例:
+
+```yaml asyncapi.yml
+asyncapi: 3.0.0
+info:
+ title: User Notification Service
+ version: 1.0.0
+ description: |
+ Service that handles user notifications through various channels
+ including email, SMS, and push notifications.
+channels:
+ user/signup:
+ address: user/signup
+ messages:
+ UserSignedUp:
+ $ref: '#/components/messages/UserSignedUp'
+ notification/send:
+ address: notification/send
+ messages:
+ SendNotification:
+ $ref: '#/components/messages/SendNotification'
+operations:
+ onUserSignup:
+ action: receive
+ channel:
+ $ref: '#/channels/user~1signup'
+ summary: User signup event
+ description: Triggered when a user signs up for the service
+ sendNotification:
+ action: send
+ channel:
+ $ref: '#/channels/notification~1send'
+ summary: Send notification
+ description: Send a notification to a user
+components:
+ messages:
+ UserSignedUp:
+ name: UserSignedUp
+ title: User Signed Up
+ summary: User has signed up for the service
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/User'
+ SendNotification:
+ name: SendNotification
+ title: Send Notification
+ summary: Send a notification to a user
+ contentType: application/json
+ payload:
+ $ref: '#/components/schemas/Notification'
+ schemas:
+ User:
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ description: Unique identifier for the user
+ email:
+ type: string
+ format: email
+ description: User's email address
+ name:
+ type: string
+ description: User's full name
+ createdAt:
+ type: string
+ format: date-time
+ description: When the user was created
+ required:
+ - id
+ - email
+ - name
+ Notification:
+ type: object
+ properties:
+ userId:
+ type: string
+ format: uuid
+ description: ID of the user to notify
+ type:
+ type: string
+ enum: [email, sms, push]
+ description: Type of notification to send
+ message:
+ type: string
+ description: Message content
+ priority:
+ type: string
+ enum: [low, medium, high, urgent]
+ default: medium
+ description: Priority level of the notification
+ required:
+ - userId
+ - type
+ - message
+```
+
+## 设置您的 fern 文件夹
+
+
+ 正在考虑生成 AsyncAPI 规范的选项?在[这里](https://fern-community.slack.com/join/shared_invite/zt-2dpftfmif-MuAegl8AfP_PK8s2tx350Q%EF%BB%BF#/shared-invite/email)获得实时支持
+
+
+
+
+在您的项目根目录中创建一个 `fern/` 文件夹。
+
+
+
+
+
+
+将您的 AsyncAPI 规范添加到 fern 目录中。您可以将其放在名为 `asyncapi` 的子文件夹中,或直接放在 fern 目录中。
+
+
+
+
+
+
+
+
+
+
+在您的 fern 目录中添加一个 `fern.config.json` 文件,其中列出您的组织和当前版本的 Fern CLI:
+
+```json title="fern.config.json"
+{
+ "organization": "your-organization",
+ "version": ""
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+在您的 fern 目录中创建一个 `generators.yml` 文件,并添加对您的 AsyncAPI 规范的引用:
+
+```yaml title="generators.yml"
+# Your API definition
+api:
+ specs:
+ - asyncapi: ./asyncapi/asyncapi.yml
+
+groups:
+ external:
+ generators:
+ # Your generator configurations here
+```
+
+您的最终目录结构:
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/asyncapi/servers.mdx b/fern/translations/zh/products/api-def/asyncapi/servers.mdx
new file mode 100644
index 000000000..70dead6bb
--- /dev/null
+++ b/fern/translations/zh/products/api-def/asyncapi/servers.mdx
@@ -0,0 +1,117 @@
+---
+title: 服务器
+description: 配置服务器 URL 和协议以帮助用户连接到您的事件驱动 API。
+subtitle: 定义服务器 URL 和协议以帮助用户连接到您的事件驱动 API。
+sidebar-title: 服务器
+---
+
+AsyncAPI 允许您在 `servers` 键下指定一个或多个服务器配置。
+
+```yml asyncapi.yml
+
+servers:
+ production:
+ host: api.yourcompany.com
+ protocol: wss
+ description: Production WebSocket server
+ staging:
+ host: staging.api.yourcompany.com
+ protocol: wss
+ description: Staging WebSocket server
+```
+
+指定服务器对 SDK 和文档都很有价值:
+- 对于 SDK,您的用户在客户端实例化时无需手动指定服务器 URL
+- 对于文档,您的 API 游乐场将自动连接到正确的服务器
+
+## 协议支持
+
+AsyncAPI 支持各种用于事件驱动通信的协议:
+
+```yml asyncapi.yml {4,8,12}
+servers:
+ websocket-server:
+ host: ws.api.yourcompany.com
+ protocol: ws
+ description: WebSocket server for real-time communication
+ mqtt-server:
+ host: mqtt.yourcompany.com
+ protocol: mqtt
+ description: MQTT broker for IoT devices
+ kafka-server:
+ host: kafka.yourcompany.com
+ protocol: kafka
+ description: Kafka cluster for event streaming
+```
+
+## 命名您的服务器
+
+我们建议为您的服务器提供描述性名称,以明确每个服务器的用途:
+
+```yml asyncapi.yml
+servers:
+ production:
+ host: api.yourcompany.com
+ protocol: wss
+ description: Production WebSocket server
+ staging:
+ host: staging.api.yourcompany.com
+ protocol: wss
+ description: Staging environment for testing
+ development:
+ host: localhost:8080
+ protocol: ws
+ description: Local development server
+```
+
+## 服务器变量
+
+您可以在服务器配置中使用变量来使其更加灵活:
+
+```yml asyncapi.yml {3-10}
+servers:
+ production:
+ host: '{environment}.api.yourcompany.com'
+ protocol: wss
+ variables:
+ environment:
+ default: prod
+ enum:
+ - prod
+ - staging
+ description: Environment name
+```
+
+## 不同通道使用多种协议
+
+如果您有使用不同协议的不同通道,您可以在服务器配置中指定这一点:
+
+```yml asyncapi.yml {2-14, 17-21}
+servers:
+ websocket-server:
+ host: ws.api.yourcompany.com
+ protocol: wss
+ description: WebSocket server for real-time notifications
+ mqtt-server:
+ host: mqtt.api.yourcompany.com
+ protocol: mqtt
+ description: MQTT broker for IoT device communication
+ kafka-server:
+ host: kafka.api.yourcompany.com
+ protocol: kafka
+ description: Kafka for high-throughput event streaming
+
+channels:
+ user/notifications:
+ servers:
+ - websocket-server
+ address: user/notifications
+ description: Real-time user notifications via WebSocket
+ device/telemetry:
+ servers:
+ - mqtt-server
+ address: device/telemetry
+ description: IoT device telemetry via MQTT
+```
+
+这允许不同的通道使用最适合其用例的协议。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/api-yml/environments.mdx b/fern/translations/zh/products/api-def/ferndef/api-yml/environments.mdx
new file mode 100644
index 000000000..9f6ece096
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/api-yml/environments.mdx
@@ -0,0 +1,132 @@
+---
+title: 环境配置
+description: 列出生产、预发布和开发等环境。
+sidebar-title: 环境配置
+---
+
+您可以指定服务器部署的环境。
+
+## 单 URL 环境
+
+```yaml title="api.yml"
+name: api
+environments:
+ Production: https://www.yoursite.com
+ Staging:
+ docs: This staging environment is helpful for testing!
+ url: https://www.staging.yoursite.com
+```
+
+## 每个环境多个 URL
+
+您可以为每个环境指定多个 URL。如果您有微服务架构,并且希望单个 SDK 与多个服务器交互,这将很有帮助。
+
+```yaml title="api.yml"
+environments:
+ Production:
+ urls:
+ Auth: https://auth.yoursite.com
+ Plants: https://plants.yoursite.com
+ Staging:
+ urls:
+ Auth: https://auth.staging.yoursite.com
+ Plants: https://plants.staging.yoursite.com
+```
+
+如果您选择使用此功能,必须为您定义的每个服务指定一个 `url`:
+
+```yaml title="auth.yml"
+service:
+ url: Auth
+ base-path: /auth
+ ...
+```
+
+## 默认环境
+
+您也可以提供默认环境:
+
+```yaml title="api.yml"
+name: api
+environments:
+ Production: https://www.yoursite.com
+ Staging:
+ docs: This staging environment is helpful for testing!
+ url: https://www.staging.yoursite.com
+default-environment: Production
+```
+
+通过提供默认环境,生成的 SDK 将设置为开箱即用地访问该 URL。
+
+## URL 模板
+
+URL 模板目前仅支持 Python 和 Java SDK 生成。
+
+对于跨多个区域或环境部署的 API,您可以定义带有变量占位符的 URL 模板,SDK 用户可以在运行时进行自定义。要设置此功能:
+
+1. 在 `urls` 下定义您的静态基础 URL——这些会出现在生成的环境枚举中。
+2. 为每个服务添加带有 `{variable}` 占位符的 `url-templates`(例如,`https://api.{region}.example.com/v1`)。Fern 将这些作为 SDK 中的可配置参数公开。
+3. 提供 `default-urls` 作为具体的回退选项,这样 SDK 用户无需提供变量就能获得开箱即用的客户端。
+4. 为每个服务列出可用的 `variables`,每个变量都有一个 `id`、一个 `default` 值,以及一个可选的 `values` 列表来约束允许的选项。
+
+```yaml title="api.yml"
+environments:
+ RegionalApiServer:
+ urls:
+ Base: https://api.example.com/v1
+ Auth: https://auth.example.com
+ url-templates:
+ Base: https://api.{region}.{environment}.example.com/v1
+ Auth: https://auth.{region}.example.com
+ default-urls:
+ Base: https://api.example.com/v1
+ Auth: https://auth.example.com
+ variables:
+ Base:
+ - id: region
+ default: us-east-1
+ values:
+ - us-east-1
+ - us-west-2
+ - eu-west-1
+ - id: environment
+ default: prod
+ values:
+ - prod
+ - staging
+ - dev
+ Auth:
+ - id: region
+ default: us-east-1
+ values:
+ - us-east-1
+ - us-west-2
+ - eu-west-1
+default-environment: RegionalApiServer
+```
+
+## 基础路径
+如果您希望所有端点都添加路径前缀,请使用 `base-path`。
+
+在下面的示例中,每个端点都添加了 `/v1` 前缀:
+```yaml title="api.yml"
+name: api
+base-path: /v1
+```
+
+## 受众
+
+如果您有列出的环境需要过滤,可以利用受众功能。
+
+```yaml title="api.yml"
+audiences:
+ - public
+
+environments:
+ Dev:
+ url: https://api.dev.buildwithfern.com
+ Prod:
+ url: https://api.buildwithfern.com
+ audiences:
+ - external
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/api-yml/errors.mdx b/fern/translations/zh/products/api-def/ferndef/api-yml/errors.mdx
new file mode 100644
index 000000000..2546acd56
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/api-yml/errors.mdx
@@ -0,0 +1,49 @@
+---
+title: 错误处理
+description: 指定错误类型和模式
+sidebar-title: 错误处理
+---
+
+为了以惯用方式生成 SDK,Fern 需要知道在解析端点响应时如何区分不同的错误。
+
+### 按状态码区分
+
+您可以指定 Fern 按状态码区分。这意味着在每个端点上,列出的每个错误都必须具有不同的 HTTP 状态码。
+
+
+```yaml
+name: api
+error-discrimination:
+ strategy: status-code
+```
+
+
+### 按错误名称区分
+
+您可以指定 Fern 按错误名称区分。如果您选择此策略,那么 Fern 将假设每个错误响应都有一个额外的属性来表示错误名称。
+
+如果您使用 Fern 生成服务器端代码,那么此选项提供了最大的灵活性。否则,您可能希望使用状态码区分策略。
+
+
+```yaml
+name: api
+error-discrimination:
+ strategy: property
+ property-name: errorName
+```
+
+
+### 全局错误
+
+您可以导入并列出将由每个端点抛出的错误。
+
+
+```yaml
+imports:
+ commons: commons.yml
+
+errors:
+ - commons.NotFoundError
+ - commons.BadRequestError
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/api-yml/global-configuration.mdx b/fern/translations/zh/products/api-def/ferndef/api-yml/global-configuration.mdx
new file mode 100644
index 000000000..8445f0a39
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/api-yml/global-configuration.mdx
@@ -0,0 +1,69 @@
+---
+title: 全局配置
+description: 指定全局请求头、路径参数或查询参数,以包含在每个请求中。
+sidebar-title: 全局配置
+---
+
+`api.yml` 配置支持全局配置,如请求头和路径参数。
+
+## 全局请求头
+
+您可以指定要包含在每个请求中的请求头:
+
+
+```yaml
+name: api
+headers:
+ X-App-Id: string
+```
+
+
+在 `api.yml` 中定义全局请求头时,您必须[在端点示例中包含它们](/api-definitions/ferndef/examples#examples-with-headers)。
+
+## 全局路径参数
+
+您可以指定要包含在每个请求中的路径参数:
+
+
+```yaml
+name: api
+base-path: /{userId}/{orgId}
+path-parameters:
+ userId: string
+ orgId: string
+```
+
+
+### 覆盖基础路径
+
+如果您有某些端点不在配置的 `base-path` 下,您可以在端点级别覆盖 `base-path`。
+
+```yml imdb.yml {5}
+service:
+ endpoints:
+ getMovie:
+ method: POST
+ base-path: "override/{arg}"
+ path: "movies/{movieId}"
+ path-parameters:
+ arg: string
+```
+
+## 全局查询参数
+
+目前还不能指定要包含在每个请求中的查询参数。
+如果您希望看到这个功能,请为[此问题](https://github.com/fern-api/fern/issues/2930)投票。
+
+## 幂等性请求头
+
+配置幂等性请求头来定义 [SDK 用户](/learn/sdks/deep-dives/idempotency)可以为安全请求重试指定的请求头。您还必须[将每个端点标记为幂等](/learn/api-definitions/ferndef/endpoints/overview#idempotent-endpoints)才能公开这些请求头。当两者都配置时,Fern 生成的 SDK 会将这些请求头作为幂等端点调用的参数公开。
+
+```yaml title="api.yml"
+name: api
+auth: bearer
+idempotency-headers:
+ Idempotency-Key: string
+ Idempotency-Expiration: optional
+```
+
+`idempotency-headers` 中的每个键是 HTTP 请求头名称,值是类型。然后 [SDK 用户](/learn/sdks/deep-dives/idempotency)可以在调用幂等端点时指定这些请求头。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/api-yml/overview.mdx b/fern/translations/zh/products/api-def/ferndef/api-yml/overview.mdx
new file mode 100644
index 000000000..fc5c27f04
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/api-yml/overview.mdx
@@ -0,0 +1,57 @@
+---
+title: api.yml 配置文件
+description: 使用 Fern Definition 格式时,api.yml 文件包含通用 API 配置。
+sidebar-title: api.yml 配置文件
+---
+
+`fern/` 文件夹中有一个名为 `api.yml` 的特殊文件,其中包含所有 API 级别的配置。
+
+```bash {5}
+fern/
+├─ fern.config.json
+├─ generators.yml
+└─ definition/
+ ├─ api.yml
+ ├─ pet.yml
+ ├─ store.yml
+ └─ user.yml
+```
+
+## API 名称
+
+此名称用于在您的组织中唯一标识您的 API。如果您只有一个 API,那么 `api` 是一个合适的名称。
+
+
+```yaml
+name: api
+```
+
+
+## API 描述
+
+您可以定义顶级 API 描述。此描述将出现在 OpenAPI 规范和 Postman 集合中。
+
+
+```yaml {2-4}
+name: api
+docs: |
+ ## Header
+ This API provides access to...
+```
+
+
+## API 版本
+
+您可以定义基于请求头的 API 版本控制方案,例如 `X-API-Version`。支持的版本和默认值的指定方式如下:
+
+
+```yaml
+version:
+ header: X-API-Version
+ default: "2.0.0"
+ values:
+ - "1.0.0"
+ - "2.0.0"
+ - "latest"
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/audiences.mdx b/fern/translations/zh/products/api-def/ferndef/audiences.mdx
new file mode 100644
index 000000000..c0f34a865
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/audiences.mdx
@@ -0,0 +1,116 @@
+---
+title: Fern Definition 中的受众
+subtitle: 在您的 Fern Definition 中使用受众,为不同的 API 消费者群体进行分组。
+sidebar-title: Fern Definition 中的受众
+---
+
+
+
+
+受众是为不同消费者分组 API 的有用工具。您可以配置 Fern Docs 发布特定于某个`受众`的文档。您也可以在 [OpenAPI 规范中使用受众](/learn/api-definitions/openapi/extensions/audiences)。
+
+受众的常见示例包括:
+
+- 内部消费者(例如,使用 API 的前端开发人员)
+- Beta 测试人员
+- 客户
+
+默认情况下,如果未指定受众,则所有消费者都可以访问。
+
+## 配置
+
+Fern Definition 具有为不同端点、类型和属性标记不同受众的一级概念。
+
+要在 Fern Definition 中使用受众,请将其添加到 `api.yml` 中。
+
+在下面的示例中,我们为 `internal`、`beta` 和 `customer` 群体创建了受众:
+
+```yaml title='api.yml' {2-5}
+name: api
+audiences:
+ - internal
+ - beta
+ - customers
+```
+
+## 端点的受众
+
+要为特定消费者标记端点,请添加包含相关群体的 `audience`。
+
+在此示例中,`sendEmail` 端点仅对内部消费者可用:
+
+```yaml title='user.yml' {6-7}
+service:
+ base-path: /users
+ auth: true
+ endpoints:
+ sendEmail:
+ audiences:
+ - internal
+ path: /send-email
+ ...
+```
+
+## 类型的受众
+
+类型也可以标记为不同的受众。
+
+在此示例中,`Email` 类型对内部和 beta 消费者可用:
+
+```yaml title='user.yml' {5-7}
+Email:
+ properties:
+ subject: string
+ body: optional
+ audiences:
+ - internal
+ - beta
+```
+
+## 属性的受众
+
+类型的属性也可以标记为不同的受众。
+
+在此示例中,`to` 属性仅对 beta 消费者可用:
+
+```yaml title='user.yml' {8-9}
+Email:
+ properties:
+ subject: string
+ body: optional
+ to:
+ type: string
+ docs: The recipient of the email
+ audiences:
+ - beta
+```
+
+## SDK 的受众
+
+在 `generators.yml` 中,您可以应用受众过滤器,以便只有某些端点传递给生成器。
+
+以下示例配置 SDK 过滤 `customers`:
+
+```yaml title='generators.yml' {3-4}
+groups:
+ external:
+ audiences:
+ - customers
+ generators:
+ ...
+```
+
+## 文档的受众
+
+如果生成 Fern Docs,请更新您的 `docs.yml` 配置以包含您的受众。
+
+以下示例展示了如何配置您的 `docs.yml` 为 `customers` 受众发布文档:
+
+
+```yaml {3-4}
+navigation:
+ - api: API Reference
+ audiences:
+ - customers
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/auth.mdx b/fern/translations/zh/products/api-def/ferndef/auth.mdx
new file mode 100644
index 000000000..dfbf786e0
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/auth.mdx
@@ -0,0 +1,258 @@
+---
+title: 身份验证
+description: 在 Fern Definition 中配置 API 身份验证。为您的 API 端点设置 bearer token、基本身份验证、自定义头部和 OAuth。
+sidebar-title: 身份验证
+---
+
+身份验证方案的配置在 `api.yml` 文件中进行。所有 Fern 生成的 SDK 都支持直接配置和环境变量来配置身份验证凭据。
+
+```bash {5}
+fern/
+├─ fern.config.json # 根级别配置
+├─ generators.yml # 你正在使用的生成器
+└─ definition/
+ ├─ api.yml # API 级别配置
+ └─ imdb.yml # 端点、类型和错误
+```
+
+要添加身份验证方案,请在 `auth-schemes` 部分下指定身份验证方法。
+
+```yaml api.yml {1-2}
+auth-schemes:
+ AuthScheme:
+ ...
+```
+
+
+要在所有端点中应用身份验证方案,请在 `api.yml` 文件的 `auth` 部分中引用 `auth-scheme`。
+```yaml api.yml {1}
+auth: AuthScheme
+auth-schemes:
+ AuthScheme:
+ ...
+```
+
+
+## Bearer 身份验证
+
+首先在 `api.yml` 中定义一个 `Bearer` 身份验证方案:
+
+```yaml api.yml
+auth: Bearer
+auth-schemes:
+ Bearer:
+ scheme: bearer
+```
+
+这将生成一个 SDK,用户需要提供一个名为 `token` 的必需参数。
+
+```ts index.ts
+const client = new Client({
+ token: "ey34..."
+})
+```
+
+如果你想控制变量命名和要扫描的环境变量,请使用以下配置:
+
+```yaml title="api.yml" {5-7}
+auth: Bearer
+auth-schemes:
+ Bearer:
+ scheme: bearer
+ token:
+ name: apiKey
+ env: PLANTSTORE_API_KEY
+```
+
+生成的 SDK 会是这样:
+
+```ts index.ts
+
+// 使用 process.env.PLANTSTORE_API_KEY
+let client = new Client();
+
+// token 已被重命名为 apiKey
+client = new Client({
+ apiKey: "ey34..."
+})
+```
+
+## 基本身份验证
+
+首先在 `api.yml` 中定义一个 `Basic` 身份验证方案:
+
+```yaml api.yml
+auth: Basic
+auth-schemes:
+ Basic:
+ scheme: basic
+```
+
+这将生成一个 SDK,用户需要提供名为 `username` 和 `password` 的必需参数。
+
+```ts index.ts
+const client = new Client({
+ username: "joeschmoe"
+ password: "ey34..."
+})
+```
+
+如果你想控制变量命名和要扫描的环境变量,请使用以下配置:
+
+```yaml title="api.yml" {5-11}
+auth: Basic
+auth-schemes:
+ Basic:
+ scheme: basic
+ username:
+ name: clientId
+ env: PLANTSTORE_CLIENT_ID
+ password:
+ name: clientSecret
+ env: PLANTSTORE_CLIENT_SECRET
+```
+
+生成的 SDK 会是这样:
+
+```ts index.ts
+
+// 使用 process.env.PLANTSTORE_CLIENT_ID 和 process.env.PLANTSTORE_CLIENT_SECRET
+let client = new Client();
+
+// 参数已被重命名
+client = new Client({
+ clientId: "joeschmoe",
+ clientSecret: "ey34..."
+})
+```
+
+## 自定义头部(例如 API 密钥)
+
+你也可以使用自定义头部创建自己的身份验证方案。
+
+```yaml title="api.yml" {3-5}
+auth: ApiKeyAuthScheme
+auth-schemes:
+ ApiKeyAuthScheme:
+ header: X-API-Key
+ type: string
+```
+
+这将生成一个 SDK,用户需要提供一个名为 `apiKey` 的必需参数。
+
+```ts index.ts
+const client = new Client({
+ xApiKey: "ey34..."
+})
+```
+
+如果你想控制变量命名和要扫描的环境变量,请使用以下配置:
+
+```yaml title="api.yml" {7-8}
+auth: ApiKeyAuthScheme
+auth-schemes:
+ ApiKeyAuthScheme:
+ header: X-API-Key
+ type: string
+ name: apiKey
+ env: PLANTSTORE_API_KEY
+```
+
+生成的 SDK 会是这样:
+
+```ts index.ts
+
+// 使用 process.env.PLANTSTORE_API_KEY
+let client = new Client();
+
+// 参数已被重命名
+client = new Client({
+ apiKey: "ey34..."
+})
+```
+
+## OAuth 客户端凭据
+
+
+
+如果你的 API 使用 OAuth,你可以在 `api.yml` 中指定 oauth 方案,并在单独的 `auth.yml` 文件中定义令牌检索端点([示例](https://github.com/fern-api/fern/blob/3137938b70e058f3691ddef34d5c1cc29acc4b80/test-definitions/fern/apis/oauth-client-credentials/definition/api.yml))。
+
+```yaml api.yml
+name: api
+
+imports:
+ auth: auth.yml
+
+auth: OAuthScheme
+auth-schemes:
+ OAuthScheme:
+ scheme: oauth
+ type: client-credentials
+ client-id-env: YOUR_CLIENT_ID
+ client-secret-env: YOUR_CLIENT_SECRET
+ get-token:
+ endpoint: auth.getTokenWithClientCredentials
+ request-properties:
+ client-id: $request.client_id # 格式: parameter-name: $request.property_name
+ client-secret: $request.client_secret # 格式: parameter-name: $request.property_name
+ response-properties:
+ access-token: $response.access_token # 格式: parameter-name: $response.property_name
+ expires-in: $response.expires_in # 格式: parameter-name: $response.property_name
+
+```
+
+`request-properties` 和 `response-properties` 将 OAuth 标准参数映射到在 `auth.yml` 中定义的实际端点的请求和响应字段名称。
+
+
+ 如果设置了 `expires-in` 属性,生成的 OAuth 令牌提供程序将在令牌过期时自动刷新令牌。否则,假设访问令牌永久有效。
+
+
+相应的 `auth.yml` 文件([示例](https://github.com/fern-api/fern/blob/3137938b70e058f3691ddef34d5c1cc29acc4b80/test-definitions/fern/apis/oauth-client-credentials/definition/auth.yml))定义了令牌端点:
+
+```yaml title="auth.yml"
+types:
+ TokenResponse:
+ docs: |
+ OAuth 令牌响应。
+ properties:
+ access_token: string
+ expires_in: integer
+ refresh_token: optional
+
+service:
+ auth: false
+ base-path: /
+ endpoints:
+ getTokenWithClientCredentials:
+ path: /token
+ method: POST
+ request:
+ name: GetTokenRequest
+ body:
+ properties:
+ client_id: string
+ client_secret: string
+ audience: literal<"https://api.example.com">
+ grant_type: literal<"client_credentials">
+ scope: optional
+ response: TokenResponse
+```
+
+如果你的 OAuth 服务器托管在与主 API 不同的 URL 上,你可以使用[每个环境多个 URL](/api-definitions/ferndef/api-yml/environments#multiple-urls-per-environment) 为身份验证和 API 调用指定单独的基础 URL。
+
+有了这些,所有的 OAuth 逻辑都会在生成的 SDK 中自动处理。只要你配置了这些设置,你的客户端将自动检索访问令牌并根据需要刷新它。
+
+在使用文档 playground 时,可以选择设置 `token-header` 和 `token-prefix` 来自定义头部键名和头部值前缀,以匹配 API 身份验证方案的预期格式。
+
+例如,以下配置将产生头部 `Fern-Authorization: Fern-Bearer `:
+
+```yaml api.yml {5-6}
+auth-schemes:
+ OAuthScheme:
+ scheme: oauth
+ type: client-credentials
+ token-header: Fern-Authorization
+ token-prefix: Fern-Bearer
+ get-token:
+ ...
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/availability.mdx b/fern/translations/zh/products/api-def/ferndef/availability.mdx
new file mode 100644
index 000000000..edaa5f2d1
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/availability.mdx
@@ -0,0 +1,103 @@
+---
+title: Fern Definition 中的可用性
+description: 向 Fern Definition API 服务、端点、类型或属性添加可用性标识,以指示其发布状态。
+sidebar-title: 可用性
+---
+
+您可以在 Fern Definition 中为端点、类型或属性添加 `availability`。您可以在 [`docs.yml` 文件](/learn/docs/configuration/site-level-settings)中配置 API 参考文档各部分的 `availability`。
+
+## 端点、类型和属性
+
+可用性可以是:
+- `in-development` 表示正在开发中;将显示 `Beta` 标签
+- `pre-release` 表示可用;将显示 `Beta` 标签
+- `deprecated` 表示将来会被移除;将显示 `Deprecated` 标签
+- `generally-available` 表示稳定且可供使用;将显示 `GA` 标签
+
+### 端点
+
+
+```yaml {6}
+service:
+ base-path: /pet
+ auth: true
+ endpoints:
+ add:
+ availability: deprecated
+ display-name: Add pet
+ docs: Add a new Pet to the store
+ method: POST
+ path: ""
+ request: AddPetRequest
+ response: Pet
+```
+
+
+在 Fern Docs 中,这将显示为:
+
+
+
+
+
+### 类型
+
+
+```yaml {15}
+ Pet:
+ properties:
+ id:
+ type: integer
+ docs: A unique ID for the Pet
+ name:
+ type: string
+ docs: The first name of the Pet
+ photoUrls:
+ type: list
+ docs: A list of publicly available URLs featuring the Pet
+ availability: generally-available
+ category:
+ type: optional
+ availability: pre-release
+
+ Category:
+ properties:
+ id: optional
+ name: optional
+```
+
+
+在 Fern Docs 中,这将显示为:
+
+
+
+
+
+### 属性
+
+
+```yaml {12}
+ Pet:
+ properties:
+ id:
+ type: integer
+ docs: A unique ID for the Pet
+ name:
+ type: string
+ docs: The first name of the Pet
+ photoUrls:
+ type: list
+ docs: A list of publicly available URLs featuring the Pet
+ availability: deprecated
+ category: optional
+```
+
+
+在 Fern Docs 中,这将显示为:
+
+
+
+
+
+## 部分
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/depending-on-other-apis.mdx b/fern/translations/zh/products/api-def/ferndef/depending-on-other-apis.mdx
new file mode 100644
index 000000000..f5b091f9a
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/depending-on-other-apis.mdx
@@ -0,0 +1,69 @@
+---
+title: "依赖其他 API"
+subtitle: 导入 API 定义以生成统一的 SDK
+sidebar-title: 依赖其他 API
+---
+
+Fern 允许您将其他 API 导入到您的 API 中。
+
+这在以下情况下通常很有用:
+
+- 您希望在您的 API 中重用另一个 API 的类型
+- 您希望将多个微服务的 API 合并到一个 SDK 中(类似于 AWS SDK)
+
+## 注册依赖的 API
+
+第一步是**注册**您要依赖的 API。为此,使用 `register` 命令:
+
+```
+$ fern register
+[some-dependency]: Uploading definition...
+[some-dependency]: Registered @fern/some-dependency:0.0.1
+```
+
+## 依赖已注册的 API
+
+要添加对另一个 API 的依赖,您必须添加一个 `dependencies.yml` 来声明您希望依赖的 API。
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的 `dependencies.yml` 包含您希望依赖的所有 API 列表:
+
+```yaml dependencies.yml
+dependencies:
+ "@fern/some-dependency": "0.0.1"
+```
+
+接下来,您需要在您的 Fern 定义中创建一个文件夹来容纳依赖项。在文件夹内,创建一个特殊文件 `__package__.yml`,该文件指定您要添加的依赖项和版本。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```yaml __package__.yml
+export:
+ dependency: "@fern/some-dependency"
+```
+
+当您使用 `fern generate` 生成 SDK 时,`__package__.yml` 文件将有效地被您所依赖的 API 替换。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/endpoints.mdx b/fern/translations/zh/products/api-def/ferndef/endpoints.mdx
new file mode 100644
index 000000000..b83cb83f6
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/endpoints.mdx
@@ -0,0 +1,664 @@
+---
+title: Fern 定义中的端点
+description: 在 Fern 定义中将相关的 API 端点组织到服务中,并定义每个端点的 URL、HTTP 方法、请求、响应、错误等。
+sidebar-title: 端点
+---
+
+在 Fern 中,您可以将相关的端点组织到一个**服务**中。这种分组方式提高了清晰度,使生成的 SDK 更加符合习惯。
+
+## 服务定义
+
+每个服务定义:
+
+1. 一个**基础路径**:所有端点 HTTP 路径的共同前缀
+2. 服务是否需要[身份验证](/learn/api-definitions/ferndef/authentication)
+3. **端点**
+
+
+ ```yaml
+ service:
+ base-path: /users # 这定义了方法的组/命名空间
+ auth: false
+ endpoints: {}
+ ```
+
+
+
+ 要定义空基础路径的服务,请使用空字符串:`base-path: ""`
+
+
+### 章节显示名称
+
+默认情况下,API 参考中的章节名称来源于服务文件名(例如,`user.yml` 变成 "User")。要覆盖章节的显示名称,[请在 `docs.yml` 中使用 `section` 属性](/docs/api-references/customize-api-reference-layout#renaming-sections)。
+
+### SDK 方法名称
+
+SDK 方法名称直接从服务文件名和端点键派生而来。文件名成为命名空间,端点键成为方法名称。
+
+例如,给定以下定义:
+
+
+```yaml
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ create:
+ path: ""
+ method: POST
+ request: CreateUserRequest
+```
+
+
+Fern 生成一个名为 `client.users.create()` 的方法。
+
+## 端点
+
+端点包括:
+
+- 一个 **URL 路径** _(可选择性地包括路径参数)_
+- 一个**显示名称** _(可选)_
+- 一个 **HTTP 方法**
+- **请求信息** _(可选)_
+ - **查询参数**
+ - **标头**
+ - **请求体**
+- **成功(200)响应**信息 _(可选)_
+- 此端点可能返回的**错误(非 200)响应** _(可选)_
+
+### URL 路径
+
+每个端点都有一个 URL 路径。
+
+
+```yaml {6}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getAllUsers:
+ path: /all
+ method: GET
+```
+
+
+端点的完整路径是以下内容的连接:
+
+- [环境](/learn/api-definitions/ferndef/api-yml/environments) URL
+- 服务 `base-path`
+- 端点 `path`
+
+### 端点显示名称
+
+显示名称将作为端点的标题出现。默认情况下,显示名称等于端点名称的"标题大小写"。如果您想要自定义端点名称,可以**设置显示名称**。
+
+在下面的示例中,["Add a new plant to the store"](https://plantstore.dev/api-reference/plant-store-api/plants/add-plant) 显示为 API 参考中端点页面的标题。
+
+
+```yaml {7}
+service:
+ base-path: /v3
+ auth: false
+ endpoints:
+ addPlant:
+ path: /plant
+ display-name: Add a new plant to the store
+ method: POST
+```
+
+
+### 路径参数
+
+为您的端点提供路径参数以创建动态 URL。
+
+
+```yaml {6-8}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getUser:
+ path: /{userId}
+ path-parameters:
+ userId: string
+ method: GET
+```
+
+
+服务也可以有路径参数:
+
+
+ ```yaml {2-4}
+ service:
+ base-path: /projects/{projectId}
+ path-parameters:
+ projectId: string
+ auth: false
+ endpoints:
+ ...
+ ```
+
+
+### 查询参数
+
+每个端点可以指定查询参数:
+
+
+```yaml
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getAllUsers:
+ path: /all
+ method: GET
+ request:
+ # 符合习惯的 SDK 需要这个名称
+ name: GetAllUsersRequest
+ query-parameters:
+ limit: optional
+```
+
+
+#### `allow-multiple`
+
+使用 `allow-multiple` 指定查询参数在 URL 中允许多次出现,如 `?filter=jane&filter=smith`。这将修改生成的 SDK,以便使用者可以为查询参数提供多个值。
+
+
+```yaml {5}
+ ...
+ query-parameters:
+ filter:
+ type: string
+ allow-multiple: true
+```
+
+
+### 身份验证
+
+每个端点可以覆盖服务中指定的身份验证行为。
+
+
+ ```yaml
+ service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getMe:
+ path: ""
+ method: GET
+ # 这个端点将进行身份验证
+ auth: true
+ docs: 根据 Authorization 标头返回当前用户。
+ ```
+
+
+### 标头
+
+每个端点可以指定请求标头:
+
+
+ ```yaml
+ service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getAllUsers:
+ path: /all
+ method: GET
+ request:
+ # 符合习惯的 SDK 需要这个名称
+ name: GetAllUsersRequest
+ headers:
+ X-Endpoint-Header: string
+ ```
+
+
+服务也可以指定请求标头。这些标头将级联到服务的端点。
+
+
+ ```yaml {4-5}
+ service:
+ base-path: /users
+ auth: false
+ headers:
+ X-Service-Header: string
+ endpoints:
+ getAllUsers:
+ path: /all
+ method: GET
+ request:
+ # 符合习惯的 SDK 需要这个名称
+ name: GetAllUsersRequest
+ headers:
+ X-Endpoint-Header: string
+ ```
+
+
+### 请求体
+
+端点可以指定请求体类型。
+
+
+```yaml {10}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ setUserName:
+ path: /{userId}/set-name
+ path-parameters:
+ userId: string
+ method: POST
+ request: string
+```
+
+
+#### 内联请求体
+
+如果请求体是一个对象,您可以**内联类型声明**。这使生成的 SDK 更加符合习惯。
+
+
+ ```yaml
+ service:
+ base-path: /users
+ auth: false
+ endpoints:
+ createUser:
+ path: /create
+ method: POST
+ request:
+ # 符合习惯的 SDK 需要这个名称
+ name: CreateUserRequest
+ body:
+ properties:
+ userName: string
+ ```
+
+
+### 成功响应
+
+端点可以指定 `response`,这是成功(200)调用时将返回的体的类型。
+
+
+```yaml
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getAllUsers:
+ path: /all
+ method: GET
+ response: list
+
+types:
+ User:
+ properties:
+ userId: string
+ name: string
+```
+
+
+### 响应状态码
+
+您还可以使用 `status-code` 字段为成功响应指定自定义状态码。
+
+
+```yaml {11}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ create: :
+ path: ""
+ method: POST
+ request: CreateUserRequest
+ response:
+ type: User
+ status-code: 201
+
+types:
+ User:
+ properties:
+ userId: string
+ name: string
+```
+
+
+### 分页
+
+Fern 支持偏移量、游标、URI 和基于路径的分页方案。要在[生成的 SDK](/learn/sdks/deep-dives/auto-pagination) 中设置自动分页:
+
+1. 使用 `pagination` 字段标注所需的分页端点
+2. 指定分页方案(`offset`、`cursor`、`next_uri` 或 `next_path`)
+3. 使用点访问表示法指定 `results` 的位置。
+
+
+在大多数偏移分页配置中包含 `step`,以确保偏移量按页面大小递增。当您的 API 为附加页面返回布尔指示符时,请使用 `has-next-page`。
+
+
+
+```yaml title="偏移分页" {8-12}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ list:
+ path: ""
+ method: GET
+ pagination:
+ offset: $request.page
+ step: $request.page_size # 推荐
+ results: $response.data
+ has-next-page: $response.has_more
+ request:
+ name: ListUsersRequest
+ query-parameters:
+ page: optional
+ page_size: optional
+ response: ListUsersResponse
+
+types:
+ ListUsersResponse:
+ properties:
+ data: list
+ has_more: boolean
+```
+
+```yaml title="游标分页" {8-11}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ list:
+ path: ""
+ method: GET
+ pagination:
+ cursor: $request.starting_after
+ next_cursor: $response.page.next.starting_after
+ results: $response.data
+ request:
+ name: ListUsersRequest
+ query-parameters:
+ starting_after: optional
+ response: ListUsersResponse
+
+types:
+ ListUsersResponse:
+ properties:
+ data: list
+ page:
+ properties:
+ next:
+ properties:
+ starting_after: optional
+```
+
+```yaml title="URI 分页" {8-10}
+service:
+ base-path: /plants
+ auth: false
+ endpoints:
+ list:
+ path: ""
+ method: GET
+ pagination:
+ next_uri: $response.next_page_url
+ results: $response.data
+ response: ListPlantsResponse
+
+types:
+ ListPlantsResponse:
+ properties:
+ data: list
+ next_page_url: optional
+```
+
+```yaml title="路径分页" {8-10}
+service:
+ base-path: /plants
+ auth: false
+ endpoints:
+ list:
+ path: ""
+ method: GET
+ pagination:
+ next_path: $response.next_page_path
+ results: $response.data
+ response: ListPlantsResponse
+
+types:
+ ListPlantsResponse:
+ properties:
+ data: list
+ next_page_path: optional
+```
+
+
+`pagination` 字段支持以下属性:
+
+
+
+### 幂等端点
+
+将端点标记为幂等,以允许 SDK 用户指定幂等性标头进行安全的请求重试。您还必须在 [`api.yml` 中配置幂等性标头](/learn/api-definitions/ferndef/api-yml/global-headers#idempotency-headers)来定义哪些标头可用。
+
+```yaml title="service.yml" {8}
+service:
+ base-path: /transactions
+ auth: true
+ endpoints:
+ send:
+ path: ""
+ method: POST
+ idempotent: true
+ request: SendTransactionRequest
+ response: Transaction
+```
+
+### 错误响应
+
+端点可以指定错误响应,详细说明端点可能返回的非 200 响应。
+
+
+```yaml
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getUser:
+ path: /{userId}
+ path-parameters:
+ userId: string
+ method: GET
+ response: User
+ errors:
+ - UserNotFoundError
+
+types:
+ User:
+ properties:
+ userId: string
+ name: string
+
+errors:
+ UserNotFoundError:
+ status-code: 404
+```
+
+
+您可以在[错误](/learn/api-definitions/ferndef/errors)页面了解更多关于如何定义错误的信息。
+
+## 指定示例
+
+当您声明一个示例时,您也可以指定该端点可能如何使用的一些示例。编译器使用这些示例来增强生成的输出。示例将在您的 SDK、API 文档和 Postman 集合中显示为注释。
+
+您可以为端点、类型和错误添加示例。
+
+
+```yaml {13-19}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getUser:
+ path: /{userId}
+ path-parameters:
+ userId: string
+ method: GET
+ response: User
+ errors:
+ - UserNotFoundError
+ examples:
+ - path-parameters:
+ userId: alice-user-id
+ response:
+ body:
+ userId: alice-user-id
+ name: Alice
+
+types:
+ User:
+ properties:
+ userId: string
+ name: string
+
+errors:
+ UserNotFoundError:
+ status-code: 404
+```
+
+
+如果您要向端点添加示例,而该类型已经有示例,您可以使用 `$` 引用它。
+```yaml
+service:
+ auth: true
+ base-path: /address
+ endpoints:
+ create:
+ method: POST
+ path: ""
+ request: CreateAddress
+ response: Address
+ examples:
+ - request: $CreateAddress.WhiteHouse
+ response:
+ body: $Address.WhiteHouseWithID
+
+ CreateAddress:
+ properties:
+ street1: string
+ street2: optional
+ city: string
+ state: string
+ postalCode: string
+ country: string
+ isResidential: boolean
+ examples:
+ - name: WhiteHouse
+ value:
+ street1: 1600 Pennsylvania Avenue NW
+ city: Washington DC
+ state: Washington DC
+ postalCode: "20500"
+ country: US
+ isResidential: true
+
+ Address:
+ extends: CreateAddress
+ properties:
+ id:
+ type: uuid
+ docs: The unique identifier for the address.
+ examples:
+ - name: WhiteHouseWithID
+ value:
+ id: 65ce514c-41e3-11ee-be56-0242ac120002
+ street1: 1600 Pennsylvania Avenue NW
+ city: Washington DC
+ state: Washington DC
+ postalCode: "20500"
+ country: US
+ isResidential: true
+````
+
+示例包含端点调用的所有信息,包括请求体、路径参数、查询参数、标头和响应体。
+
+
+ ```yaml
+ examples:
+ - path-parameters:
+ userId: some-user-id
+ query-parameters:
+ limit: 50
+ headers:
+ X-My-Header: some-value
+ response:
+ body:
+ response-field: hello
+ ```
+
+
+#### 失败示例
+
+您也可以指定失败的端点调用示例。向响应示例添加 `error` 属性来指定您正在演示的失败。
+
+
+```yaml {5}
+examples:
+ - path-parameters:
+ userId: missing-user-id
+ response:
+ error: UserNotFoundError
+
+errors:
+ UserNotFoundError:
+ status-code: 404
+```
+
+
+如果错误有体,那么您必须在示例中包含该体。
+
+
+```yaml {6, 11}
+examples:
+ - path-parameters:
+ userId: missing-user-id
+ response:
+ error: UserNotFoundError
+ body: "User with id `missing-user-id` was not found"
+
+errors:
+ UserNotFoundError:
+ status-code: 404
+ type: string
+```
+
+
+#### 从类型引用示例
+
+为了避免重复,您可以使用 `$` 从类型引用示例。
+
+
+```yaml {12}
+service:
+ base-path: /users
+ auth: true
+ endpoints:
+ getUser:
+ method: GET
+ path: /{userId}
+ path-parameters:
+ userId: UserId
+ examples:
+ - path-parameters:
+ userId: $UserId.Example1
+
+types:
+ UserId:
+ type: integer
+ examples:
+ - name: Example1
+ value: user-id-123
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/endpoints/bytes.mdx b/fern/translations/zh/products/api-def/ferndef/endpoints/bytes.mdx
new file mode 100644
index 000000000..444c61a9a
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/endpoints/bytes.mdx
@@ -0,0 +1,56 @@
+---
+title: 二进制数据和文件
+subtitle: 使用 `bytes` 类型处理 API 中的二进制数据
+sidebar-title: 二进制数据和文件
+---
+
+
+
+ `bytes` 类型允许您在请求和响应中处理二进制数据。
+
+
+## 发送字节数据
+
+如果您的 API 需要发送字节流(即通常用于音频、图像和其他文件等资源),那么您可以在 Fern Definition 中使用 `bytes` 类型来建模。
+
+```yml audio.yml
+service:
+ base-path: /audio
+ endpoints:
+ upload:
+ display-name: Upload audio
+ method: POST
+ path: /upload
+ content-type: application/octet-stream
+ request:
+ type: bytes
+ docs: The bytes of the MP3 file that you would like to upload
+```
+
+## 接收字节数据
+
+
+ 在响应中处理二进制数据时,请使用 `type: file` 而不是 `type: bytes`。
+
+
+另一方面,如果您的 API 返回字节流,那么您可以利用 `bytes` 类型作为响应。
+
+```yml textToSpeech.yml
+service:
+ base-path: /tts
+ endpoints:
+ upload:
+ display-name: Upload audio
+ method: POST
+ path: ""
+ request:
+ name: TTSRequest
+ body:
+ properties:
+ text:
+ type: string
+ docs: The text that you want converted to speech.
+ response:
+ type: file
+ docs: The bytes of the audio file.
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/endpoints/multipart.mdx b/fern/translations/zh/products/api-def/ferndef/endpoints/multipart.mdx
new file mode 100644
index 000000000..c3344dc9e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/endpoints/multipart.mdx
@@ -0,0 +1,48 @@
+---
+title: 多部分文件上传
+description: 使用 `multiform` 内容类型记录端点。
+sidebar-title: 多部分文件上传
+---
+
+
+在 Fern 中,端点定义在 `endpoints` 键下。如果您的端点请求包含文件上传,您可以使用 `file` 类型来指示请求是 `multiform` 内容类型。下面的示例演示了一个在请求体中包含文件的端点。
+
+
+```yaml {12}
+service:
+ base-path: /documents
+ auth: false
+ endpoints:
+ uploadDocument:
+ path: /upload
+ method: POST
+ request:
+ name: UploadDocumentRequest
+ body:
+ properties:
+ file: file
+```
+
+
+在给定的多部分请求中,带有 `format:binary` 的字符串参数将表示任意文件。
+
+## 文件列表
+
+如果您的端点支持文件列表,那么您的请求体必须如此指示。
+
+
+```yaml {12}
+service:
+ base-path: /documents
+ auth: false
+ endpoints:
+ uploadDocuments:
+ path: /upload
+ method: POST
+ request:
+ name: UploadDocumentsRequest
+ body:
+ properties:
+ files: list
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/endpoints/rest.mdx b/fern/translations/zh/products/api-def/ferndef/endpoints/rest.mdx
new file mode 100644
index 000000000..3e1bc9568
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/endpoints/rest.mdx
@@ -0,0 +1,45 @@
+---
+title: HTTP JSON 端点
+sidebar-title: HTTP JSON 端点
+---
+
+
+Fern 中的端点定义在 `endpoints` 键下。以下是定义单个 REST 端点的示例:
+
+```yml title="users.yml" maxLines=0
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ createUser:
+ path: /create
+ method: POST
+ request:
+ body:
+ properties:
+ userName: string
+```
+
+## 示例
+
+你可以通过使用 `examples` 键来提供请求和响应的示例。
+
+```yaml {11-17}
+service:
+ base-path: /users
+ auth: false
+ endpoints:
+ getUser:
+ path: /{userId}
+ path-parameters:
+ userId: string
+ method: GET
+ response: User
+ examples:
+ - path-parameters:
+ userId: alice-user-id
+ response:
+ body:
+ userId: alice-user-id
+ name: Alice
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/endpoints/sse.mdx b/fern/translations/zh/products/api-def/ferndef/endpoints/sse.mdx
new file mode 100644
index 000000000..07dcfaed9
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/endpoints/sse.mdx
@@ -0,0 +1,100 @@
+---
+title: 服务器发送事件和流式 API
+subtitle: 使用 `response-stream` 键来建模流式端点
+sidebar-title: 服务器发送事件和流式 API
+---
+
+
+
+
+在端点上指定 `response-stream` 允许您表示流式响应的端点。
+
+## JSON 流式传输
+
+如果您的 API 返回一系列 `JSON` 块,如下所示
+
+```json
+{ "text": "Hi, I am a" }
+{ "text": "chatbot. Do you have any"}
+{ "text": "questions for me"}
+```
+
+那么只需在端点的 `response-stream` 下指定响应即可。
+
+```yaml title="chat.yml" {4}
+service:
+ base-path: /chat
+ endpoints:
+ stream:
+ method: POST
+ path: ""
+ response-stream: Chat
+
+types:
+ Chat:
+ properties:
+ text: string
+```
+
+## 服务器发送事件
+
+如果您的 API 返回服务器发送事件,带有 `data` 和 `event` 键,如下所示
+
+```json
+data: { "text": "Hi, I am a" }
+data: { "text": "chatbot. Do you have any"}
+data: { "text": "questions for me"}
+```
+
+那么请确保包含 `format: sse`。
+
+```yaml title="chat.yml" {9}
+service:
+ base-path: /chat
+ endpoints:
+ stream:
+ method: POST
+ path: ""
+ response-stream:
+ type: Chat
+ format: sse
+
+types:
+ Chat:
+ properties:
+ text: string
+```
+
+## `Stream` 参数
+
+端点具有 `stream` 参数来控制响应是否流式传输已成为常见做法。Fern 以一等公民的方式支持此模式。
+
+只需指定 `stream-condition` 以及普通响应和流式响应:
+
+```yaml title="chat.yml" {7}
+service:
+ base-path: /chat
+ endpoints:
+ stream:
+ method: POST
+ path: ""
+ stream-condition: $request.stream
+ request:
+ name: StreamChatRequest
+ body:
+ properties:
+ stream: boolean
+ response: Chat
+ response-stream:
+ type: ChatChunk
+ format: sse
+
+types:
+ Chat:
+ properties:
+ text: string
+ tokens: integer
+ ChatChunk:
+ properties:
+ text: string
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/errors.mdx b/fern/translations/zh/products/api-def/ferndef/errors.mdx
new file mode 100644
index 000000000..ba16cba5c
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/errors.mdx
@@ -0,0 +1,26 @@
+---
+title: Fern Definition 中的错误
+description: 在 Fern Definition 中添加表示 API 端点失败响应的错误。
+sidebar-title: Fern Definition 中的错误
+---
+
+错误表示端点的失败(非 200)响应。
+
+一个错误包含:
+
+- HTTP 状态码
+- 主体类型 _(可选)_
+
+
+```yaml
+errors:
+ UserNotFoundError:
+ status-code: 404
+ type: UserNotFoundErrorBody
+
+types:
+ UserNotFoundErrorBody:
+ properties:
+ requestedUserId: string
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/examples.mdx b/fern/translations/zh/products/api-def/ferndef/examples.mdx
new file mode 100644
index 000000000..f02496a9e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/examples.mdx
@@ -0,0 +1,368 @@
+---
+title: Fern 定义中的示例
+subtitle: 使用 Fern 定义添加 API 示例,这些示例会显示在 SDK 注释、API 参考文档和 Postman 集合中。
+sidebar-title: Fern 定义中的示例
+---
+
+您可以为类型和端点添加示例。示例会显示为 SDK 中的注释、文档的请求和响应部分,以及 Postman 集合中。
+
+## 验证
+
+Fern CLI 会验证您的示例是否与预期的类型匹配。以下内容无法编译:
+
+```yaml
+types:
+ UserId:
+ type: integer
+ examples:
+ - value: hello # 不是整数
+```
+
+```bash CLI 错误消息
+[api]: example.yml -> types -> UserId -> examples[0]
+ 期望示例为整数。示例值为:"hello"
+```
+
+## 引用示例
+
+您可以引用来自其他类型、端点或错误的示例。
+
+就像类型一样,您可以组合示例。要引用来自其他类型的示例,请使用 `$`。
+
+```yaml {14}
+types:
+ UserId:
+ type: integer
+ examples:
+ - name: Example1
+ value: user-id-123
+
+ User:
+ properties:
+ id: UserId
+ name: string
+ examples:
+ - value:
+ id: $UserId.Example1
+ name: Jane Smith
+```
+
+## 类型示例
+
+### 对象
+
+```yml
+types:
+ ShipTo:
+ properties:
+ street1: string
+ street2: optional
+ city: string
+ state: string
+ postalCode: string
+ country: Country
+ isResidential: boolean
+ examples:
+ - name: WhiteHouse
+ value:
+ street1: 1600 Pennsylvania Avenue NW
+ city: Washington DC
+ state: Washington DC
+ postalCode: "20500"
+ country: US
+ isResidential: true
+ - name: EmpireStateBuilding
+ value:
+ street1: 350 5th Ave
+ street2: Attn: Maintenance Department
+ city: New York
+ state: NY
+ postalCode: "10118"
+ country: US
+ isResidential: false
+```
+
+
+```typescript
+/**
+ * 代表一个邮寄地址。
+ *
+ * 白宫地址
+ * @example {
+ * street1: "1600 Pennsylvania Avenue NW",
+ * city: "Washington DC",
+ * state: "Washington DC",
+ * postalCode: "20500",
+ * country: "US",
+ * isResidential: true
+ * }
+ *
+ * * 帝国大厦地址
+ * @example {
+ * street1: "350 5th Ave",
+ * street2: "Attn: Maintenance Department",
+ * city: "New York",
+ * state: "NY",
+ * postalCode: "10118",
+ * country: "US",
+ * isResidential: false
+ * }
+ */
+type ShipTo = {
+ street1: string;
+ street2?: string;
+ city: string;
+ state: string;
+ postalCode: string;
+ country: Country;
+ isResidential: boolean;
+};
+```
+
+
+### 列表
+
+```yml
+ Shipments:
+ type: list
+ examples:
+ - name: Default
+ value:
+ - status: "InTransit"
+ estimatedDeliveryDate: "2024-01-11"
+ - status: "Delivered"
+ estimatedDeliveryDate: "2024-01-13"
+```
+
+### 联合
+
+#### 有区分的联合
+
+```yml
+types:
+ Animal:
+ union:
+ dog: Dog
+ cat: Cat
+ examples:
+ - value:
+ type: dog
+ likesToWoof: true
+ Dog:
+ properties:
+ likesToWoof: boolean
+ Cat:
+ properties:
+ likesToMeow: boolean
+```
+
+
+```typescript
+/**
+ * 代表一个动物,可以是狗或猫。
+ *
+ * 狗的示例:
+ * @example {
+ * type: "dog",
+ * likesToWoof: true
+ * }
+ */
+type Animal = Dog | Cat;
+```
+
+
+#### 无区分的联合
+
+```yml
+types:
+ Animal:
+ discriminated: false
+ union:
+ - Dog
+ - Cat
+ examples:
+ - value:
+ likesToMeow: true
+ Dog:
+ properties:
+ likesToWoof: boolean
+ Cat:
+ properties:
+ likesToMeow: boolean
+```
+
+
+```typescript
+/**
+ * 代表一个动物,可以是狗或猫。
+ *
+ * 动物作为猫的示例:
+ * @example {
+ * likesToMeow: true
+ * }
+ */
+type Animal = Dog | Cat;
+```
+
+
+### 别名
+
+```yml
+types:
+ UserId:
+ docs: 用户的唯一标识符
+ type: string
+ examples:
+ - value: user-id-123
+```
+
+
+ ```typescript
+ /**
+ * 用户的唯一标识符 *
+ * @example "user-id-123"
+ */
+ type UserId = string;
+ ```
+
+
+## 端点示例
+
+您可以为端点添加成功和错误响应的示例。示例可以引用类型的示例以避免重复。
+
+```yml
+service:
+ auth: true
+ base-path: ""
+ endpoints:
+ CreateShippingLabel:
+ docs: 创建新的运输标签。
+ method: POST
+ path: /shipping
+ request: CreateShippingLabelRequest
+ response: ShippingLabel
+ errors:
+ - NotAuthorized
+ - InsufficientFunds
+ examples:
+ # 不引用其他示例的成功响应。
+ - request:
+ orderId: "online_789"
+ weightInOunces: 5
+ response:
+ body:
+ orderId: "online_789"
+ weightInOunces: 5
+ trackingNumber: "1Z26W8370303469306"
+ price: 2.50
+
+ # 使用引用的成功响应。
+ - request: $CreateShippingLabelRequest.SuccessfulRequest
+ response:
+ body: $ShippingLabel.Default
+
+ # 错误响应。
+ - request: $CreateShippingLabelRequest.InsufficientFundsRequest
+ response:
+ error: InsufficientFunds
+ body: $InsufficientFundsBody.Default
+
+types:
+ CreateShippingLabelRequest:
+ properties:
+ orderId: string
+ weightInOunces: integer
+ examples:
+ - name: SuccessfulRequest
+ value:
+ orderId: "online_123"
+ weightInOunces: 13
+ - name: InsufficientFundsRequest
+ value:
+ orderId: "online_456"
+ weightInOunces: 2000
+
+ ShippingLabel:
+ properties:
+ orderId: string
+ weightInOunces: integer
+ trackingNumber: string
+ price: double
+ examples:
+ - name: Default
+ value:
+ orderId: "online_123"
+ weightInOunces: 13
+ trackingNumber: "1Z12345E0205271688"
+ price: 12.35
+
+ InsufficientFundsBody:
+ properties:
+ message: string
+ examples:
+ - name: Default
+ value:
+ message: "Insufficient funds to create shipping label."
+
+errors:
+ NotAuthorized:
+ status-code: 401
+ InsufficientFunds:
+ status-code: 422
+ type: InsufficientFundsBody
+```
+
+### 带请求头的示例
+
+当您在 `api.yml` 中定义了[全局请求头](/api-definitions/ferndef/api-yml/global-headers#global-headers)时,必须在示例中包含它们:
+
+```yml {15-16}
+service:
+ auth: true
+ base-path: ""
+ endpoints:
+ CreateShippingLabel:
+ docs: 创建新的运输标签。
+ method: POST
+ path: /shipping
+ request: CreateShippingLabelRequest
+ response: ShippingLabel
+ errors:
+ - NotAuthorized
+ - InsufficientFunds
+ examples:
+ - headers:
+ X-App-Id: "app_12345"
+ request:
+ orderId: "online_789"
+ weightInOunces: 5
+ response:
+ body:
+ orderId: "online_789"
+ weightInOunces: 5
+ trackingNumber: "1Z26W8370303469306"
+ price: 2.50
+```
+
+## 路径参数示例
+
+```yml
+service:
+ auth: true
+ base-path: ""
+ endpoints:
+ TrackShipment:
+ docs: 跟踪货物的状态。
+ method: GET
+ path: /shipping/{trackingNumber}
+ path-parameters:
+ trackingNumber: string
+ response: ShipmentStatus
+ examples:
+ - path-parameters:
+ trackingNumber: "1Z26W8370303469306"
+ response:
+ body:
+ status: "InTransit"
+ estimatedDeliveryDate: "2024-01-11"
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/export-openapi.mdx b/fern/translations/zh/products/api-def/ferndef/export-openapi.mdx
new file mode 100644
index 000000000..3757bc618
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/export-openapi.mdx
@@ -0,0 +1,19 @@
+---
+title: 从 Fern Definition 导出到 OpenAPI
+description: 使用 fern export 命令将 Fern Definition 导出为 OpenAPI 3.1 格式。防止供应商锁定并轻松转换您的 API 定义。
+sidebar-title: 从 Fern Definition 导出到 OpenAPI
+---
+
+为了防止被锁定在 Fern Definition 格式中,您可以随时使用 [`fern export` 命令](/cli-api-reference/cli-reference/commands#fern-export)将您的 API 定义导出为 OpenAPI 3.1。
+
+如果您在 `fern/apis/` 文件夹中定义了多个 API,请使用 `--api` 来指定要导出的 API。
+
+
+ ```bash
+ fern export path/to/openapi.yml
+ fern export path/to/openapi.json
+
+ # 指定要导出的 API
+ fern export --api public-api path/to/openapi.yml
+ ```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/imports.mdx b/fern/translations/zh/products/api-def/ferndef/imports.mdx
new file mode 100644
index 000000000..e25c468c7
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/imports.mdx
@@ -0,0 +1,23 @@
+---
+title: Fern 定义中的导入
+description: 使用导入功能从其他 Fern 定义文件中引用 API 类型和错误。
+sidebar-title: 导入
+---
+
+导入功能允许您从其他文件中引用类型和错误。
+
+```yaml title="person.yml"
+types:
+ Person: ...
+```
+
+```yaml title="family.yml"
+imports:
+ person: ./path/to/person.yml
+types:
+ Family:
+ properties:
+ people: list # 使用导入的类型
+```
+
+请注意,您只能导入存在于您的 Fern 定义中的文件(即,在同一个 `definition/` 文件夹中)。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/overview.mdx b/fern/translations/zh/products/api-def/ferndef/overview.mdx
new file mode 100644
index 000000000..926f06e73
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/overview.mdx
@@ -0,0 +1,103 @@
+---
+title: 什么是 Fern Definition?
+description: Fern Definition 是用于 API 规范的 YAML 格式。在一个统一的真实数据源中定义您的 REST API 端点、数据模型和错误。
+sidebar-title: 什么是 Fern Definition?
+---
+
+Fern Definition 是一组 YAML 文件,是您 API 的单一真实数据源。您可以将 Fern Definition 提交到您的代码库中,其中描述了您的 API 请求、响应、模型、路径、方法、错误和身份验证方案。
+
+
+ 想要使用 OpenAPI?没问题,我们[同样支持](/learn/api-definitions/overview/what-is-an-api-definition#openapi-swagger)
+
+
+## Fern Definition 结构
+
+要初始化一个 Fern Definition,只需运行:
+
+```sh
+npm install -g fern-api
+fern init
+```
+
+这将在您的项目中创建以下文件夹结构:
+
+
+
+
+
+
+
+
+
+
+
+
+## Definition 文件
+
+每个 Fern Definition 文件可以定义:
+
+- **[自定义类型](/learn/api-definitions/ferndef/types)**。使用**自定义类型**来构建您的数据模型。
+- **[端点](/learn/api-definitions/ferndef/endpoints/overview)**。一个**服务**是一组相关的 REST 端点。
+- **[错误](/learn/api-definitions/ferndef/errors)**。一个**错误**代表端点的失败(非 200)响应。
+- **[导入](/learn/api-definitions/ferndef/imports)**。使用**导入**在文件之间共享类型。
+
+```yml imdb.yml maxLines=0
+service:
+ auth: false
+ base-path: /movies
+ endpoints:
+ createMovie:
+ docs: Add a movie to the database
+ method: POST
+ path: /create-movie
+ request: CreateMovieRequest
+ response: MovieId
+
+ getMovie:
+ method: GET
+ path: /{movieId}
+ path-parameters:
+ movieId: MovieId
+ response: Movie
+ errors:
+ - NotFoundError
+ - UnauthorizedError
+
+types:
+ Movie:
+ properties:
+ title: string
+ rating:
+ type: double
+ docs: The rating scale from one to five stars
+ id:
+ type: MovieId
+ docs: The unique identifier for a movie
+
+ CreateMovieRequest:
+ properties:
+ title: string
+ rating: double
+
+errors:
+ NotFoundError:
+ http:
+ statusCode: 404
+ type:
+ properties:
+ id: MovieId
+
+ UnauthorizedError:
+ http:
+ statusCode: 401
+```
+
+## 为什么要使用另一种格式?
+
+Google 构建了 gRPC。Amazon 构建了 Smithy。Facebook 构建了 GraphQL。Palantir 构建了 Conjure。这些公司拒绝了 OpenAPI,而选择了更简洁的 API Definition Language。
+
+我们构建 Fern 是为了将这种设计产品化,并使所有软件公司都能使用它。
+
+
+ 尽管这是描述 API 的不同格式,**但您永远不会被锁定在 Fern 中**。将您的 [Fern Definition 转换为 OpenAPI](/learn/api-definitions/ferndef/export-openapi) 很容易。
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/packages.mdx b/fern/translations/zh/products/api-def/ferndef/packages.mdx
new file mode 100644
index 000000000..83dd37eda
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/packages.mdx
@@ -0,0 +1,146 @@
+---
+title: Fern 定义中的包
+description: Fern 定义支持在包之间重用 API 类型和错误名称,并可以配置您的 API 文档结构。
+sidebar-title: 包
+---
+
+## 什么是包?
+
+您的 API 定义中的每个文件夹都是一个包。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+生成的 SDK 将匹配您的 API 定义层次结构。
+
+
+```ts
+const client = new Client();
+
+// 调用在 projects.yml 中定义的端点
+client.projects.get();
+
+// 调用在 roles/admin.yml 中定义的端点
+client.roles.admin.get();
+```
+
+
+## 包配置
+
+每个包都可以有一个名为 `__package__.yml` 的特殊定义文件。与任何其他定义文件一样,它可以包含[导入](/learn/api-definitions/ferndef/imports)、[类型](/learn/api-definitions/ferndef/types)、[端点](/learn/api-definitions/ferndef/endpoints/overview)和[错误](/learn/api-definitions/ferndef/errors)。
+
+`__package__.yml` 中的端点将出现在包的根目录下。
+例如,以下生成的 SDK:
+
+
+```ts
+const client = new Client();
+
+client.getProjects();
+```
+
+
+将具有一个 `fern/` 文件夹:
+
+
+
+
+
+
+
+
+
+
+
+
+其中包含以下 `__package__.yml`:
+
+
+```yaml
+service:
+ base-path: ""
+ auth: false
+ endpoints:
+ getProjects:
+ method: GET
+ path: ""
+ response: list
+```
+
+
+## 命名空间
+
+每个包都有自己的命名空间。这意味着您可以在包之间重用类型名称和错误名称。
+
+这在版本化您的 API 时很有用。例如,当您想要增加 API 版本时,可以将现有的 API 复制到新包中并开始进行更改。如果新的 API 版本重用了某些类型或错误,这是可以的,因为两个 API 位于不同的包中。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 导航
+
+`__package__.yml` 还允许您配置服务的导航顺序。当您想要控制文档的显示时,这是相关的。
+
+例如,假设您有以下 `fern/` 文件夹:
+
+
+
+
+
+
+
+
+
+
+
+
+
+您的 API 将按字母顺序排序:projects、roles,然后是 users。如果您想控制导航,可以添加一个 `__package__.yml` 文件并配置顺序:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```yaml
+navigation:
+ - users.yml
+ - roles.yml
+ - projects.yml
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/types.mdx b/fern/translations/zh/products/api-def/ferndef/types.mdx
new file mode 100644
index 000000000..f0609c4f3
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/types.mdx
@@ -0,0 +1,396 @@
+---
+title: Fern 定义中的类型
+description: 类型描述了您的 API 的数据模型。Fern 具有许多内置类型,支持自定义类型,以及扩展和别名对象和联合类型。
+sidebar-title: 类型
+---
+
+类型描述了您的 API 的数据模型。
+
+## 内置类型
+
+| 类型 | 描述 |
+|------|-------------|
+| `string` | 基本字符串类型 |
+| `integer` | 整数类型 |
+| `long` | 长整数类型 |
+| `double` | 双精度浮点数 |
+| `boolean` | 布尔值 true/false |
+| `datetime` | [RFC 3339, section 5.6 datetime](https://ijmacd.github.io/rfc3339-iso8601/)。例如,`2017-07-21T17:32:28Z` |
+| `date` | RFC 3339, section 5.6 日期 (YYYY-MM-DD)。例如,`2017-07-21` |
+| `uuid` | UUID 标识符 |
+| `base64` | Base64 编码数据 |
+| `list` | 允许重复的有序集合,例如,`list` |
+| `set` | 具有唯一元素的无序集合,例如,`set` |
+| `map` | 键值映射,例如,`map` |
+| `optional` | 可选值,例如,`optional` |
+| `literal` | 字面值,例如,`literal<"Plants">` |
+| `file` | 文件上传类型,例如,[文件上传](/learn/api-definitions/ferndef/endpoints/multipart) |
+| `unknown` | 表示任意 JSON |
+
+## 自定义类型
+
+在 Fern 中创建您自己的类型很容易!
+
+### 对象
+
+最常见的自定义类型是**对象**。
+
+在 Fern 中,您使用 `"properties"` 键来创建对象:
+
+```yaml {3,8}
+types:
+ Person:
+ properties:
+ name: string
+ address: Address
+
+ Address:
+ properties:
+ line1: string
+ line2: optional
+ city: string
+ state: string
+ zip: string
+ country: literal<"USA">
+```
+
+这些表示 JSON 对象:
+
+```json
+{
+ "name": "Alice",
+ "address": {
+ "line1": "123 Happy Lane",
+ "city": "New York",
+ "state": "NY",
+ "zip": "10001",
+ "country": "USA"
+ }
+}
+```
+
+您还可以使用 **extends** 来组合对象:
+
+```yaml {6}
+types:
+ Pet:
+ properties:
+ name: string
+ Dog:
+ extends: Pet
+ properties:
+ breed: string
+```
+
+您可以扩展多个对象:
+
+```yaml {3-5}
+types:
+ GoldenRetriever:
+ extends:
+ - Dog
+ - Pet
+ properties:
+ isGoodBoy: boolean
+```
+
+### 别名
+
+别名类型是对现有类型的重命名。这通常是为了清晰起见。
+
+```yaml
+types:
+ # UserId 是 string 的别名
+ UserId: string
+
+ User:
+ properties:
+ id: UserId
+ name: string
+```
+
+### 枚举
+
+枚举表示具有一组允许值的字符串。
+
+在 Fern 中,您使用 `"enum"` 键来创建枚举:
+
+```yaml {3}
+types:
+ WeatherReport:
+ enum:
+ - SUNNY
+ - CLOUDY
+ - RAINING
+ - SNOWING
+```
+
+枚举名称仅限于 `A-Z`、`a-z`、`0-9` 和 `_`,以确保生成的代码能够在 Fern 能够输出的所有语言中编译。如果您有一个不遵循此约定的枚举,您可以使用 `"name"` 键来指定自定义名称:
+
+```yaml
+types:
+ Operator:
+ enum:
+ - name: LESS_THAN # <--- 将在 SDK 中使用的名称
+ value: '<' # <--- 将被序列化的值
+ - name: GREATER_THAN
+ value: '>'
+ - name: NOT_EQUAL
+ value: '!='
+```
+
+### 判别联合
+
+Fern 支持标记联合(也称为判别联合)。联合对于多态性很有用。这类似于 OpenAPI 中的 `oneOf` 概念。
+
+在 Fern 中,您使用 `"union"` 键来创建联合:
+
+```yaml {3-5}
+types:
+ Animal:
+ union:
+ dog: Dog
+ cat: Cat
+ Dog:
+ properties:
+ likesToWoof: boolean
+ Cat:
+ properties:
+ likesToMeow: boolean
+```
+
+在 JSON 中,联合有一个**判别属性**来区分联合的不同成员。默认情况下,Fern 使用 `"type"` 作为判别属性:
+
+```json
+{
+ "type": "dog",
+ "likesToWoof": true
+}
+```
+
+您可以使用 "discriminant" 键自定义判别属性:
+
+```yaml {3}
+ types:
+ Animal:
+ discriminant: animalType
+ union:
+ dog: Dog
+ cat: Cat
+ Dog:
+ properties:
+ likesToWoof: boolean
+ Cat:
+ properties:
+ likesToMeow: boolean
+```
+
+这对应于如下的 JSON 对象:
+
+```json
+{
+ "animalType": "dog",
+ "likesToWoof": true
+}
+```
+
+### 无判别联合
+
+无判别联合类似于判别联合,但是您不需要定义显式的判别属性。
+
+```yaml
+MyUnion:
+ discriminated: false
+ union:
+ - string
+ - integer
+```
+
+### 泛型
+
+Fern 支持浅泛型对象,以最小化代码重复。您可以定义一个泛型以供重用:
+
+```yaml
+MySpecialMapItem:
+ properties:
+ key: Key,
+ value: Value,
+ diagnostics: string
+```
+
+现在,您可以将泛型类型实例化为类型别名:
+
+```yml
+StringIntegerMapItem:
+ type: Response
+
+StringStringMapItem:
+ type: Response
+```
+
+您现在可以像使用任何其他类型一样自由使用这种类型!请注意,生成的代码不会使用泛型。上面的示例将在 TypeScript 中生成为:
+
+```typescript
+type StringIntegerMapItem = {
+ key: string,
+ value: number,
+ diagnostics: string
+}
+
+type StringStringMapItem = {
+ key: string,
+ value: string,
+ diagnostics: string
+}
+```
+
+### 文档化类型
+
+您可以为类型添加文档。这些文档被传递到编译器中,在生成的输出中非常有用(例如,SDK 中的文档字符串)。
+
+
+```yaml
+types:
+ Person:
+ docs: 一个人代表一个人类
+ properties:
+ name: string
+ age:
+ docs: 年龄(以年为单位)
+ type: integer
+```
+
+
+
+```typescript
+/**
+ * 一个人代表一个人类
+ */
+interface Person {
+ name: string;
+ // 年龄(以年为单位)
+ age: number;
+}
+```
+
+
+### 验证类型
+
+您可以向类型(别名和引用)添加验证约束以确保数据完整性。这些验证约束存在于您的 API 定义中,由服务器强制执行,但生成的客户端 SDK 不包含验证逻辑。
+
+
+```yaml {8-11, 15-17}
+types:
+ Person:
+ docs: 一个人代表一个人类
+ properties:
+ name:
+ docs: 该人的全名
+ type: string
+ validation:
+ minLength: 2
+ maxLength: 100
+ pattern: "^[A-Za-z ]+$"
+ age:
+ docs: 年龄(以年为单位)
+ type: integer
+ validation:
+ min: 0
+ max: 150
+```
+
+
+
+
+
+字符串类型支持几个验证约束。
+
+```yaml {4-6, 11-13, 16-19}
+types:
+ Word:
+ type: string
+ validation:
+ minLength: 2
+ maxLength: 26
+ User:
+ properties:
+ email:
+ type: string
+ validation:
+ format: email
+ maxLength: 254
+ username:
+ type: string
+ validation:
+ minLength: 3
+ maxLength: 20
+ pattern: "^[a-zA-Z0-9_]+$"
+```
+
+
+ 所需的最小字符数
+
+
+
+ 允许的最大字符数
+
+
+
+ 字符串必须匹配的正则表达式模式
+
+
+
+ 字符串格式规范(例如,"email"、"uri"、"date-time")
+
+
+
+
+
+
+数字类型(包括 `integer`、`long` 和 `double`)支持几个验证约束。
+
+```yaml {4-6, 12-15, 18-20}
+types:
+ Age:
+ type: integer
+ validation:
+ min: 0
+ max: 150
+ Product:
+ properties:
+ name: string
+ price:
+ type: double
+ validation:
+ min: 0
+ exclusiveMin: true
+ multipleOf: 0.01
+ quantity:
+ type: integer
+ validation:
+ min: 1
+ max: 1000
+```
+
+
+ 最小值(默认包含)
+
+
+
+ 最大值(默认包含)
+
+
+
+ 为 true 时,最小值为独占(值必须大于 min)
+
+
+
+ 为 true 时,最大值为独占(值必须小于 max)
+
+
+
+ 值必须是此数字的倍数
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/webhooks.mdx b/fern/translations/zh/products/api-def/ferndef/webhooks.mdx
new file mode 100644
index 000000000..1e3ec2ca4
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/webhooks.mdx
@@ -0,0 +1,142 @@
+---
+title: Fern Definition 中的 Webhooks
+description: 学习如何在 Fern Definition 中定义 webhooks
+sidebar-title: Fern Definition 中的 Webhooks
+max-toc-depth: 3
+---
+
+在 Fern 中,您可以在 API 定义中指定 webhooks。这些 webhooks 将包含在生成的 SDK 和 API 文档中。
+
+## Webhook 定义
+
+每个 webhook 定义:
+
+1. **方法**:webhook 将使用的 HTTP 方法(`GET` 或 `POST`)
+2. **标头**:webhook 将发送的标头
+3. **负载**:webhook 负载的模式
+
+
+ ```yaml {2-10}
+ webhooks:
+ paymentNotification:
+ display-name: Payment Notification
+ docs: Receive a notification when a payment changes status
+ method: POST
+ headers:
+ X-Signature-Primary:
+ type: string
+ docs: An HMAC signature of the payload
+ payload: PaymentNotificationPayload
+
+ types:
+ PaymentNotificationPayload:
+ discriminant: notificationType
+ union:
+ queued: QueuedPaymentNotification
+ processing: ProcessingPaymentNotification
+ completed: CompletedPaymentNotification
+ ```
+
+
+### 内联负载
+
+您可以通过以下方式内联负载的模式:
+
+
+ ```yaml
+ webhooks:
+ paymentNotification:
+ display-name: Payment Notification
+ docs: Receive a notification when a payment changes status
+ method: POST
+ headers:
+ X-Signature-Primary:
+ type: string
+ docs: An HMAC signature of the payload
+ payload:
+ name: PaymentNotificationPayload
+ properties:
+ id:
+ type: string
+ docs: The notification id
+ amount: double
+ currency: Currency
+ ```
+
+
+## 生成 webhook 参考
+
+Fern Docs 可以从您的定义自动生成 webhook 参考文档。在您的 `docs.yml` 文件中设置此配置。
+
+您的 webhook 参考可以是单个文档页面:
+
+```yml docs.yml
+navigation:
+ - api: Webhook Reference # Display name for this page
+ api-name: webhooks-v1 # Directory containing webhook definition
+```
+
+或者您可以为每个 webhook 事件配置单独的文档页面:
+
+```yaml title="docs.yml"
+navigation:
+ - subpackage_api.newPlantWebhook # Format: subpackage_{name-of-api}.{webhook-event-name}
+```
+
+有关如何在 `docs.yml` 中配置 webhook 参考的更多信息,请参阅[生成您的 webhook 参考](/docs/api-references/generate-webhook-ref)。
+
+## SDK 签名验证
+
+您可以使用 `webhook-signature` 块直接在 Fern Definition 中配置 webhook 签名验证。配置后,Fern 生成 SDK 工具,允许用户验证 webhook 签名并确保事件来源于您的 API。
+
+配置可以在**文档级别**(适用于所有 webhooks)或**每个 webhook**(覆盖文档级别的默认值)设置。两个级别都接受相同的配置选项。
+
+Fern 支持两种验证方法:**HMAC**(使用共享密钥的对称密钥验证)和**非对称**(使用 RSA、ECDSA 或 Ed25519 密钥的公钥验证)。
+
+
+
+```yaml title="api.yml"
+webhook-signature:
+ type: hmac
+ header: x-webhook-signature
+ algorithm: sha256
+ encoding: hex
+
+webhooks:
+ userCreated:
+ method: POST
+ payload: UserCreatedPayload
+ # Inherits document-level signature config
+
+ orderCompleted:
+ method: POST
+ payload: OrderCompletedPayload
+ # Inherits document-level signature config
+```
+
+
+```yaml title="api.yml"
+webhook-signature:
+ type: hmac
+ header: x-webhook-signature
+ algorithm: sha256
+ encoding: hex
+
+webhooks:
+ paymentNotification:
+ method: POST
+ payload: PaymentNotificationPayload
+ signature:
+ # Override: use asymmetric instead of HMAC
+ type: asymmetric
+ header: x-payment-signature
+ asymmetric-algorithm: rsa-sha256
+ encoding: base64
+ jwks-url: https://api.example.com/.well-known/jwks.json
+```
+
+
+
+### 配置选项
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/ferndef/websockets.mdx b/fern/translations/zh/products/api-def/ferndef/websockets.mdx
new file mode 100644
index 000000000..18257c6e1
--- /dev/null
+++ b/fern/translations/zh/products/api-def/ferndef/websockets.mdx
@@ -0,0 +1,100 @@
+---
+title: Fern Definition 中的 WebSockets
+description: 了解如何在 Fern Definition 中定义 WebSockets
+sidebar-title: WebSockets
+---
+
+WebSockets 使用户能够与服务器创建连接,通过该连接可以发送双向通信。
+
+在 Fern 中,您可以在 API 定义中指定 WebSockets。WebSockets 将包含在生成的 SDK 和 API 文档中。
+
+## WebSocket 定义
+每个 WebSocket 都在自己的文件中定义,通过 `channel` 对象进行描述。将您的 WebSocket 定义文件放在 `fern` 文件夹中,与其他 API 定义文件一起。
+
+
+
+
+
+
+
+
+
+
+
+
+### channel 对象
+
+`channel` 由以下字段定义:
+
+- `auth`:WebSocket 的身份验证方案
+- `path`:WebSocket 的路径
+- `headers` _(可选)_:WebSocket 将发送的任何标头
+- `path-parameters` _(可选)_:WebSocket 路径中的任何路径参数
+- `query-parameters` _(可选)_:WebSocket 初始请求中使用的任何查询参数
+- `messages` _(可选)_:WebSocket 连接后可以发送和接收的消息模式
+ - `origin`:发送消息的实体(例如 `client` 或 `server`)
+ - `body`:消息的模式
+- `examples`:示例 WebSocket 连接 _(可选)_
+
+### WebSocket 示例
+
+
+ ```yaml
+ channel:
+ path: /chat
+ auth: false
+ query-parameters:
+ model_id:
+ type: optional
+ docs: The unique identifier of the model.
+ model_version:
+ type: optional
+ docs: The version number of the model.
+ messages:
+ publish:
+ origin: client
+ body: PublishEvent
+ subscribe:
+ origin: server
+ body: SubscribeEvent
+ examples:
+ - query-parameters:
+ model_id: "123"
+ messages:
+ - type: publish
+ body:
+ text: "Hello, world."
+ - type: subscribe
+ body:
+ id: "23823049"
+ message: "Hello there, how are you?"
+ types:
+ PublishEvent:
+ docs: The input from the user to send through the WebSocket.
+ properties:
+ text:
+ type: string
+ docs: The user text to send into the conversation.
+ SubscribeEvent:
+ docs: The response from the server sent through the WebSocket.
+ properties:
+ id:
+ type: string
+ docs: The id of the message.
+ message:
+ type: string
+ docs: The message sent through the socket.
+ ```
+
+
+## WebSocket API 参考
+
+### WebSocket 参考
+
+Fern 为 WebSockets 渲染[独特的参考页面](/learn/docs/api-references/generate-websocket-ref)。**握手**部分概述了与服务器连接的协议,而**发送**和**接收**部分概述了客户端和服务器之间可以发送的消息模式。
+
+用户可以直接在 API 参考中连接和使用 WebSockets(查看 Hume 的 WebSockets [这里](https://dev.hume.ai/reference/text-to-speech-tts/stream-input))。
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/auth.mdx b/fern/translations/zh/products/api-def/grpc/auth.mdx
new file mode 100644
index 000000000..daee6709e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/auth.mdx
@@ -0,0 +1,371 @@
+---
+title: 身份验证
+subtitle: 为 gRPC 服务配置身份验证,包括 TLS、JWT 和自定义认证
+sidebar-title: 身份验证
+---
+
+gRPC 支持各种身份验证机制来保护您的服务。身份验证可以在传输层(TLS)和应用层(凭证、令牌等)进行配置。
+
+## 传输安全(TLS)
+
+gRPC 强烈建议在生产环境服务中使用 TLS 以确保加密通信:
+
+```protobuf auth_service.proto
+syntax = "proto3";
+
+package auth.v1;
+
+// Authentication service
+service AuthService {
+ // Authenticate user and return JWT token
+ rpc Login(LoginRequest) returns (LoginResponse);
+
+ // Validate and refresh JWT token
+ rpc RefreshToken(RefreshTokenRequest) returns (RefreshTokenResponse);
+
+ // Logout and invalidate token
+ rpc Logout(LogoutRequest) returns (google.protobuf.Empty);
+}
+
+message LoginRequest {
+ string email = 1;
+ string password = 2;
+}
+
+message LoginResponse {
+ string access_token = 1;
+ string refresh_token = 2;
+ int64 expires_in = 3;
+ User user = 4;
+}
+```
+
+在您的服务器中配置 TLS:
+
+```python title="server.py"
+import grpc
+from grpc import ssl_channel_credentials
+import auth_service_pb2_grpc
+
+def create_secure_server():
+ # Load TLS credentials
+ server_credentials = grpc.ssl_server_credentials([
+ (private_key, certificate_chain)
+ ])
+
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ auth_service_pb2_grpc.add_AuthServiceServicer_to_server(
+ AuthServiceServicer(), server
+ )
+
+ # Listen on secure port
+ server.add_secure_port('[::]:443', server_credentials)
+ return server
+```
+
+## JWT 身份验证
+
+使用 JWT 令牌进行无状态身份验证:
+
+```protobuf auth.proto
+syntax = "proto3";
+
+package auth.v1;
+
+// JWT claims for user authentication
+message JWTClaims {
+ string user_id = 1;
+ string email = 2;
+ repeated string roles = 3;
+ google.protobuf.Timestamp issued_at = 4;
+ google.protobuf.Timestamp expires_at = 5;
+}
+```
+
+在您的服务中实现 JWT 身份验证:
+
+```python title="auth_service.py"
+import grpc
+import jwt
+from grpc import ServicerContext
+
+class AuthServiceServicer(auth_service_pb2_grpc.AuthServiceServicer):
+
+ def Login(self, request, context):
+ # Validate credentials
+ user = self.validate_credentials(request.email, request.password)
+ if not user:
+ context.set_code(grpc.StatusCode.UNAUTHENTICATED)
+ context.set_details('Invalid credentials')
+ return auth_service_pb2.LoginResponse()
+
+ # Generate JWT token
+ payload = {
+ 'user_id': user.id,
+ 'email': user.email,
+ 'roles': user.roles,
+ 'exp': datetime.utcnow() + timedelta(hours=1)
+ }
+
+ access_token = jwt.encode(payload, JWT_SECRET, algorithm='HS256')
+
+ return auth_service_pb2.LoginResponse(
+ access_token=access_token,
+ refresh_token=self.generate_refresh_token(user.id),
+ expires_in=3600,
+ user=user
+ )
+```
+
+## 用于身份验证的拦截器
+
+使用 gRPC 拦截器来处理所有方法的身份验证:
+
+```python title="auth_interceptor.py"
+import grpc
+import jwt
+from grpc import ServicerContext
+
+class AuthInterceptor(grpc.ServerInterceptor):
+
+ def __init__(self, jwt_secret, exempt_methods=None):
+ self.jwt_secret = jwt_secret
+ self.exempt_methods = exempt_methods or []
+
+ def intercept_service(self, continuation, handler_call_details):
+ method_name = handler_call_details.method
+
+ # Skip authentication for exempt methods
+ if method_name in self.exempt_methods:
+ return continuation(handler_call_details)
+
+ # Extract metadata
+ metadata = dict(handler_call_details.invocation_metadata)
+ authorization = metadata.get('authorization', '')
+
+ if not authorization.startswith('Bearer '):
+ return self._unauthenticated_response()
+
+ token = authorization[7:] # Remove 'Bearer ' prefix
+
+ try:
+ # Validate JWT token
+ payload = jwt.decode(token, self.jwt_secret, algorithms=['HS256'])
+
+ # Add user info to context
+ handler_call_details = handler_call_details._replace(
+ invocation_metadata=handler_call_details.invocation_metadata + (
+ ('user_id', payload['user_id']),
+ ('user_email', payload['email']),
+ )
+ )
+
+ return continuation(handler_call_details)
+
+ except jwt.ExpiredSignatureError:
+ return self._expired_token_response()
+ except jwt.InvalidTokenError:
+ return self._invalid_token_response()
+
+ def _unauthenticated_response(self):
+ def abort(ignored_request, context):
+ context.set_code(grpc.StatusCode.UNAUTHENTICATED)
+ context.set_details('Missing or invalid authorization header')
+ return grpc.unary_unary_rpc_method_handler(abort)
+```
+
+## API 密钥身份验证
+
+实现基于 API 密钥的身份验证:
+
+```protobuf api_key.proto
+syntax = "proto3";
+
+package auth.v1;
+
+message ApiKeyRequest {
+ string api_key = 1;
+ string service_name = 2;
+}
+
+message ApiKeyResponse {
+ bool valid = 1;
+ string client_id = 2;
+ repeated string permissions = 3;
+ google.protobuf.Timestamp expires_at = 4;
+}
+```
+
+服务器实现:
+
+```python title="api_key_auth.py"
+class ApiKeyAuthInterceptor(grpc.ServerInterceptor):
+
+ def __init__(self, api_key_store):
+ self.api_key_store = api_key_store
+
+ def intercept_service(self, continuation, handler_call_details):
+ metadata = dict(handler_call_details.invocation_metadata)
+ api_key = metadata.get('x-api-key', '')
+
+ if not api_key:
+ return self._unauthorized_response('API key required')
+
+ # Validate API key
+ key_info = self.api_key_store.get(api_key)
+ if not key_info or key_info.is_expired():
+ return self._unauthorized_response('Invalid or expired API key')
+
+ # Add client info to context
+ handler_call_details = handler_call_details._replace(
+ invocation_metadata=handler_call_details.invocation_metadata + (
+ ('client_id', key_info.client_id),
+ ('permissions', ','.join(key_info.permissions)),
+ )
+ )
+
+ return continuation(handler_call_details)
+```
+
+## OAuth2 集成
+
+与 OAuth2 提供商集成:
+
+```python title="oauth2_auth.py"
+import requests
+from google.oauth2 import id_token
+from google.auth.transport import requests as google_requests
+
+class OAuth2Interceptor(grpc.ServerInterceptor):
+
+ def __init__(self, google_client_id):
+ self.google_client_id = google_client_id
+
+ def intercept_service(self, continuation, handler_call_details):
+ metadata = dict(handler_call_details.invocation_metadata)
+ auth_header = metadata.get('authorization', '')
+
+ if not auth_header.startswith('Bearer '):
+ return self._unauthorized_response()
+
+ token = auth_header[7:]
+
+ try:
+ # Verify Google ID token
+ idinfo = id_token.verify_oauth2_token(
+ token, google_requests.Request(), self.google_client_id
+ )
+
+ # Add user info to context
+ handler_call_details = handler_call_details._replace(
+ invocation_metadata=handler_call_details.invocation_metadata + (
+ ('user_id', idinfo['sub']),
+ ('user_email', idinfo['email']),
+ ('user_name', idinfo.get('name', '')),
+ )
+ )
+
+ return continuation(handler_call_details)
+
+ except ValueError:
+ return self._invalid_token_response()
+```
+
+## 客户端身份验证
+
+在客户端配置身份验证:
+
+```python title="client.py"
+import grpc
+
+# TLS with JWT
+def create_authenticated_channel(server_address, jwt_token):
+ credentials = grpc.ssl_channel_credentials()
+ channel = grpc.secure_channel(server_address, credentials)
+
+ # Add JWT token to all requests
+ def jwt_interceptor(continuation, client_call_details):
+ metadata = list(client_call_details.metadata or [])
+ metadata.append(('authorization', f'Bearer {jwt_token}'))
+
+ client_call_details = client_call_details._replace(metadata=metadata)
+ return continuation(client_call_details)
+
+ intercepted_channel = grpc.intercept_channel(channel, jwt_interceptor)
+ return intercepted_channel
+
+# API Key authentication
+def create_api_key_channel(server_address, api_key):
+ credentials = grpc.ssl_channel_credentials()
+ channel = grpc.secure_channel(server_address, credentials)
+
+ def api_key_interceptor(continuation, client_call_details):
+ metadata = list(client_call_details.metadata or [])
+ metadata.append(('x-api-key', api_key))
+
+ client_call_details = client_call_details._replace(metadata=metadata)
+ return continuation(client_call_details)
+
+ intercepted_channel = grpc.intercept_channel(channel, api_key_interceptor)
+ return intercepted_channel
+```
+
+## 基于角色的访问控制
+
+实现用于细粒度权限控制的 RBAC:
+
+```protobuf rbac.proto
+syntax = "proto3";
+
+package auth.v1;
+
+message Permission {
+ string resource = 1;
+ string action = 2;
+}
+
+message Role {
+ string name = 1;
+ repeated Permission permissions = 2;
+}
+
+message UserRoles {
+ string user_id = 1;
+ repeated string role_names = 2;
+}
+```
+
+RBAC 拦截器实现:
+
+```python title="rbac_interceptor.py"
+class RBACInterceptor(grpc.ServerInterceptor):
+
+ def __init__(self, permission_store):
+ self.permission_store = permission_store
+
+ def intercept_service(self, continuation, handler_call_details):
+ # Get user info from context (added by auth interceptor)
+ metadata = dict(handler_call_details.invocation_metadata)
+ user_id = metadata.get('user_id')
+
+ if not user_id:
+ return self._unauthorized_response()
+
+ # Check permissions for the method
+ method_name = handler_call_details.method
+ required_permission = self._get_required_permission(method_name)
+
+ if required_permission and not self._has_permission(user_id, required_permission):
+ return self._forbidden_response()
+
+ return continuation(handler_call_details)
+
+ def _has_permission(self, user_id, permission):
+ user_roles = self.permission_store.get_user_roles(user_id)
+ for role in user_roles:
+ if permission in role.permissions:
+ return True
+ return False
+```
+
+gRPC 的灵活身份验证系统允许您实现安全、可扩展的身份验证模式,这些模式可以在不同的环境和用例中工作。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/automation.mdx b/fern/translations/zh/products/api-def/grpc/automation.mdx
new file mode 100644
index 000000000..5c4f38a51
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/automation.mdx
@@ -0,0 +1,512 @@
+---
+title: 同步你的 gRPC 规范
+description: 使用 Fern 自动化 gRPC 规范同步。设置 GitHub Actions、CI/CD 流水线和定期更新 Protocol Buffer 文件。
+sidebar-title: 同步 gRPC 规范
+---
+
+保持你的 gRPC 规范与代码库同步对于维护准确的 SDK 和文档至关重要。Fern 提供了多种自动化选项来简化这个过程。
+
+## GitHub Actions
+
+使用 Fern 的 GitHub Action 在你的 Protocol Buffer 文件发生变化时自动更新 SDK 和文档。
+
+
+
+```yaml title=".github/workflows/fern.yml"
+name: Fern
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'proto/**/*.proto'
+ - 'fern/**/*.yml'
+ pull_request:
+ branches:
+ - main
+ paths:
+ - 'proto/**/*.proto'
+ - 'fern/**/*.yml'
+
+jobs:
+ fern-check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Check gRPC spec
+ uses: fern-api/action@v0
+ with:
+ command: check
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+
+ fern-generate:
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ # Required if using local-generation: true
+ - name: Setup buf
+ uses: bufbuild/buf-setup-action@v1
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Generate SDKs and docs
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## Protocol buffer 验证
+
+在生成 SDK 之前验证、检查并检测 Protocol Buffer 文件中的破坏性变更。
+
+```yaml title=".github/workflows/proto-validation.yml"
+name: Protocol Buffer Validation
+
+on:
+ push:
+ paths:
+ - 'proto/**/*.proto'
+ - 'buf.yaml'
+ pull_request:
+ paths:
+ - 'proto/**/*.proto'
+
+jobs:
+ validate-proto:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Setup Protocol Buffer Compiler
+ uses: arduino/setup-protoc@v2
+ with:
+ version: '23.4'
+
+ - name: Setup buf
+ uses: bufbuild/buf-setup-action@v1
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Lint Protocol Buffers
+ run: buf lint
+
+ - name: Validate Protocol Buffer files
+ run: |
+ find proto -name "*.proto" -exec protoc --proto_path=proto --descriptor_set_out=/dev/null {} \;
+
+ - name: Check for breaking changes
+ run: buf breaking --against '.git#branch=main'
+
+ - name: Generate and validate with Fern
+ uses: fern-api/action@v0
+ with:
+ command: check
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+
+
+如果你正在使用 [Buf Schema Registry](https://buf.build/product/bsr),可以添加一个步骤来发布你的模式:
+
+```yaml title=".github/workflows/buf-sync.yml"
+name: Buf Sync
+
+on:
+ push:
+ paths:
+ - 'proto/**/*.proto'
+ - 'buf.yaml'
+
+jobs:
+ buf-sync:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Setup buf
+ uses: bufbuild/buf-setup-action@v1
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Lint Protocol Buffers
+ run: buf lint
+
+ - name: Check for breaking changes
+ run: buf breaking --against '.git#branch=main'
+
+ - name: Generate and push to Buf Registry
+ run: |
+ buf generate
+ buf push
+ env:
+ BUF_TOKEN: ${{ secrets.BUF_TOKEN }}
+
+ - name: Generate SDKs with Fern
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+
+
+可选择创建一个 `buf.yaml` 文件来自定义 buf 的检查规则、破坏性变更检测和依赖项:
+
+```yaml title="buf.yaml"
+version: v1
+deps:
+ - buf.build/googleapis/googleapis
+ - buf.build/envoyproxy/protoc-gen-validate
+lint:
+ use:
+ - DEFAULT
+ except:
+ - UNARY_RPC
+breaking:
+ use:
+ - FILE
+```
+
+
+
+## 从源码自动同步
+
+配置 Fern 自动从各种源拉取 Protocol Buffer 文件:
+
+### 从 git 仓库
+```yaml title="generators.yml" {3-7}
+api:
+ specs:
+ - spec:
+ git:
+ repository: https://github.com/your-org/proto-definitions
+ path: services/user_service.proto
+ branch: main
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+### 从本地目录
+```yaml title="generators.yml" {3-4}
+api:
+ specs:
+ - spec: proto/user_service.proto
+ auto-sync: true
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+## CI/CD 集成
+
+将 Fern 集成到现有的 CI/CD 流水线中,自动生成 SDK 和文档。
+
+### CircleCI
+
+
+
+```yaml title=".circleci/config.yml" {15-26}
+version: 2.1
+
+orbs:
+ fern: fernapi/fern@1.0
+
+workflows:
+ version: 2
+ build-and-generate:
+ jobs:
+ - build
+ - test:
+ requires:
+ - build
+ - validate-proto:
+ requires:
+ - build
+ - fern/generate:
+ requires:
+ - test
+ - validate-proto
+ filters:
+ branches:
+ only: main
+ context:
+ - fern-context
+
+jobs:
+ validate-proto:
+ docker:
+ - image: namely/protoc-all:1.51_1
+ steps:
+ - checkout
+ # Required if using local-generation: true
+ - run:
+ name: Install buf
+ command: |
+ curl -sSL "https://github.com/bufbuild/buf/releases/latest/download/buf-Linux-x86_64" -o /usr/local/bin/buf
+ chmod +x /usr/local/bin/buf
+ - run:
+ name: Validate Protocol Buffers
+ command: |
+ find proto -name "*.proto" -exec protoc --proto_path=proto --descriptor_set_out=/dev/null {} \;
+```
+
+### GitLab CI
+
+
+
+```yaml title=".gitlab-ci.yml" {13-25}
+stages:
+ - build
+ - test
+ - validate
+ - generate
+
+variables:
+ FERN_TOKEN: $FERN_TOKEN
+
+build:
+ stage: build
+ script:
+ - echo "Building gRPC service..."
+
+validate-proto:
+ stage: validate
+ image: namely/protoc-all:1.51_1
+ script:
+ - find proto -name "*.proto" -exec protoc --proto_path=proto --descriptor_set_out=/dev/null {} \;
+ only:
+ changes:
+ - proto/**/*.proto
+
+generate-sdks:
+ stage: generate
+ image: fernapi/fern:latest
+ # Required if using local-generation: true
+ before_script:
+ - curl -sSL "https://github.com/bufbuild/buf/releases/latest/download/buf-Linux-x86_64" -o /usr/local/bin/buf
+ - chmod +x /usr/local/bin/buf
+ script:
+ - fern generate
+ only:
+ - main
+```
+
+## 定期更新
+
+设置定期更新以确保你的 SDK 保持最新:
+
+```yaml title=".github/workflows/scheduled-update.yml"
+name: Scheduled gRPC Update
+
+on:
+ schedule:
+ - cron: '0 2 * * 1' # Every Monday at 2 AM UTC
+ workflow_dispatch:
+
+jobs:
+ update-proto:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Sync Protocol Buffer files
+ run: |
+ # Sync from upstream proto repository
+ git subtree pull --prefix=proto https://github.com/your-org/proto-definitions main --squash
+
+ - name: Generate with latest spec
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+
+ - name: Create PR if changes
+ uses: peter-evans/create-pull-request@v5
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ commit-message: "chore: update Protocol Buffer definitions"
+ title: "Update Protocol Buffer definitions"
+ body: "Automated update of Protocol Buffer definitions from upstream repository"
+```
+
+## 从 gRPC 服务器生成代码
+
+对于可以生成自己的 Protocol Buffer 定义的服务器:
+
+```yaml title=".github/workflows/auto-generate.yml"
+name: Auto-generate from gRPC server
+
+on:
+ push:
+ paths:
+ - 'src/**/*.py' # Trigger on server code changes
+ - 'src/**/*.go'
+ - 'src/**/*.java'
+
+jobs:
+ generate-proto:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Setup environment
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.9'
+
+ - name: Install dependencies
+ run: |
+ pip install grpcio-tools
+
+ - name: Generate Protocol Buffer files
+ run: |
+ python -m grpc_tools.protoc \
+ --proto_path=src/protos \
+ --python_out=. \
+ --grpc_python_out=. \
+ --descriptor_set_out=proto/service.protoset \
+ src/protos/*.proto
+
+ - name: Convert to Protocol Buffer text format
+ run: |
+ protoc --decode_raw < proto/service.protoset > proto/user_service.proto
+
+ - name: Generate SDKs
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## 监控变更
+
+跟踪你的 Protocol Buffer 规范的变更:
+
+```yaml title="generators.yml" {4-9}
+api:
+ specs:
+ - spec: proto/user_service.proto
+ change-detection:
+ enabled: true
+ breaking-changes: error
+ notifications:
+ slack: ${{ secrets.SLACK_WEBHOOK }}
+ email: team@yourcompany.com
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+## 多服务同步
+
+为不同组件同步不同的 Protocol Buffer 服务:
+
+```yaml title="generators.yml" {3-7, 12-16, 21-25}
+environments:
+ user-service:
+ specs:
+ - spec: proto/user_service.proto
+ overlays:
+ - user-service-overlay.yml
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@yourcompany/user-service-sdk"
+ order-service:
+ specs:
+ - spec: proto/order_service.proto
+ overlays:
+ - order-service-overlay.yml
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@yourcompany/order-service-sdk"
+ payment-service:
+ specs:
+ - spec: proto/payment_service.proto
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@yourcompany/payment-service-sdk"
+```
+
+## gRPC 反射同步
+
+自动从启用了服务器反射的运行中的 gRPC 服务同步 Protocol Buffer 定义:
+
+```python title="scripts/sync_from_reflection.py"
+import grpc
+from grpc_reflection.v1alpha import reflection_pb2
+from grpc_reflection.v1alpha import reflection_pb2_grpc
+import subprocess
+
+def sync_from_grpc_reflection(server_address, output_dir):
+ """从 gRPC 反射同步 Protocol Buffer 定义"""
+
+ channel = grpc.insecure_channel(server_address)
+ reflection_stub = reflection_pb2_grpc.ServerReflectionStub(channel)
+
+ # 列出服务
+ request = reflection_pb2.ServerReflectionRequest(
+ list_services=""
+ )
+
+ response = reflection_stub.ServerReflectionInfo(iter([request]))
+
+ for resp in response:
+ if resp.HasField('list_services_response'):
+ for service in resp.list_services_response.service:
+ print(f"Found service: {service.name}")
+
+ # 获取服务的文件描述符
+ file_request = reflection_pb2.ServerReflectionRequest(
+ file_containing_symbol=service.name
+ )
+
+ file_response = reflection_stub.ServerReflectionInfo(iter([file_request]))
+
+ for file_resp in file_response:
+ if file_resp.HasField('file_descriptor_response'):
+ # 保存描述符到文件
+ descriptor_path = f"{output_dir}/{service.name}.protoset"
+ with open(descriptor_path, 'wb') as f:
+ f.write(file_resp.file_descriptor_response.file_descriptor_proto[0])
+
+ # 转换为文本格式
+ proto_path = f"{output_dir}/{service.name}.proto"
+ subprocess.run([
+ 'protoc',
+ '--decode_raw',
+ '--proto_path', output_dir,
+ descriptor_path
+ ], stdout=open(proto_path, 'w'))
+
+if __name__ == "__main__":
+ sync_from_grpc_reflection("localhost:50051", "proto/")
+```
+
+这确保了你的 gRPC 服务的任何变更都能自动反映在你的 SDK 和文档中,在整个 API 生态系统中保持一致性。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/overview.mdx b/fern/translations/zh/products/api-def/grpc/overview.mdx
new file mode 100644
index 000000000..03286954b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/overview.mdx
@@ -0,0 +1,240 @@
+---
+title: 什么是 gRPC?
+description: gRPC 是一个使用 Protocol Buffers 的高性能 RPC 框架
+sidebar-title: 什么是 gRPC?
+---
+
+
+
+
+
+ Fern 目前仅支持为 .NET/C# 生成 gRPC SDK。Protobuf 规范可用于所有语言的文档生成。[提交问题](https://github.com/fern-api/fern/issues)请求支持其他语言。
+
+
+gRPC 是一个现代的、开源的、高性能的远程过程调用(RPC)框架,可以在任何环境中运行。它使用 Protocol Buffers (protobuf) 作为接口定义语言,并支持多种编程语言。
+Fern 兼容 gRPC 服务,可以从您的 `.proto` 文件生成 SDK 和文档。
+
+要查看实际示例,请参见 [gRPC 演示文档](https://grpc-demo.docs.buildwithfern.com/) 及其 [GitHub 仓库](https://github.com/fern-demo/grpc-demo)。
+
+以下是一个 gRPC 服务定义的示例:
+
+```protobuf user_service.proto
+syntax = "proto3";
+
+package userservice.v1;
+
+// User service for managing user accounts
+service UserService {
+ // Create a new user account
+ rpc CreateUser(CreateUserRequest) returns (User);
+
+ // Get user by ID
+ rpc GetUser(GetUserRequest) returns (User);
+
+ // List users with pagination
+ rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
+
+ // Update user information
+ rpc UpdateUser(UpdateUserRequest) returns (User);
+
+ // Delete a user account
+ rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);
+
+ // Stream user events (server streaming)
+ rpc StreamUserEvents(StreamUserEventsRequest) returns (stream UserEvent);
+
+ // Upload user data (client streaming)
+ rpc UploadUserData(stream UploadUserDataRequest) returns (UploadUserDataResponse);
+
+ // Real-time chat (bidirectional streaming)
+ rpc Chat(stream ChatMessage) returns (stream ChatMessage);
+}
+
+// Messages for user operations
+message User {
+ string id = 1;
+ string email = 2;
+ string name = 3;
+ int32 age = 4;
+ google.protobuf.Timestamp created_at = 5;
+ UserStatus status = 6;
+}
+
+message CreateUserRequest {
+ string email = 1;
+ string name = 2;
+ int32 age = 3;
+}
+
+message GetUserRequest {
+ string id = 1;
+}
+
+message ListUsersRequest {
+ int32 page_size = 1;
+ string page_token = 2;
+ string filter = 3;
+}
+
+message ListUsersResponse {
+ repeated User users = 1;
+ string next_page_token = 2;
+ int32 total_count = 3;
+}
+
+message UpdateUserRequest {
+ string id = 1;
+ User user = 2;
+ google.protobuf.FieldMask update_mask = 3;
+}
+
+message DeleteUserRequest {
+ string id = 1;
+}
+
+message StreamUserEventsRequest {
+ string user_id = 1;
+ repeated UserEventType event_types = 2;
+}
+
+message UserEvent {
+ string id = 1;
+ string user_id = 2;
+ UserEventType type = 3;
+ google.protobuf.Timestamp timestamp = 4;
+ google.protobuf.Any data = 5;
+}
+
+message UploadUserDataRequest {
+ oneof data {
+ UserDataChunk chunk = 1;
+ UserDataMetadata metadata = 2;
+ }
+}
+
+message UserDataChunk {
+ bytes data = 1;
+ int64 offset = 2;
+}
+
+message UserDataMetadata {
+ string filename = 1;
+ int64 total_size = 2;
+ string content_type = 3;
+}
+
+message UploadUserDataResponse {
+ string file_id = 1;
+ int64 bytes_uploaded = 2;
+}
+
+message ChatMessage {
+ string id = 1;
+ string user_id = 2;
+ string room_id = 3;
+ string content = 4;
+ google.protobuf.Timestamp timestamp = 5;
+ ChatMessageType type = 6;
+}
+
+// Enums
+enum UserStatus {
+ USER_STATUS_UNSPECIFIED = 0;
+ USER_STATUS_ACTIVE = 1;
+ USER_STATUS_INACTIVE = 2;
+ USER_STATUS_SUSPENDED = 3;
+}
+
+enum UserEventType {
+ USER_EVENT_TYPE_UNSPECIFIED = 0;
+ USER_EVENT_TYPE_CREATED = 1;
+ USER_EVENT_TYPE_UPDATED = 2;
+ USER_EVENT_TYPE_DELETED = 3;
+ USER_EVENT_TYPE_LOGIN = 4;
+ USER_EVENT_TYPE_LOGOUT = 5;
+}
+
+enum ChatMessageType {
+ CHAT_MESSAGE_TYPE_UNSPECIFIED = 0;
+ CHAT_MESSAGE_TYPE_TEXT = 1;
+ CHAT_MESSAGE_TYPE_IMAGE = 2;
+ CHAT_MESSAGE_TYPE_FILE = 3;
+ CHAT_MESSAGE_TYPE_SYSTEM = 4;
+}
+```
+
+## 设置您的 fern 文件夹
+
+ 需要帮助开始使用 gRPC 和 Fern?在[这里](https://fern-community.slack.com/join/shared_invite/zt-2dpftfmif-MuAegl8AfP_PK8s2tx350Q%EF%BB%BF#/shared-invite/email)获得实时支持
+
+
+
+
+在您的项目根目录中创建一个 `fern/` 文件夹。
+
+```
+fern/
+```
+
+
+将您的 gRPC 文件添加到 fern 目录中。您可以将其放在名为 `proto` 的子文件夹中,或者直接放在 fern 目录中。
+
+```
+fern/
+ └─ proto/
+ ├─ user_service.proto
+ └─ common.proto
+```
+
+
+在您的 fern 目录中添加一个 `fern.config.json` 文件,其中列出您的组织和当前版本的 Fern CLI:
+
+```json title="fern.config.json"
+{
+ "organization": "your-organization",
+ "version": ""
+}
+```
+
+```
+fern/
+ ├─ fern.config.json
+ └─ proto/
+ ├─ user_service.proto
+ └─ common.proto
+```
+
+
+在您的 fern 目录中创建一个 `generators.yml` 文件,并添加对您的 gRPC proto 文件的引用。请参见 [gRPC generators.yml 参考](/api-definitions/grpc/generators-yml-reference)以获取完整的配置选项。
+
+```yaml title="generators.yml"
+# Your API definition
+api:
+ specs:
+ - proto:
+ # Path up to where package starts (e.g., for package userservice.v1)
+ root: ../user-service/proto
+ # Omit to generate docs for entire root folder
+ target: ../user-service/proto/data/v1/user_service.proto
+groups:
+ external:
+ generators:
+ # Your C# generator configuration here, if relevant
+```
+
+
+如果您想要[本地编译 `.proto` 文件 (`local-generation: true`)](/learn/api-definitions/grpc/generators-yml-reference#local-generation),您必须在您的机器上或[在您的 CI/CD 环境中](/learn/api-definitions/grpc/sync-your-g-rpc-specification)安装 [buf](https://buf.build/docs/installation)。
+
+
+您的最终目录结构:
+
+```
+fern/
+ ├─ fern.config.json
+ ├─ generators.yml
+ └─ proto/
+ ├─ user_service.proto
+ └─ common.proto
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/reference/generators-reference.mdx b/fern/translations/zh/products/api-def/grpc/reference/generators-reference.mdx
new file mode 100644
index 000000000..e8af65b59
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/reference/generators-reference.mdx
@@ -0,0 +1,11 @@
+---
+title: gRPC generators.yml 参考
+description: Fern 完整的 gRPC generators.yml 参考指南。了解如何配置 root、target、overrides 和 local-generation 设置。
+sidebar-title: gRPC generators.yml 参考
+---
+
+`generators.yml` 文件有两个作用:它声明你的 gRPC 规范位置(在 `api.specs` 部分),并配置 SDK 生成(在可选的 `groups` 部分)。
+
+在此声明的 API 可以通过 `docs.yml` 在你的文档中渲染。请参阅 [生成你的 API 参考](/learn/docs/api-references/overview)。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/servers.mdx b/fern/translations/zh/products/api-def/grpc/servers.mdx
new file mode 100644
index 000000000..32bca6d3b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/servers.mdx
@@ -0,0 +1,428 @@
+---
+title: 服务器
+description: 配置具有 TLS、负载均衡和部署选项的 gRPC 服务器
+subtitle: 为生产部署设置和配置 gRPC 服务器
+sidebar-title: 服务器
+---
+
+gRPC 服务器可以配置各种安全性、性能和可扩展性选项。正确的服务器配置对于生产部署至关重要。
+
+## 基本服务器设置
+
+设置具有多个服务的基本 gRPC 服务器:
+
+```python title="server.py"
+import grpc
+from concurrent import futures
+import user_service_pb2_grpc
+import auth_service_pb2_grpc
+from user_service import UserServiceServicer
+from auth_service import AuthServiceServicer
+
+def create_server():
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+
+ # Add services
+ user_service_pb2_grpc.add_UserServiceServicer_to_server(
+ UserServiceServicer(), server
+ )
+ auth_service_pb2_grpc.add_AuthServiceServicer_to_server(
+ AuthServiceServicer(), server
+ )
+
+ # Listen on insecure port for development
+ server.add_insecure_port('[::]:50051')
+
+ return server
+
+if __name__ == '__main__':
+ server = create_server()
+ server.start()
+ print("gRPC server started on port 50051")
+ server.wait_for_termination()
+```
+
+## TLS 配置
+
+为安全的生产部署配置 TLS:
+
+```python title="secure_server.py"
+import grpc
+from grpc import ssl_server_credentials
+
+def create_secure_server():
+ # Load TLS certificates
+ with open('server-key.pem', 'rb') as f:
+ private_key = f.read()
+ with open('server-cert.pem', 'rb') as f:
+ certificate_chain = f.read()
+ with open('ca-cert.pem', 'rb') as f:
+ root_certificates = f.read()
+
+ # Create server credentials
+ server_credentials = ssl_server_credentials(
+ [(private_key, certificate_chain)],
+ root_certificates=root_certificates,
+ require_client_auth=True # Mutual TLS
+ )
+
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=50))
+
+ # Add services
+ user_service_pb2_grpc.add_UserServiceServicer_to_server(
+ UserServiceServicer(), server
+ )
+
+ # Listen on secure port
+ server.add_secure_port('[::]:443', server_credentials)
+
+ return server
+```
+
+## 服务器选项
+
+配置各种服务器选项以优化性能和行为:
+
+```python title="configured_server.py"
+import grpc
+from grpc import compression
+
+def create_configured_server():
+ # Define server options
+ options = [
+ ('grpc.keepalive_time_ms', 30000),
+ ('grpc.keepalive_timeout_ms', 5000),
+ ('grpc.keepalive_permit_without_calls', True),
+ ('grpc.http2.max_pings_without_data', 0),
+ ('grpc.http2.min_time_between_pings_ms', 10000),
+ ('grpc.http2.min_ping_interval_without_data_ms', 300000),
+ ('grpc.max_connection_idle_ms', 60000),
+ ('grpc.max_connection_age_ms', 300000),
+ ('grpc.max_connection_age_grace_ms', 30000),
+ ('grpc.max_receive_message_length', 4 * 1024 * 1024),
+ ('grpc.max_send_message_length', 4 * 1024 * 1024),
+ ]
+
+ server = grpc.server(
+ futures.ThreadPoolExecutor(max_workers=100),
+ options=options,
+ compression=compression.Gzip
+ )
+
+ return server
+```
+
+## 健康检查
+
+实现用于负载均衡器集成的健康检查:
+
+```protobuf health.proto
+syntax = "proto3";
+
+package grpc.health.v1;
+
+service Health {
+ // Check health status
+ rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
+
+ // Watch health status changes
+ rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
+}
+
+message HealthCheckRequest {
+ string service = 1;
+}
+
+message HealthCheckResponse {
+ enum ServingStatus {
+ UNKNOWN = 0;
+ SERVING = 1;
+ NOT_SERVING = 2;
+ SERVICE_UNKNOWN = 3;
+ }
+ ServingStatus status = 1;
+}
+```
+
+健康服务实现:
+
+```python title="health_service.py"
+import grpc
+from grpc_health.v1 import health_pb2
+from grpc_health.v1 import health_pb2_grpc
+
+class HealthServicer(health_pb2_grpc.HealthServicer):
+
+ def __init__(self):
+ self._service_status = {}
+
+ def Check(self, request, context):
+ service_name = request.service
+ status = self._service_status.get(
+ service_name,
+ health_pb2.HealthCheckResponse.SERVING
+ )
+
+ return health_pb2.HealthCheckResponse(status=status)
+
+ def Watch(self, request, context):
+ # Implementation for streaming health updates
+ service_name = request.service
+
+ while not context.is_active():
+ status = self._service_status.get(
+ service_name,
+ health_pb2.HealthCheckResponse.SERVING
+ )
+
+ yield health_pb2.HealthCheckResponse(status=status)
+ time.sleep(5) # Check every 5 seconds
+
+ def set_service_status(self, service_name, status):
+ self._service_status[service_name] = status
+```
+
+## 反射
+
+为开发和调试启用 gRPC 反射:
+
+```python title="reflection_server.py"
+import grpc
+from grpc_reflection.v1alpha import reflection
+
+def create_server_with_reflection():
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+
+ # Add services
+ user_service_pb2_grpc.add_UserServiceServicer_to_server(
+ UserServiceServicer(), server
+ )
+
+ # Enable reflection
+ SERVICE_NAMES = (
+ user_service_pb2.DESCRIPTOR.services_by_name['UserService'].full_name,
+ reflection.SERVICE_NAME,
+ )
+ reflection.enable_server_reflection(SERVICE_NAMES, server)
+
+ server.add_insecure_port('[::]:50051')
+ return server
+```
+
+## 负载均衡
+
+配置客户端负载均衡:
+
+```python title="load_balanced_client.py"
+import grpc
+
+def create_load_balanced_channel():
+ # DNS-based load balancing
+ channel = grpc.insecure_channel(
+ 'dns:///user-service.example.com:50051',
+ options=[
+ ('grpc.lb_policy_name', 'round_robin'),
+ ('grpc.dns_enable_srv_queries', True),
+ ]
+ )
+
+ return channel
+
+# Using a load balancer with multiple targets
+def create_multi_target_channel():
+ targets = [
+ 'user-service-1.example.com:50051',
+ 'user-service-2.example.com:50051',
+ 'user-service-3.example.com:50051',
+ ]
+
+ # Use a service mesh or load balancer
+ channel = grpc.insecure_channel(
+ f'ipv4:///{",".join(targets)}',
+ options=[('grpc.lb_policy_name', 'round_robin')]
+ )
+
+ return channel
+```
+
+## Kubernetes 部署
+
+在 Kubernetes 上部署 gRPC 服务:
+
+```yaml title="grpc-service.yaml"
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: user-service
+spec:
+ replicas: 3
+ selector:
+ matchLabels:
+ app: user-service
+ template:
+ metadata:
+ labels:
+ app: user-service
+ spec:
+ containers:
+ - name: user-service
+ image: user-service:latest
+ ports:
+ - containerPort: 50051
+ name: grpc
+ env:
+ - name: GRPC_PORT
+ value: "50051"
+ livenessProbe:
+ exec:
+ command: ["/bin/grpc_health_probe", "-addr=:50051"]
+ initialDelaySeconds: 30
+ readinessProbe:
+ exec:
+ command: ["/bin/grpc_health_probe", "-addr=:50051"]
+ initialDelaySeconds: 5
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: user-service
+spec:
+ selector:
+ app: user-service
+ ports:
+ - port: 50051
+ targetPort: 50051
+ name: grpc
+ type: ClusterIP
+```
+
+## 监控和可观测性
+
+为你的 gRPC 服务器添加监控和跟踪:
+
+```python title="monitored_server.py"
+import grpc
+import time
+from prometheus_client import Counter, Histogram, start_http_server
+
+# Prometheus metrics
+REQUEST_COUNT = Counter(
+ 'grpc_requests_total',
+ 'Total gRPC requests',
+ ['method', 'status']
+)
+
+REQUEST_DURATION = Histogram(
+ 'grpc_request_duration_seconds',
+ 'gRPC request duration',
+ ['method']
+)
+
+class MonitoringInterceptor(grpc.ServerInterceptor):
+
+ def intercept_service(self, continuation, handler_call_details):
+ method = handler_call_details.method
+ start_time = time.time()
+
+ def monitor_wrapper(behavior):
+ def wrapper(request, context):
+ try:
+ response = behavior(request, context)
+ REQUEST_COUNT.labels(method=method, status='OK').inc()
+ return response
+ except Exception as e:
+ REQUEST_COUNT.labels(method=method, status='ERROR').inc()
+ raise
+ finally:
+ duration = time.time() - start_time
+ REQUEST_DURATION.labels(method=method).observe(duration)
+
+ return wrapper
+
+ return grpc.unary_unary_rpc_method_handler(
+ monitor_wrapper(continuation(handler_call_details).unary_unary)
+ )
+
+def create_monitored_server():
+ # Start Prometheus metrics server
+ start_http_server(8000)
+
+ server = grpc.server(
+ futures.ThreadPoolExecutor(max_workers=10),
+ interceptors=[MonitoringInterceptor()]
+ )
+
+ return server
+```
+
+## 环境特定配置
+
+为不同环境配置服务器:
+
+```python title="config.py"
+import os
+from dataclasses import dataclass
+
+@dataclass
+class ServerConfig:
+ port: int
+ max_workers: int
+ enable_tls: bool
+ cert_file: str = None
+ key_file: str = None
+ enable_reflection: bool = False
+ enable_health_check: bool = True
+
+def get_config() -> ServerConfig:
+ env = os.getenv('ENVIRONMENT', 'development')
+
+ if env == 'production':
+ return ServerConfig(
+ port=50051,
+ max_workers=100,
+ enable_tls=True,
+ cert_file='/etc/ssl/certs/server.crt',
+ key_file='/etc/ssl/private/server.key',
+ enable_reflection=False,
+ enable_health_check=True
+ )
+ elif env == 'staging':
+ return ServerConfig(
+ port=50051,
+ max_workers=50,
+ enable_tls=True,
+ cert_file='/etc/ssl/certs/staging.crt',
+ key_file='/etc/ssl/private/staging.key',
+ enable_reflection=True,
+ enable_health_check=True
+ )
+ else: # development
+ return ServerConfig(
+ port=50051,
+ max_workers=10,
+ enable_tls=False,
+ enable_reflection=True,
+ enable_health_check=True
+ )
+
+def create_server_from_config(config: ServerConfig):
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=config.max_workers))
+
+ # Add services...
+
+ if config.enable_tls:
+ # Configure TLS
+ with open(config.cert_file, 'rb') as f:
+ cert = f.read()
+ with open(config.key_file, 'rb') as f:
+ key = f.read()
+
+ credentials = grpc.ssl_server_credentials([(key, cert)])
+ server.add_secure_port(f'[::]:{config.port}', credentials)
+ else:
+ server.add_insecure_port(f'[::]:{config.port}')
+
+ return server
+```
+
+正确的服务器配置确保你的 gRPC 服务安全、高性能并为生产工作负载做好准备。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/services/errors.mdx b/fern/translations/zh/products/api-def/grpc/services/errors.mdx
new file mode 100644
index 000000000..7ea271b06
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/services/errors.mdx
@@ -0,0 +1,528 @@
+---
+title: 错误处理
+subtitle: 使用 gRPC 状态码和自定义错误详情实现强大的错误处理
+sidebar-title: 错误处理
+---
+
+
+gRPC 提供了一个全面的错误处理系统,使用状态码、错误消息和可选的错误详情。正确的错误处理确保客户端能够适当地响应不同的故障场景。
+
+## gRPC 状态码
+
+gRPC 使用标准状态码来指示 RPC 调用的结果:
+
+```protobuf title="error_service.proto"
+syntax = "proto3";
+
+package errors.v1;
+
+import "google/rpc/status.proto";
+import "google/rpc/error_details.proto";
+
+service ErrorDemoService {
+ // 演示各种错误场景
+ rpc ValidateUser(ValidateUserRequest) returns (ValidateUserResponse);
+
+ // 可能返回速率限制错误
+ rpc RateLimitedOperation(OperationRequest) returns (OperationResponse);
+
+ // 可能返回资源耗尽错误
+ rpc ResourceIntensiveOperation(ResourceRequest) returns (ResourceResponse);
+}
+
+message ValidateUserRequest {
+ string user_id = 1;
+ string email = 2;
+}
+
+message ValidateUserResponse {
+ bool valid = 1;
+ repeated ValidationError errors = 2;
+}
+
+message ValidationError {
+ string field = 1;
+ string message = 2;
+ ErrorCode code = 3;
+}
+
+enum ErrorCode {
+ ERROR_CODE_UNSPECIFIED = 0;
+ ERROR_CODE_REQUIRED_FIELD = 1;
+ ERROR_CODE_INVALID_FORMAT = 2;
+ ERROR_CODE_DUPLICATE_VALUE = 3;
+ ERROR_CODE_OUT_OF_RANGE = 4;
+}
+```
+
+## 标准错误处理
+
+实现标准 gRPC 错误响应:
+
+```python title="error_handling.py"
+import grpc
+from grpc import ServicerContext
+from google.rpc import status_pb2, error_details_pb2
+from google.protobuf import any_pb2
+
+class ErrorDemoServiceServicer(errors_pb2_grpc.ErrorDemoServiceServicer):
+
+ def ValidateUser(
+ self,
+ request: errors_pb2.ValidateUserRequest,
+ context: ServicerContext
+ ) -> errors_pb2.ValidateUserResponse:
+ """演示验证错误。"""
+
+ validation_errors = []
+
+ # 检查必填字段
+ if not request.user_id:
+ validation_errors.append(errors_pb2.ValidationError(
+ field="user_id",
+ message="User ID is required",
+ code=errors_pb2.ERROR_CODE_REQUIRED_FIELD
+ ))
+
+ if not request.email:
+ validation_errors.append(errors_pb2.ValidationError(
+ field="email",
+ message="Email is required",
+ code=errors_pb2.ERROR_CODE_REQUIRED_FIELD
+ ))
+
+ # 验证邮箱格式
+ if request.email and not self._is_valid_email(request.email):
+ validation_errors.append(errors_pb2.ValidationError(
+ field="email",
+ message="Invalid email format",
+ code=errors_pb2.ERROR_CODE_INVALID_FORMAT
+ ))
+
+ # 检查用户是否重复
+ if request.user_id and self.user_exists(request.user_id):
+ validation_errors.append(errors_pb2.ValidationError(
+ field="user_id",
+ message="User ID already exists",
+ code=errors_pb2.ERROR_CODE_DUPLICATE_VALUE
+ ))
+
+ # 如果有验证错误则返回
+ if validation_errors:
+ context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
+ context.set_details("Validation failed")
+
+ return errors_pb2.ValidateUserResponse(
+ valid=False,
+ errors=validation_errors
+ )
+
+ return errors_pb2.ValidateUserResponse(valid=True)
+
+ def RateLimitedOperation(
+ self,
+ request: errors_pb2.OperationRequest,
+ context: ServicerContext
+ ) -> errors_pb2.OperationResponse:
+ """演示速率限制错误。"""
+
+ # 检查速率限制
+ if not self.rate_limiter.is_allowed(request.client_id):
+ # 创建详细的错误信息
+ retry_info = error_details_pb2.RetryInfo()
+ retry_info.retry_delay.seconds = 60 # 60 秒后重试
+
+ quota_failure = error_details_pb2.QuotaFailure()
+ violation = quota_failure.violations.add()
+ violation.subject = f"client:{request.client_id}"
+ violation.description = "API rate limit exceeded"
+
+ # 设置带详情的错误
+ context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED)
+ context.set_details("Rate limit exceeded")
+
+ # 添加错误详情(丰富的错误信息)
+ self._add_error_details(context, [retry_info, quota_failure])
+
+ return errors_pb2.OperationResponse()
+
+ # 正常处理操作
+ return self._process_operation(request)
+
+ def ResourceIntensiveOperation(
+ self,
+ request: errors_pb2.ResourceRequest,
+ context: ServicerContext
+ ) -> errors_pb2.ResourceResponse:
+ """演示资源耗尽错误。"""
+
+ try:
+ # 检查系统资源
+ if not self.resource_manager.has_capacity():
+ context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED)
+ context.set_details("System overloaded, please try again later")
+ return errors_pb2.ResourceResponse()
+
+ # 处理密集型操作
+ result = self._process_intensive_operation(request)
+ return errors_pb2.ResourceResponse(result=result)
+
+ except TimeoutError:
+ context.set_code(grpc.StatusCode.DEADLINE_EXCEEDED)
+ context.set_details("Operation timed out")
+ return errors_pb2.ResourceResponse()
+
+ except PermissionError:
+ context.set_code(grpc.StatusCode.PERMISSION_DENIED)
+ context.set_details("Insufficient permissions for this operation")
+ return errors_pb2.ResourceResponse()
+
+ except FileNotFoundError as e:
+ context.set_code(grpc.StatusCode.NOT_FOUND)
+ context.set_details(f"Required resource not found: {str(e)}")
+ return errors_pb2.ResourceResponse()
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f"Internal server error: {str(e)}")
+ return errors_pb2.ResourceResponse()
+
+ def _add_error_details(self, context: ServicerContext, details):
+ """向 gRPC 响应添加丰富的错误详情。"""
+ rich_status = status_pb2.Status()
+ rich_status.code = context._state.code.value[0]
+ rich_status.message = context._state.details
+
+ for detail in details:
+ detail_any = any_pb2.Any()
+ detail_any.Pack(detail)
+ rich_status.details.append(detail_any)
+
+ # 添加到尾随元数据
+ context.set_trailing_metadata([
+ ('grpc-status-details-bin', rich_status.SerializeToString())
+ ])
+```
+
+## 自定义错误类型
+
+为特定领域的错误定义自定义错误类型:
+
+```protobuf title="custom_errors.proto"
+syntax = "proto3";
+
+package errors.v1;
+
+// 自定义错误详情
+message BusinessLogicError {
+ string error_code = 1;
+ string error_message = 2;
+ map error_context = 3;
+ repeated string suggested_actions = 4;
+}
+
+message ValidationFailure {
+ repeated FieldError field_errors = 1;
+ string global_error = 2;
+}
+
+message FieldError {
+ string field_path = 1;
+ string error_message = 2;
+ string error_code = 3;
+ google.protobuf.Any invalid_value = 4;
+}
+
+message ServiceUnavailableError {
+ string service_name = 1;
+ google.protobuf.Timestamp estimated_recovery_time = 2;
+ repeated string alternative_endpoints = 3;
+}
+```
+
+自定义错误实现:
+
+```python title="custom_errors.py"
+class CustomErrorHandler:
+
+ @staticmethod
+ def business_logic_error(
+ context: ServicerContext,
+ error_code: str,
+ message: str,
+ error_context: dict = None,
+ suggested_actions: list = None
+ ):
+ """创建业务逻辑错误。"""
+
+ business_error = errors_pb2.BusinessLogicError(
+ error_code=error_code,
+ error_message=message,
+ error_context=error_context or {},
+ suggested_actions=suggested_actions or []
+ )
+
+ context.set_code(grpc.StatusCode.FAILED_PRECONDITION)
+ context.set_details(message)
+
+ # 添加自定义错误详情
+ CustomErrorHandler._add_custom_details(context, business_error)
+
+ @staticmethod
+ def validation_failure(
+ context: ServicerContext,
+ field_errors: list,
+ global_error: str = None
+ ):
+ """创建验证失败错误。"""
+
+ validation_error = errors_pb2.ValidationFailure(
+ field_errors=field_errors,
+ global_error=global_error or ""
+ )
+
+ context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
+ context.set_details("Validation failed")
+
+ CustomErrorHandler._add_custom_details(context, validation_error)
+
+ @staticmethod
+ def service_unavailable(
+ context: ServicerContext,
+ service_name: str,
+ estimated_recovery: datetime = None,
+ alternatives: list = None
+ ):
+ """创建服务不可用错误。"""
+
+ error = errors_pb2.ServiceUnavailableError(
+ service_name=service_name,
+ alternative_endpoints=alternatives or []
+ )
+
+ if estimated_recovery:
+ error.estimated_recovery_time.FromDatetime(estimated_recovery)
+
+ context.set_code(grpc.StatusCode.UNAVAILABLE)
+ context.set_details(f"Service {service_name} is currently unavailable")
+
+ CustomErrorHandler._add_custom_details(context, error)
+
+ @staticmethod
+ def _add_custom_details(context: ServicerContext, error_detail):
+ """向响应添加自定义错误详情。"""
+ detail_any = any_pb2.Any()
+ detail_any.Pack(error_detail)
+
+ rich_status = status_pb2.Status()
+ rich_status.code = context._state.code.value[0]
+ rich_status.message = context._state.details
+ rich_status.details.append(detail_any)
+
+ context.set_trailing_metadata([
+ ('grpc-status-details-bin', rich_status.SerializeToString())
+ ])
+
+# 使用示例
+class UserService(user_pb2_grpc.UserServiceServicer):
+
+ def CreateUser(self, request, context):
+ # 验证业务规则
+ if self.user_repository.email_exists(request.email):
+ CustomErrorHandler.business_logic_error(
+ context,
+ error_code="DUPLICATE_EMAIL",
+ message="Email address is already registered",
+ error_context={"email": request.email},
+ suggested_actions=[
+ "Use a different email address",
+ "Reset password if you forgot your account"
+ ]
+ )
+ return user_pb2.User()
+
+ # 继续用户创建...
+```
+
+## 错误拦截器
+
+使用拦截器实现全局错误处理:
+
+```python title="error_interceptor.py"
+import logging
+import traceback
+from grpc import ServicerContext, StatusCode
+
+class ErrorInterceptor(grpc.ServerInterceptor):
+
+ def __init__(self, logger=None):
+ self.logger = logger or logging.getLogger(__name__)
+
+ def intercept_service(self, continuation, handler_call_details):
+ def error_wrapper(behavior):
+ def wrapper(request, context):
+ try:
+ return behavior(request, context)
+
+ except ValueError as e:
+ # 将 Python ValueError 转换为 gRPC INVALID_ARGUMENT
+ context.set_code(StatusCode.INVALID_ARGUMENT)
+ context.set_details(f"Invalid input: {str(e)}")
+ self.logger.warning(f"Validation error in {handler_call_details.method}: {e}")
+ return self._get_default_response(behavior)
+
+ except PermissionError as e:
+ context.set_code(StatusCode.PERMISSION_DENIED)
+ context.set_details("Access denied")
+ self.logger.warning(f"Permission denied in {handler_call_details.method}: {e}")
+ return self._get_default_response(behavior)
+
+ except TimeoutError as e:
+ context.set_code(StatusCode.DEADLINE_EXCEEDED)
+ context.set_details("Operation timed out")
+ self.logger.error(f"Timeout in {handler_call_details.method}: {e}")
+ return self._get_default_response(behavior)
+
+ except Exception as e:
+ # 记录未预期的错误
+ self.logger.error(
+ f"Unexpected error in {handler_call_details.method}: {e}\n"
+ f"Traceback: {traceback.format_exc()}"
+ )
+
+ context.set_code(StatusCode.INTERNAL)
+ context.set_details("Internal server error")
+ return self._get_default_response(behavior)
+
+ return wrapper
+
+ return grpc.unary_unary_rpc_method_handler(
+ error_wrapper(continuation(handler_call_details).unary_unary)
+ )
+
+ def _get_default_response(self, behavior):
+ """返回正确类型的空响应。"""
+ # 这需要根据您的服务方法进行实现
+ return None
+```
+
+## 客户端错误处理
+
+在客户端处理错误:
+
+```python title="client_error_handling.py"
+import grpc
+from google.rpc import status_pb2, error_details_pb2
+from google.protobuf import any_pb2
+
+def handle_grpc_errors(stub_method, request):
+ """gRPC 客户端调用的通用错误处理。"""
+
+ try:
+ response = stub_method(request)
+ return response, None
+
+ except grpc.RpcError as e:
+ error_info = {
+ 'code': e.code(),
+ 'details': e.details(),
+ 'status': e.code().name
+ }
+
+ # 如果可用,提取丰富的错误详情
+ metadata = dict(e.trailing_metadata())
+ if 'grpc-status-details-bin' in metadata:
+ try:
+ status_detail = status_pb2.Status()
+ status_detail.ParseFromString(metadata['grpc-status-details-bin'])
+
+ error_info['rich_details'] = []
+ for detail in status_detail.details:
+ # 尝试解包常见错误类型
+ if detail.Is(error_details_pb2.RetryInfo.DESCRIPTOR):
+ retry_info = error_details_pb2.RetryInfo()
+ detail.Unpack(retry_info)
+ error_info['rich_details'].append({
+ 'type': 'retry_info',
+ 'retry_delay_seconds': retry_info.retry_delay.seconds
+ })
+ elif detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR):
+ quota_failure = error_details_pb2.QuotaFailure()
+ detail.Unpack(quota_failure)
+ error_info['rich_details'].append({
+ 'type': 'quota_failure',
+ 'violations': [
+ {
+ 'subject': v.subject,
+ 'description': v.description
+ } for v in quota_failure.violations
+ ]
+ })
+
+ except Exception:
+ # 如果无法解析丰富的详情,那也没关系
+ pass
+
+ return None, error_info
+
+# 使用示例
+def create_user_with_error_handling(stub, user_data):
+ """创建用户并进行全面的错误处理。"""
+
+ request = user_pb2.CreateUserRequest(**user_data)
+ response, error = handle_grpc_errors(stub.CreateUser, request)
+
+ if error:
+ if error['code'] == grpc.StatusCode.INVALID_ARGUMENT:
+ print(f"Validation failed: {error['details']}")
+ return None
+
+ elif error['code'] == grpc.StatusCode.ALREADY_EXISTS:
+ print(f"User already exists: {error['details']}")
+ return None
+
+ elif error['code'] == grpc.StatusCode.RESOURCE_EXHAUSTED:
+ # 检查重试信息
+ for detail in error.get('rich_details', []):
+ if detail['type'] == 'retry_info':
+ retry_delay = detail['retry_delay_seconds']
+ print(f"Rate limited. Retry after {retry_delay} seconds")
+ return None
+
+ print("Resource exhausted")
+ return None
+
+ else:
+ print(f"Unexpected error: {error['status']} - {error['details']}")
+ return None
+
+ return response
+```
+
+## 错误响应模式
+
+定义一致的错误响应模式:
+
+```protobuf title="error_responses.proto"
+syntax = "proto3";
+
+// 标准错误响应包装器
+message ErrorResponse {
+ string error_code = 1;
+ string error_message = 2;
+ map error_context = 3;
+ repeated string suggestions = 4;
+ google.protobuf.Timestamp timestamp = 5;
+ string request_id = 6;
+}
+
+// 联合响应模式
+message CreateUserResult {
+ oneof result {
+ User success = 1;
+ ErrorResponse error = 2;
+ }
+}
+```
+
+gRPC 中正确的错误处理确保了强大、可维护的服务,为客户端提供关于出了什么问题以及如何修复的明确反馈。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/services/grpc-services.mdx b/fern/translations/zh/products/api-def/grpc/services/grpc-services.mdx
new file mode 100644
index 000000000..12336eb24
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/services/grpc-services.mdx
@@ -0,0 +1,449 @@
+---
+title: gRPC 服务
+subtitle: 使用 RPC、消息和 Protocol Buffer 模式定义 gRPC 服务
+sidebar-title: gRPC 服务
+---
+
+gRPC 服务是 API 的核心构建块。每个服务定义了客户端可以调用的远程过程调用(RPC)集合,以及用于请求和响应的消息类型。
+
+## 服务定义
+
+在 `.proto` 文件中定义 gRPC 服务:
+
+```protobuf title="user_service.proto"
+syntax = "proto3";
+
+package userservice.v1;
+
+import "google/protobuf/empty.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/field_mask.proto";
+
+// User management service
+service UserService {
+ // Create a new user account
+ rpc CreateUser(CreateUserRequest) returns (User) {
+ option deprecated = false;
+ }
+
+ // Get user by ID
+ rpc GetUser(GetUserRequest) returns (User);
+
+ // Update user information
+ rpc UpdateUser(UpdateUserRequest) returns (User);
+
+ // Delete a user account
+ rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);
+
+ // List users with pagination
+ rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
+
+ // Search users by various criteria
+ rpc SearchUsers(SearchUsersRequest) returns (SearchUsersResponse);
+}
+
+// User message definition
+message User {
+ string id = 1;
+ string email = 2;
+ string name = 3;
+ int32 age = 4;
+ UserStatus status = 5;
+ google.protobuf.Timestamp created_at = 6;
+ google.protobuf.Timestamp updated_at = 7;
+ repeated string roles = 8;
+ UserPreferences preferences = 9;
+}
+
+// User status enumeration
+enum UserStatus {
+ USER_STATUS_UNSPECIFIED = 0;
+ USER_STATUS_ACTIVE = 1;
+ USER_STATUS_INACTIVE = 2;
+ USER_STATUS_SUSPENDED = 3;
+ USER_STATUS_DELETED = 4;
+}
+
+// Nested message for user preferences
+message UserPreferences {
+ bool email_notifications = 1;
+ string timezone = 2;
+ string language = 3;
+ ThemeMode theme = 4;
+}
+
+enum ThemeMode {
+ THEME_MODE_UNSPECIFIED = 0;
+ THEME_MODE_LIGHT = 1;
+ THEME_MODE_DARK = 2;
+ THEME_MODE_AUTO = 3;
+}
+```
+
+## 请求和响应消息
+
+定义清晰的请求和响应消息类型:
+
+```protobuf title="user_messages.proto"
+// Create user request
+message CreateUserRequest {
+ string email = 1 [(validate.rules).string.email = true];
+ string name = 2 [(validate.rules).string.min_len = 1];
+ int32 age = 3 [(validate.rules).int32.gte = 0];
+ UserPreferences preferences = 4;
+}
+
+// Get user request
+message GetUserRequest {
+ string id = 1 [(validate.rules).string.uuid = true];
+}
+
+// Update user request
+message UpdateUserRequest {
+ string id = 1 [(validate.rules).string.uuid = true];
+ User user = 2;
+ google.protobuf.FieldMask update_mask = 3;
+}
+
+// Delete user request
+message DeleteUserRequest {
+ string id = 1 [(validate.rules).string.uuid = true];
+}
+
+// List users request with pagination
+message ListUsersRequest {
+ int32 page_size = 1 [(validate.rules).int32 = {gte: 1, lte: 100}];
+ string page_token = 2;
+ string filter = 3;
+ string order_by = 4;
+}
+
+// List users response
+message ListUsersResponse {
+ repeated User users = 1;
+ string next_page_token = 2;
+ int32 total_count = 3;
+}
+
+// Search users request
+message SearchUsersRequest {
+ string query = 1 [(validate.rules).string.min_len = 1];
+ repeated UserStatus status_filter = 2;
+ repeated string role_filter = 3;
+ int32 page_size = 4 [(validate.rules).int32 = {gte: 1, lte: 100}];
+ string page_token = 5;
+}
+
+// Search users response
+message SearchUsersResponse {
+ repeated User users = 1;
+ string next_page_token = 2;
+ int32 total_count = 3;
+ SearchMetadata metadata = 4;
+}
+
+message SearchMetadata {
+ int32 search_time_ms = 1;
+ repeated string suggested_corrections = 2;
+}
+```
+
+## 服务实现
+
+使用您首选的语言实现服务:
+
+```python title="user_service.py"
+import grpc
+from grpc import ServicerContext
+import user_service_pb2
+import user_service_pb2_grpc
+from google.protobuf import empty_pb2
+from typing import Iterator
+
+class UserServiceServicer(user_service_pb2_grpc.UserServiceServicer):
+
+ def __init__(self, user_repository):
+ self.user_repository = user_repository
+
+ def CreateUser(
+ self,
+ request: user_service_pb2.CreateUserRequest,
+ context: ServicerContext
+ ) -> user_service_pb2.User:
+ """Create a new user account."""
+ try:
+ # Validate request
+ if not request.email or not request.name:
+ context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
+ context.set_details('Email and name are required')
+ return user_service_pb2.User()
+
+ # Check if user already exists
+ if self.user_repository.get_by_email(request.email):
+ context.set_code(grpc.StatusCode.ALREADY_EXISTS)
+ context.set_details(f'User with email {request.email} already exists')
+ return user_service_pb2.User()
+
+ # Create user
+ user = self.user_repository.create_user(
+ email=request.email,
+ name=request.name,
+ age=request.age,
+ preferences=request.preferences
+ )
+
+ return user
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Failed to create user: {str(e)}')
+ return user_service_pb2.User()
+
+ def GetUser(
+ self,
+ request: user_service_pb2.GetUserRequest,
+ context: ServicerContext
+ ) -> user_service_pb2.User:
+ """Get user by ID."""
+ try:
+ user = self.user_repository.get_by_id(request.id)
+ if not user:
+ context.set_code(grpc.StatusCode.NOT_FOUND)
+ context.set_details(f'User with ID {request.id} not found')
+ return user_service_pb2.User()
+
+ return user
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Failed to get user: {str(e)}')
+ return user_service_pb2.User()
+
+ def UpdateUser(
+ self,
+ request: user_service_pb2.UpdateUserRequest,
+ context: ServicerContext
+ ) -> user_service_pb2.User:
+ """Update user information."""
+ try:
+ # Check if user exists
+ existing_user = self.user_repository.get_by_id(request.id)
+ if not existing_user:
+ context.set_code(grpc.StatusCode.NOT_FOUND)
+ context.set_details(f'User with ID {request.id} not found')
+ return user_service_pb2.User()
+
+ # Apply field mask for partial updates
+ updated_user = self.user_repository.update_user(
+ user_id=request.id,
+ updates=request.user,
+ field_mask=request.update_mask
+ )
+
+ return updated_user
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Failed to update user: {str(e)}')
+ return user_service_pb2.User()
+
+ def DeleteUser(
+ self,
+ request: user_service_pb2.DeleteUserRequest,
+ context: ServicerContext
+ ) -> empty_pb2.Empty:
+ """Delete a user account."""
+ try:
+ # Check if user exists
+ user = self.user_repository.get_by_id(request.id)
+ if not user:
+ context.set_code(grpc.StatusCode.NOT_FOUND)
+ context.set_details(f'User with ID {request.id} not found')
+ return empty_pb2.Empty()
+
+ # Soft delete user
+ self.user_repository.delete_user(request.id)
+
+ return empty_pb2.Empty()
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Failed to delete user: {str(e)}')
+ return empty_pb2.Empty()
+
+ def ListUsers(
+ self,
+ request: user_service_pb2.ListUsersRequest,
+ context: ServicerContext
+ ) -> user_service_pb2.ListUsersResponse:
+ """List users with pagination."""
+ try:
+ # Apply pagination
+ page_size = min(request.page_size or 20, 100)
+
+ users, next_page_token, total_count = self.user_repository.list_users(
+ page_size=page_size,
+ page_token=request.page_token,
+ filter_expr=request.filter,
+ order_by=request.order_by
+ )
+
+ return user_service_pb2.ListUsersResponse(
+ users=users,
+ next_page_token=next_page_token,
+ total_count=total_count
+ )
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Failed to list users: {str(e)}')
+ return user_service_pb2.ListUsersResponse()
+
+ def SearchUsers(
+ self,
+ request: user_service_pb2.SearchUsersRequest,
+ context: ServicerContext
+ ) -> user_service_pb2.SearchUsersResponse:
+ """Search users by various criteria."""
+ try:
+ start_time = time.time()
+
+ users, next_page_token, total_count = self.user_repository.search_users(
+ query=request.query,
+ status_filter=request.status_filter,
+ role_filter=request.role_filter,
+ page_size=request.page_size or 20,
+ page_token=request.page_token
+ )
+
+ search_time_ms = int((time.time() - start_time) * 1000)
+
+ metadata = user_service_pb2.SearchMetadata(
+ search_time_ms=search_time_ms,
+ suggested_corrections=[] # Add spell check suggestions if needed
+ )
+
+ return user_service_pb2.SearchUsersResponse(
+ users=users,
+ next_page_token=next_page_token,
+ total_count=total_count,
+ metadata=metadata
+ )
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Failed to search users: {str(e)}')
+ return user_service_pb2.SearchUsersResponse()
+```
+
+## Protocol Buffer 最佳实践
+
+### 字段编号
+- 对于频繁使用的字段使用字段编号 1-15(编码更高效)
+- 为已删除的字段保留字段编号以维持兼容性
+- 永远不要重复使用字段编号
+
+```protobuf
+message User {
+ // 频繁使用的字段 (1-15)
+ string id = 1;
+ string email = 2;
+ string name = 3;
+
+ // 不太频繁使用的字段
+ UserPreferences preferences = 16;
+ repeated string tags = 17;
+
+ // 保留字段
+ reserved 4, 5, 6;
+ reserved "old_field_name", "deprecated_field";
+}
+```
+
+### 命名规范
+- 字段名使用 `snake_case`
+- 消息和服务名使用 `PascalCase`
+- 枚举值使用 `UPPER_SNAKE_CASE`
+
+```protobuf
+service UserManagementService { // PascalCase
+ rpc GetUser(GetUserRequest) returns (User);
+}
+
+message User { // PascalCase
+ string first_name = 1; // snake_case
+ UserStatus status = 2;
+}
+
+enum UserStatus {
+ USER_STATUS_UNSPECIFIED = 0; // UPPER_SNAKE_CASE
+ USER_STATUS_ACTIVE = 1;
+}
+```
+
+### 版本管理
+- 在包名中包含版本
+- 对于破坏性更改使用语义版本控制
+
+```protobuf
+syntax = "proto3";
+
+package userservice.v1; // 包名中的版本
+
+option go_package = "example.com/userservice/v1";
+```
+
+## 多个服务
+
+将相关功能组织到单独的服务中:
+
+```protobuf title="services.proto"
+// 用户管理
+service UserService {
+ rpc CreateUser(CreateUserRequest) returns (User);
+ rpc GetUser(GetUserRequest) returns (User);
+}
+
+// 身份验证
+service AuthService {
+ rpc Login(LoginRequest) returns (LoginResponse);
+ rpc RefreshToken(RefreshTokenRequest) returns (RefreshTokenResponse);
+}
+
+// 通知服务
+service NotificationService {
+ rpc SendNotification(SendNotificationRequest) returns (SendNotificationResponse);
+ rpc GetNotificationPreferences(GetNotificationPreferencesRequest) returns (NotificationPreferences);
+}
+```
+
+gRPC 服务为构建分布式系统提供了强类型、高性能的基础,在客户端和服务器之间建立了清晰的合约。
+
+## 自定义选项
+
+Fern 提供自定义 Protocol Buffer 选项来增强您的 API 参考文档和生成的代码。
+
+### API 导航名称
+
+使用 `fern.summary` 选项为端点设置明确的显示名称,比默认的 RPC 方法名称更用户友好。
+
+
+```protobuf
+// Import Fern custom options
+import "fern/options.proto";
+
+service CommentsService {
+ // Description of the endpoint
+ rpc CreateComment(CreateCommentRequest) returns (CreateCommentResponse) {
+ option (google.api.http) = {
+ post: "/comments/v1/comments"
+ response_body: "comment"
+ body: "*"
+ };
+
+ // Display name shown in navigation
+ option (fern.summary) = "Create your comment";
+ }
+}
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/grpc/services/streaming.mdx b/fern/translations/zh/products/api-def/grpc/services/streaming.mdx
new file mode 100644
index 000000000..643f56a35
--- /dev/null
+++ b/fern/translations/zh/products/api-def/grpc/services/streaming.mdx
@@ -0,0 +1,516 @@
+---
+title: 流式传输
+description: 学习如何在 gRPC 中实现服务器流式传输、客户端流式传输和双向流式传输,以实现实时通信和高效的数据传输。
+sidebar-title: 流式传输
+---
+
+
+gRPC 支持四种类型的服务方法:一元调用、服务器流式传输、客户端流式传输和双向流式传输。流式传输可实现高效的实时通信和大数据传输。
+
+## 服务器流式传输
+
+服务器流式传输允许服务器对单个客户端请求发送多个响应:
+
+```protobuf title="streaming_service.proto"
+syntax = "proto3";
+
+package streaming.v1;
+
+service StreamingService {
+ // 服务器流式传输:向客户端发送多个事件
+ rpc StreamUserEvents(StreamUserEventsRequest) returns (stream UserEvent);
+
+ // 服务器流式传输:分块下载大文件
+ rpc DownloadFile(DownloadFileRequest) returns (stream FileChunk);
+
+ // 服务器流式传输:实时通知
+ rpc SubscribeToNotifications(SubscribeRequest) returns (stream Notification);
+}
+
+message StreamUserEventsRequest {
+ string user_id = 1;
+ repeated UserEventType event_types = 2;
+ google.protobuf.Timestamp start_time = 3;
+}
+
+message UserEvent {
+ string id = 1;
+ string user_id = 2;
+ UserEventType type = 3;
+ google.protobuf.Timestamp timestamp = 4;
+ google.protobuf.Any data = 5;
+}
+
+enum UserEventType {
+ USER_EVENT_TYPE_UNSPECIFIED = 0;
+ USER_EVENT_TYPE_LOGIN = 1;
+ USER_EVENT_TYPE_LOGOUT = 2;
+ USER_EVENT_TYPE_PROFILE_UPDATE = 3;
+ USER_EVENT_TYPE_PASSWORD_CHANGE = 4;
+}
+```
+
+服务器流式传输实现:
+
+```python title="server_streaming.py"
+import grpc
+import time
+import asyncio
+from grpc import ServicerContext
+from typing import Iterator
+
+class StreamingServiceServicer(streaming_pb2_grpc.StreamingServiceServicer):
+
+ def StreamUserEvents(
+ self,
+ request: streaming_pb2.StreamUserEventsRequest,
+ context: ServicerContext
+ ) -> Iterator[streaming_pb2.UserEvent]:
+ """实时流式传输用户事件。"""
+
+ # 验证请求
+ if not request.user_id:
+ context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
+ context.set_details('User ID is required')
+ return
+
+ # 订阅事件流
+ event_subscriber = self.event_store.subscribe(
+ user_id=request.user_id,
+ event_types=request.event_types,
+ start_time=request.start_time
+ )
+
+ try:
+ while context.is_active():
+ # 等待下一个事件(带超时)
+ try:
+ event = event_subscriber.get_next_event(timeout=30)
+ if event:
+ yield event
+ else:
+ # 发送心跳以保持连接活跃
+ continue
+
+ except TimeoutError:
+ # 检查客户端是否仍然连接
+ if not context.is_active():
+ break
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Error streaming events: {str(e)}')
+ break
+
+ finally:
+ # 清理订阅
+ event_subscriber.close()
+
+ def DownloadFile(
+ self,
+ request: streaming_pb2.DownloadFileRequest,
+ context: ServicerContext
+ ) -> Iterator[streaming_pb2.FileChunk]:
+ """分块下载文件。"""
+
+ try:
+ file_path = self.file_store.get_file_path(request.file_id)
+ if not file_path or not os.path.exists(file_path):
+ context.set_code(grpc.StatusCode.NOT_FOUND)
+ context.set_details(f'File {request.file_id} not found')
+ return
+
+ chunk_size = 64 * 1024 # 64KB 块大小
+
+ with open(file_path, 'rb') as f:
+ while True:
+ chunk_data = f.read(chunk_size)
+ if not chunk_data:
+ break
+
+ # 检查客户端是否断开连接
+ if not context.is_active():
+ break
+
+ yield streaming_pb2.FileChunk(
+ data=chunk_data,
+ offset=f.tell() - len(chunk_data),
+ size=len(chunk_data)
+ )
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Error downloading file: {str(e)}')
+```
+
+## 客户端流式传输
+
+客户端流式传输允许客户端发送多个请求并接收单个响应:
+
+```protobuf title="client_streaming.proto"
+service StreamingService {
+ // 客户端流式传输:分块上传大文件
+ rpc UploadFile(stream FileChunk) returns (UploadFileResponse);
+
+ // 客户端流式传输:批量数据处理
+ rpc ProcessDataBatch(stream DataRecord) returns (BatchProcessingResult);
+
+ // 客户端流式传输:实时指标收集
+ rpc CollectMetrics(stream MetricData) returns (MetricsCollectionResult);
+}
+
+message FileChunk {
+ oneof data {
+ FileMetadata metadata = 1;
+ bytes chunk = 2;
+ }
+}
+
+message FileMetadata {
+ string filename = 1;
+ int64 total_size = 2;
+ string content_type = 3;
+ string checksum = 4;
+}
+
+message UploadFileResponse {
+ string file_id = 1;
+ int64 bytes_uploaded = 2;
+ string download_url = 3;
+ bool checksum_verified = 4;
+}
+```
+
+客户端流式传输实现:
+
+```python title="client_streaming.py"
+class StreamingServiceServicer(streaming_pb2_grpc.StreamingServiceServicer):
+
+ def UploadFile(
+ self,
+ request_iterator: Iterator[streaming_pb2.FileChunk],
+ context: ServicerContext
+ ) -> streaming_pb2.UploadFileResponse:
+ """从客户端流上传文件。"""
+
+ file_metadata = None
+ total_bytes = 0
+ file_path = None
+ hasher = hashlib.sha256()
+
+ try:
+ for chunk in request_iterator:
+ if chunk.HasField('metadata'):
+ # 第一个块包含元数据
+ file_metadata = chunk.metadata
+
+ # 创建临时文件
+ file_id = str(uuid.uuid4())
+ file_path = f'/tmp/uploads/{file_id}'
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
+
+ elif chunk.HasField('chunk'):
+ # 后续块包含文件数据
+ if not file_metadata:
+ context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
+ context.set_details('File metadata must be sent first')
+ return streaming_pb2.UploadFileResponse()
+
+ # 将块写入文件
+ with open(file_path, 'ab') as f:
+ f.write(chunk.chunk)
+
+ total_bytes += len(chunk.chunk)
+ hasher.update(chunk.chunk)
+
+ # 检查大小限制
+ if total_bytes > file_metadata.total_size:
+ context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
+ context.set_details('File size exceeds declared size')
+ return streaming_pb2.UploadFileResponse()
+
+ # 验证校验和
+ computed_checksum = hasher.hexdigest()
+ checksum_verified = computed_checksum == file_metadata.checksum
+
+ if not checksum_verified:
+ context.set_code(grpc.StatusCode.DATA_LOSS)
+ context.set_details('File checksum verification failed')
+ return streaming_pb2.UploadFileResponse()
+
+ # 将文件移动到永久存储
+ permanent_path = self.file_store.store_file(file_id, file_path)
+ download_url = self.file_store.get_download_url(file_id)
+
+ return streaming_pb2.UploadFileResponse(
+ file_id=file_id,
+ bytes_uploaded=total_bytes,
+ download_url=download_url,
+ checksum_verified=True
+ )
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Error uploading file: {str(e)}')
+ return streaming_pb2.UploadFileResponse()
+
+ finally:
+ # 清理临时文件
+ if file_path and os.path.exists(file_path):
+ os.remove(file_path)
+```
+
+## 双向流式传输
+
+双向流式传输允许客户端和服务器都发送多个消息:
+
+```protobuf title="bidirectional_streaming.proto"
+service StreamingService {
+ // 双向流式传输:实时聊天
+ rpc Chat(stream ChatMessage) returns (stream ChatMessage);
+
+ // 双向流式传输:实时协作
+ rpc Collaborate(stream CollaborationEvent) returns (stream CollaborationEvent);
+
+ // 双向流式传输:实时数据处理
+ rpc ProcessLiveData(stream DataInput) returns (stream ProcessingResult);
+}
+
+message ChatMessage {
+ string id = 1;
+ string user_id = 2;
+ string room_id = 3;
+ string content = 4;
+ google.protobuf.Timestamp timestamp = 5;
+ ChatMessageType type = 6;
+}
+
+enum ChatMessageType {
+ CHAT_MESSAGE_TYPE_UNSPECIFIED = 0;
+ CHAT_MESSAGE_TYPE_TEXT = 1;
+ CHAT_MESSAGE_TYPE_IMAGE = 2;
+ CHAT_MESSAGE_TYPE_FILE = 3;
+ CHAT_MESSAGE_TYPE_SYSTEM = 4;
+ CHAT_MESSAGE_TYPE_TYPING = 5;
+}
+```
+
+双向流式传输实现:
+
+```python title="bidirectional_streaming.py"
+import asyncio
+import queue
+import threading
+
+class StreamingServiceServicer(streaming_pb2_grpc.StreamingServiceServicer):
+
+ def Chat(
+ self,
+ request_iterator: Iterator[streaming_pb2.ChatMessage],
+ context: ServicerContext
+ ) -> Iterator[streaming_pb2.ChatMessage]:
+ """双向聊天流式传输。"""
+
+ # 出站消息队列
+ outgoing_queue = queue.Queue()
+
+ # 跟踪用户会话
+ user_session = None
+
+ def handle_incoming_messages():
+ """处理来自客户端的入站消息。"""
+ nonlocal user_session
+
+ try:
+ for message in request_iterator:
+ if not user_session:
+ # 第一条消息建立会话
+ user_session = self.chat_service.join_room(
+ user_id=message.user_id,
+ room_id=message.room_id
+ )
+
+ # 发送欢迎消息
+ welcome_msg = streaming_pb2.ChatMessage(
+ id=str(uuid.uuid4()),
+ user_id="system",
+ room_id=message.room_id,
+ content=f"User {message.user_id} joined the chat",
+ timestamp=google.protobuf.timestamp_pb2.Timestamp(),
+ type=streaming_pb2.CHAT_MESSAGE_TYPE_SYSTEM
+ )
+ outgoing_queue.put(welcome_msg)
+
+ # 处理消息
+ if message.type == streaming_pb2.CHAT_MESSAGE_TYPE_TEXT:
+ # 广播给房间内其他用户
+ self.chat_service.broadcast_message(message)
+
+ elif message.type == streaming_pb2.CHAT_MESSAGE_TYPE_TYPING:
+ # 向其他用户发送打字指示器
+ self.chat_service.broadcast_typing(message)
+
+ except Exception as e:
+ print(f"Error handling incoming messages: {e}")
+ finally:
+ # 清理会话
+ if user_session:
+ self.chat_service.leave_room(user_session)
+
+ # 启动处理入站消息的后台线程
+ incoming_thread = threading.Thread(target=handle_incoming_messages)
+ incoming_thread.daemon = True
+ incoming_thread.start()
+
+ # 订阅房间消息
+ message_subscriber = None
+ if user_session:
+ message_subscriber = self.chat_service.subscribe_to_room(
+ user_session.room_id,
+ exclude_user=user_session.user_id
+ )
+
+ try:
+ while context.is_active():
+ # 检查队列中的出站消息
+ try:
+ message = outgoing_queue.get(timeout=1)
+ yield message
+ except queue.Empty:
+ pass
+
+ # 检查来自其他用户的消息
+ if message_subscriber:
+ try:
+ room_message = message_subscriber.get_message(timeout=1)
+ if room_message:
+ yield room_message
+ except TimeoutError:
+ pass
+
+ finally:
+ # 清理
+ if message_subscriber:
+ message_subscriber.close()
+ if user_session:
+ self.chat_service.leave_room(user_session)
+```
+
+## 流式传输最佳实践
+
+### 流量控制
+实现适当的流量控制以防止客户端不堪重负:
+
+```python title="flow_control.py"
+def StreamData(self, request, context):
+ """带流量控制的流式传输。"""
+
+ # 使用有界队列控制内存使用
+ data_queue = queue.Queue(maxsize=100)
+
+ def data_producer():
+ """生成数据的后台线程。"""
+ for item in self.data_source.get_items():
+ try:
+ data_queue.put(item, timeout=5)
+ except queue.Full:
+ # 应用反压
+ print("Client is too slow, dropping data")
+ break
+
+ producer_thread = threading.Thread(target=data_producer)
+ producer_thread.start()
+
+ try:
+ while context.is_active():
+ try:
+ item = data_queue.get(timeout=30)
+ yield item
+ except queue.Empty:
+ # 发送心跳或检查客户端连接
+ if not context.is_active():
+ break
+ finally:
+ producer_thread.join(timeout=1)
+```
+
+### 流中的错误处理
+在流式操作中优雅地处理错误:
+
+```python title="stream_error_handling.py"
+def StreamWithErrorHandling(self, request, context):
+ """带健壮错误处理的流式传输。"""
+
+ try:
+ for item in self.get_stream_data(request):
+ if not context.is_active():
+ break
+
+ try:
+ # 处理项目
+ processed_item = self.process_item(item)
+ yield processed_item
+
+ except ProcessingError as e:
+ # 将错误作为响应的一部分发送
+ error_response = create_error_response(e)
+ yield error_response
+
+ except Exception as e:
+ # 严重错误 - 中止流
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Processing failed: {str(e)}')
+ break
+
+ except Exception as e:
+ context.set_code(grpc.StatusCode.INTERNAL)
+ context.set_details(f'Stream failed: {str(e)}')
+```
+
+### 客户端流式传输
+
+在客户端处理流式传输:
+
+```python title="streaming_client.py"
+import grpc
+
+def stream_chat_client():
+ """双向流式传输客户端示例。"""
+
+ channel = grpc.insecure_channel('localhost:50051')
+ stub = streaming_pb2_grpc.StreamingServiceStub(channel)
+
+ def message_generator():
+ """生成出站消息。"""
+ # 发送初始消息
+ yield streaming_pb2.ChatMessage(
+ user_id="user123",
+ room_id="general",
+ content="Hello, world!",
+ type=streaming_pb2.CHAT_MESSAGE_TYPE_TEXT
+ )
+
+ # 保持连接活跃并定期发送消息
+ while True:
+ user_input = input("Enter message: ")
+ if user_input.lower() == 'quit':
+ break
+
+ yield streaming_pb2.ChatMessage(
+ user_id="user123",
+ room_id="general",
+ content=user_input,
+ type=streaming_pb2.CHAT_MESSAGE_TYPE_TEXT
+ )
+
+ # 启动双向流
+ responses = stub.Chat(message_generator())
+
+ try:
+ for response in responses:
+ print(f"Received: {response.content}")
+ except grpc.RpcError as e:
+ print(f"RPC failed: {e}")
+```
+
+gRPC 中的流式传输可实现强大的实时应用程序,同时保持强类型契约和高效二进制协议的优势。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/auth.mdx b/fern/translations/zh/products/api-def/openapi/auth.mdx
new file mode 100644
index 000000000..394972b3b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/auth.mdx
@@ -0,0 +1,272 @@
+---
+title: 身份验证
+description: '为 bearer、basic、API 密钥和 OAuth 等认证方案建模。'
+sidebar-title: 身份验证
+---
+
+Fern 支持两种配置身份验证的方式:
+
+- **在您的 OpenAPI 规范中**使用 `securitySchemes` — 标准方法,使身份验证配置具有可移植性,并与其他 OpenAPI 工具兼容。
+- **在 `generators.yml` 中**使用 `auth-schemes` — 用于自定义参数名称和环境变量,覆盖规范中定义的内容,或配置 OAuth(在 OpenAPI 中不可用)。
+
+您的身份验证配置适用于生成的 SDK 和 [API 浏览器](/learn/docs/api-references/api-explorer)。所有 SDK 都支持凭据的直接配置和环境变量。如果您在两个地方定义了相同的方案,`generators.yml` 优先。
+
+## 在您的规范中配置身份验证
+
+在 `components.securitySchemes` 中定义您的方案,然后使用 `security` 属性全局或按端点应用它们。
+
+```yml title="openapi.yml"
+# 定义方案
+components:
+ securitySchemes:
+ BearerAuth: # 用户定义的方案名称
+ type: http
+ scheme: bearer
+
+# 在所有端点中全局应用
+security:
+ - BearerAuth: []
+```
+
+生成的 SDK 用法:
+
+```ts index.ts
+const client = new Client({
+ token: "ey34..."
+});
+```
+
+
+
+
+```yml title="openapi.yml"
+components:
+ securitySchemes:
+ BearerAuth: # 用户定义的方案名称
+ type: http
+ scheme: bearer
+```
+
+要自定义参数名称和环境变量,请添加 `x-fern-bearer`:
+
+```yaml title="openapi.yml"
+components:
+ securitySchemes:
+ BearerAuth:
+ type: http
+ scheme: bearer
+ x-fern-bearer:
+ name: apiKey
+ env: PLANTSTORE_API_KEY
+```
+
+
+
+
+```yaml title="openapi.yml"
+components:
+ securitySchemes:
+ BasicAuth: # 用户定义的方案名称
+ type: http
+ scheme: basic
+```
+
+要自定义参数名称和环境变量,请添加 `x-fern-basic`:
+
+```yaml title="openapi.yml"
+components:
+ securitySchemes:
+ BasicAuth:
+ type: http
+ scheme: basic
+ x-fern-basic:
+ username:
+ name: clientId
+ env: PLANTSTORE_CLIENT_ID
+ password:
+ name: clientSecret
+ env: PLANTSTORE_CLIENT_SECRET
+```
+
+
+
+
+```yml title="openapi.yml"
+components:
+ securitySchemes:
+ ApiKeyAuth: # 用户定义的方案名称
+ type: apiKey
+ in: header
+ name: X_API_KEY
+```
+
+要自定义参数名称和环境变量,请添加 `x-fern-header`:
+
+```yaml title="openapi.yml"
+components:
+ securitySchemes:
+ ApiKeyAuth:
+ type: apiKey
+ in: header
+ name: X_API_KEY
+ x-fern-header:
+ name: apiToken
+ env: PLANTSTORE_API_KEY
+ prefix: "Token "
+```
+
+
+`prefix` 选项自动为 API 密钥添加字符串前缀,当您的 API 期望 `"Bearer abc123"` 或 `"Token abc123"` 等格式时很有用。
+
+
+
+
+
+### 多种身份验证方案
+
+配置端点以支持多种身份验证方案或组合。在 `security` 部分中,多个顶级项是 OR 选项,而单个项中的方案用 AND 组合。
+
+```yaml title="openapi.yml"
+components:
+ securitySchemes:
+ bearerAuth: # 用户定义的方案名称
+ type: http
+ scheme: bearer
+ basicAuth: # 用户定义的方案名称
+ type: http
+ scheme: basic
+ apiKey: # 用户定义的方案名称
+ type: apiKey
+ in: header
+ name: X-API-Key
+
+paths:
+ /plant/search/status:
+ get:
+ summary: 按状态搜索植物
+ security:
+ - bearerAuth: [] # 选项 1:仅 Bearer 令牌
+ - basicAuth: [] # 选项 2:基本身份验证和 API 密钥
+ apiKey: []
+```
+
+在此示例中,用户可以使用 Bearer 令牌或基本身份验证和 API 密钥一起进行身份验证。
+
+
+当使用 OAuth 客户端凭据与多种方案时,确保您的 OpenAPI 规范 `security` 部分中的方案名称与 `generators.yml` 中定义的名称匹配。
+
+
+## 在 `generators.yml` 中自定义或覆盖身份验证
+
+在 [`auth-schemes`](/learn/sdks/reference/generators-yml#auth-schemes) 中定义您的方案,然后使用 [`api.auth`](/learn/sdks/reference/generators-yml#auth) 将其作为所有端点的默认值应用:
+
+```yml title="generators.yml"
+# 定义方案
+auth-schemes:
+ BearerAuth: # 用户定义的方案名称
+ scheme: bearer
+ token:
+ name: apiKey
+ env: PLANTSTORE_API_KEY
+
+# 将其作为所有端点的默认值应用
+api:
+ auth: BearerAuth
+ specs:
+ - openapi: ./openapi.yml
+```
+
+有关完整的配置选项,请参阅 [`auth-schemes` 参考](/learn/sdks/reference/generators-yml#auth-schemes)。您还可以为[特定 SDK](/learn/sdks/reference/generators-yml#override-api-authentication-settings) 覆盖身份验证设置。
+
+
+生成的 SDK 用法:
+
+```ts index.ts
+// 使用 process.env.PLANTSTORE_API_KEY
+const client = new PlantStoreClient();
+
+// 或显式提供
+const client = new PlantStoreClient({
+ apiKey: "your-api-key"
+});
+```
+
+
+
+
+```yaml title="generators.yml"
+auth-schemes:
+ BearerAuth: # 用户定义的方案名称
+ scheme: bearer
+ token:
+ name: apiKey
+ env: MY_API_KEY
+```
+
+
+
+
+```yaml title="generators.yml"
+auth-schemes:
+ BasicAuth: # 用户定义的方案名称
+ scheme: basic
+ username:
+ name: clientId
+ env: MY_CLIENT_ID
+ password:
+ name: clientSecret
+ env: MY_CLIENT_SECRET
+```
+
+
+
+
+```yaml title="generators.yml"
+auth-schemes:
+ ApiKeyAuth: # 用户定义的方案名称
+ header: X-API-Key
+ name: apiKey
+ env: MY_API_KEY
+ prefix: "Token "
+```
+
+
+
+
+
+此功能在[专业版和企业版计划](https://buildwithfern.com/pricing)中提供。请联系 support@buildwithfern.com 开始使用。
+
+
+```yaml title="generators.yml"
+auth-schemes:
+ OAuth: # 用户定义的方案名称
+ scheme: oauth
+ type: client-credentials
+ client-id-env: OAUTH_CLIENT_ID
+ client-secret-env: OAUTH_CLIENT_SECRET
+ get-token:
+ endpoint: "POST /oauth/token"
+ request-properties:
+ client-id: client_id
+ client-secret: client_secret
+ response-properties:
+ access-token: access_token
+ expires-in: expires_in
+ refresh-token: refresh_token
+ refresh-token:
+ endpoint: "POST /oauth/refresh"
+ request-properties:
+ refresh-token: refresh_token
+ response-properties:
+ access-token: access_token
+ expires-in: expires_in
+```
+
+`endpoint` 值引用您的 OpenAPI 规范中的路径。当返回 `expires-in` 时,SDK 会在令牌过期前自动刷新令牌。
+
+
+如果您的 API 使用[命名空间](/learn/api-definitions/overview/project-structure#combined-sdks-from-multiple-apis)(多个 API 规范),请在端点前加上命名空间和 `::`。例如,`"payments::POST /oauth/token"`。
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/automation.mdx b/fern/translations/zh/products/api-def/openapi/automation.mdx
new file mode 100644
index 000000000..e4bf2b2ee
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/automation.mdx
@@ -0,0 +1,63 @@
+---
+title: 同步您的 OpenAPI 规范
+subtitle: 自动将最新的 OpenAPI 规范拉取到您的 Fern 文件夹中。
+sidebar-title: 同步您的 OpenAPI 规范
+---
+
+使用 [sync-openapi GitHub Action](https://github.com/fern-api/sync-openapi) 自动从公开可用的 URL 将最新的 OpenAPI 规范拉取到您的 fern 文件夹中。这样可以让您提交的规范与实时 API 保持同步,无需手动更新。
+
+## 设置
+
+
+ 在您的 `generators.yml` 中添加 `origin` 字段,指定您的 OpenAPI 规范托管位置:
+
+ ```yml title="generators.yml"
+ api:
+ specs:
+ - openapi: .path/to/openapi.json # 定义文件
+ overrides: .path/to-openapi-overrides.yml # 覆盖文件
+ origin: https://api.example.com/openapi.json # 获取最新规范的 URL
+ ```
+
+
+ 在您的仓库中创建 `.github/workflows/sync-openapi.yml`。此操作使用 [`fern api update`](/cli-api-reference/cli-reference/commands#fern-api-update) 从您的 `generators.yml` 文件中的 `origin` 字段拉取最新版本的 OpenAPI 规范。
+
+ ```yml title=".github/workflows/sync-openapi.yml"
+ name: Sync OpenAPI Specs # 可以自定义
+ on: # 可以配置其他自定义触发器
+ workflow_dispatch: # 手动触发
+ push:
+ branches:
+ - main # 推送到主分支时触发
+ schedule:
+ - cron: '0 3 * * *' # 每日 UTC 时间凌晨 3:00
+ jobs:
+ update-from-source:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.OPENAPI_SYNC_TOKEN }}
+ - name: Update API with Fern
+ uses: fern-api/sync-openapi@v2
+ with:
+ update_from_source: true
+ token: ${{ secrets.OPENAPI_SYNC_TOKEN }}
+ branch: 'update-api'
+ auto_merge: false
+ add_timestamp: true
+```
+
+
+ 生成一个 [细粒度个人访问令牌](https://github.com/settings/personal-access-tokens),为您的仓库授予 **Contents** 和 **Pull requests** 读写权限。
+
+
+ 在您的仓库中,转到 `Settings > Secrets and variables > Actions`。点击 **New repository secret**,将其命名为 `OPENAPI_SYNC_TOKEN`,粘贴您的令牌,然后点击 **Add secret**。
+
+
+
+这将创建包含任何 API 规范更新的每日拉取请求。要更改频率,请修改 `cron` 计划(参见 GitHub 的 [计划语法](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#schedule))。
+
+## 其他用例
+
+如果您的 OpenAPI 规范位于不同的仓库中(而不是在公共 URL),您可以使用显式文件映射将其同步到您的 Fern 文件夹。有关此操作和其他高级配置,请参见 [sync-openapi GitHub Action README](https://github.com/fern-api/sync-openapi)。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/endpoints/multipart.mdx b/fern/translations/zh/products/api-def/openapi/endpoints/multipart.mdx
new file mode 100644
index 000000000..c5baa9abf
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/endpoints/multipart.mdx
@@ -0,0 +1,74 @@
+---
+title: 多部分文件上传
+subtitle: 使用 `multipart/form-data` 内容类型记录端点
+sidebar-title: 多部分文件上传
+---
+
+多部分请求将一个或多个数据集组合到单个请求体中,通过边界分隔。
+您通常使用这些请求进行文件上传,以及在单个请求中传输多种类型的数据
+(例如,文件和 JSON 对象一起传输)。
+
+```yml title="openapi.yml" maxLines=0 {12-24}
+paths:
+ /upload:
+ post:
+ summary: Upload a file
+ description: Upload a file using multipart/form-data encoding
+ operationId: uploadFile
+ tags:
+ - file
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ file:
+ type: string
+ format: binary
+ description: The file to upload
+ description:
+ type: string
+ description: A description of the file (optional)
+ required:
+ - file
+ responses:
+ "200":
+ description: Successful upload
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ message:
+ type: string
+ fileId:
+ type: string
+```
+
+任何使用 `multipart/form-data` 内容类型定义的请求体都将被视为多部分请求。在给定的多部分请求中,具有 `format:binary` 的字符串参数将表示任意文件。
+
+## 文件数组
+
+如果您的端点支持文件数组,那么您的请求体必须使用数组类型。
+
+```yml openapi.yml {12-17}
+paths:
+ /upload:
+ post:
+ summary: Upload multiple files
+ operationId: uploadFiles
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ properties:
+ files:
+ type: array
+ items:
+ type: string
+ format: binary
+ description: An array of files to upload
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/endpoints/rest.mdx b/fern/translations/zh/products/api-def/openapi/endpoints/rest.mdx
new file mode 100644
index 000000000..4d1f631d4
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/endpoints/rest.mdx
@@ -0,0 +1,65 @@
+---
+title: HTTP JSON 端点
+subtitle: 使用 `application/json` 内容类型记录 HTTP JSON API
+sidebar-title: HTTP JSON 端点
+---
+
+OpenAPI 中的端点定义在 `paths` 键下。以下是定义单个端点的示例:
+
+```yml title="openapi.yml" maxLines=0 {2-18}
+paths:
+ /pets:
+ post:
+ summary: Create a new pet
+ description: Creates a new pet with the provided information
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ responses:
+ '200':
+ description: User created successfully
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+```
+
+## 示例
+
+您可以通过使用 `examples` 键来提供请求和响应的示例。
+
+```yaml title="openapi.yml" {12-17,25-30}
+paths:
+ /pets:
+ post:
+ summary: Create a new pet
+ description: Creates a new pet with the provided information
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ examples:
+ PetExample:
+ summary: This is an example of a Pet
+ value:
+ name: Markley
+ id: 44
+ responses:
+ '200':
+ description: A Pet object
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ examples:
+ PetExample:
+ summary: This is an example of a Pet
+ value:
+ name: Markley
+ id: 44
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/endpoints/sse.mdx b/fern/translations/zh/products/api-def/openapi/endpoints/sse.mdx
new file mode 100644
index 000000000..da676eade
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/endpoints/sse.mdx
@@ -0,0 +1,124 @@
+---
+title: 服务器发送事件和流式 API
+subtitle: 使用 `x-fern-streaming` 扩展来建模流式端点
+sidebar-title: 服务器发送事件和流式 API
+---
+
+
+`x-fern-streaming` 扩展允许您表示流式端点。
+
+## JSON 流式传输
+
+如果您的 API 返回一系列 `JSON` 块,如下所示
+
+```json
+{ "text": "Hi, I am a" }
+{ "text": "chatbot. Do you have any"}
+{ "text": "questions for me"}
+```
+
+那么只需在您的 OpenAPI 操作中添加 `x-fern-streaming: true`。
+
+```yaml title="openapi.yml" {4}
+paths:
+ /logs:
+ post:
+ x-fern-streaming: true
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Chat"
+components:
+ schemas:
+ Chat:
+ type: object
+ properties:
+ text:
+ type: string
+```
+
+## 服务器发送事件
+
+
+
+如果您的 API 返回服务器发送事件 (SSE),包含 `data` 和 `event` 键,如下所示
+
+```json
+data: { "text": "Hi, I am a" }
+data: { "text": "chatbot. Do you have any"}
+data: { "text": "questions for me"}
+```
+
+那么确保包含 `format: sse`。
+
+```yaml title="openapi.yml" {4-5}
+paths:
+ /logs:
+ post:
+ x-fern-streaming:
+ format: sse
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Chat"
+components:
+ schemas:
+ Chat:
+ type: object
+ properties:
+ text:
+ type: string
+```
+
+### 终止消息
+
+一些 SSE API 会发送独立的终止消息来表示流传输完成。例如,
+OpenAI 的 API 发送 `[DONE]` 作为最终消息。您可以使用 `terminator` 字段来指定:
+
+```yaml title="openapi.yml" {4-6}
+paths:
+ /logs:
+ post:
+ x-fern-streaming:
+ format: sse
+ terminator: "[DONE]"
+# ... responses and schemas
+```
+
+## `Stream` 参数
+
+端点拥有一个 `stream` 参数来控制响应是否为流式传输已成为常见做法。Fern 以一等公民的方式支持这种模式。
+
+只需指定 `stream-condition` 以及普通响应和流式响应:
+
+```yaml title="openapi.yml" {4-11}
+paths:
+ /logs:
+ post:
+ x-fern-streaming:
+ format: sse
+ terminator: "[DONE]"
+ stream-condition: $request.stream
+ response:
+ $ref: '#/components/schemas/Chat'
+ response-stream:
+ $ref: '#/components/schemas/ChatChunk'
+components:
+ schemas:
+ Chat:
+ type: object
+ properties:
+ text:
+ type: string
+ tokens:
+ type: number
+ ChatChunk:
+ type: object
+ properties:
+ text:
+ type: string
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/api-version.mdx b/fern/translations/zh/products/api-def/openapi/extensions/api-version.mdx
new file mode 100644
index 000000000..690b695f4
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/api-version.mdx
@@ -0,0 +1,19 @@
+---
+title: API 版本
+headline: API 版本 (OpenAPI)
+description: 使用 `x-fern-version` 扩展配置 API 版本方案和请求头
+sidebar-title: API 版本
+---
+
+您可以定义您的 API 版本方案,例如 `X-API-Version` 请求头。支持的版本和默认值按如下方式指定:
+
+```yaml title="openapi.yaml"
+x-fern-version:
+ header: X-API-Version
+ default: "2.0.0"
+ values:
+ - "1.0.0"
+ - "2.0.0"
+ - "latest"
+paths: ...
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/audiences.mdx b/fern/translations/zh/products/api-def/openapi/extensions/audiences.mdx
new file mode 100644
index 000000000..4c347fcf7
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/audiences.mdx
@@ -0,0 +1,148 @@
+---
+title: 使用受众筛选您的 API
+headline: 使用受众筛选您的 API (OpenAPI)
+subtitle: 了解如何使用 x-fern-audiences 为不同的 API 消费者(如公共用户和 beta 用户)筛选 OpenAPI 端点、模式和属性。
+sidebar-title: 使用受众筛选 API
+---
+
+
+
+
+Fern 提供两种方式来筛选哪些 API 元素会出现在您的 SDK 和 API 参考文档中:
+
+- **`audiences`(基于标签的筛选):** 为特定端点、模式或属性标记受众标签,然后将 SDK 和文档筛选到这些标签。最适合基于用户类型(公共 vs beta、免费 vs 企业版)或功能成熟度创建变体,无论 URL 结构如何。
+
+- **`settings.filter`(基于路径的筛选):** 筛选整个 URL 路径或模式。最适合您的 API 组织自然按 URL 划分的情况(如 `/v1/*` vs `/v2/*`,或 `/admin/*` vs `/user/*`)。配置详细信息请参见 [`settings.filter` 参考](/learn/sdks/reference/generators-yml#openapi)。
+
+许多团队同时使用这两种方法:基于路径的筛选用于主要划分,受众标签用于这些划分内的精细控制。
+
+## 基于路径的筛选
+
+在您的 `generators.yml` 中使用 [`settings.filter`](/learn/api-definitions/openapi/generators-yml-reference#settingsfilter) 来限制哪些端点会根据其路径包含在生成的 SDK 或 API 参考中:
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: "./openapi.yml"
+ settings:
+ filter:
+ endpoints: ["POST /users", "GET /users/{id}"]
+```
+
+## 基于标签的筛选(受众)
+
+在您的 OpenAPI 规范中应用受众标签,然后配置您的 SDK 或 API 参考来筛选到这些受众。
+
+
+
+
+
+
+
+将 `x-fern-server-name` 和 `x-fern-audiences` 扩展添加到相关服务器。
+
+在下面的示例中,`Production` 服务器仅对公共消费者可用:
+
+```yaml title="openapi.yml" {3-5}
+servers:
+ - url: https://api.com
+ x-fern-server-name: Production
+ x-fern-audiences:
+ - public
+```
+
+
+
+将 `x-fern-audiences` 扩展添加到相关端点。
+
+在下面的示例中,`POST /users/sendEmail` 端点仅对公共消费者可用:
+
+```yaml title="openapi.yml" {4-5}
+paths:
+ /users/sendEmail:
+ post:
+ x-fern-audiences:
+ - public
+ operationId: send_email
+```
+
+
+
+将 `x-fern-audiences` 扩展添加到相关模式。
+
+在此示例中,`Email` 类型对公共和 beta 客户都可用。
+
+```yaml title="openapi.yml" {13-15}
+components:
+ schemas:
+ Email:
+ title: Email
+ type: object
+ properties:
+ subject:
+ type: string
+ body:
+ type: string
+ to:
+ type: string
+ x-fern-audiences:
+ - public
+ - beta
+```
+
+
+
+将 `x-fern-audiences` 扩展添加到相关属性。
+
+在此示例中,`to` 属性仅对 beta 客户可用。
+
+```yaml title="openapi.yml" {13-17}
+components:
+ schemas:
+ Email:
+ title: Email
+ type: object
+ properties:
+ subject:
+ type: string
+ body:
+ type: string
+ to:
+ type: string
+ x-fern-audiences:
+ - beta
+```
+
+
+
+
+
+指定要包含在您的 SDK 或 API 参考文档中的受众。如果**没有指定受众**,所有标记的元素都将包含在您的 SDK 中,无论其受众标签如何。
+
+
+
+以下示例配置 SDK 筛选到 `public` 受众:
+
+```yaml title="generators.yml" {3-4}
+groups:
+ sdks:
+ audiences:
+ - public
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+
+以下示例配置文档筛选到 `public` 受众:
+
+```yaml title="docs.yml" {3-4}
+navigation:
+ - api: API Reference
+ audiences:
+ - public
+```
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/availability.mdx b/fern/translations/zh/products/api-def/openapi/extensions/availability.mdx
new file mode 100644
index 000000000..745f72f70
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/availability.mdx
@@ -0,0 +1,38 @@
+---
+title: 可用性
+headline: 可用性 (OpenAPI)
+sidebar-title: 可用性
+description: 在 OpenAPI 中使用 `x-fern-availability` 标记 API 端点可用性。为端点和章节设置 beta、已弃用、稳定等状态。
+---
+
+
+`x-fern-availability` 扩展用于在 OpenAPI 定义中标记端点的可用性。可用性信息会传播到生成的 Fern Docs 网站中,显示为可视化标签。
+
+您可以在 [`docs.yml` 文件](/learn/docs/configuration/site-level-settings)中配置 API Reference 文档中章节的 `availability`。
+
+## 端点
+
+选项包括:
+
+- `beta`
+- `generally-available`
+- `deprecated`
+
+下面的示例将 `POST /pet` 端点标记为 `deprecated`。
+
+```yaml title="openapi.yml 中的 x-fern-availability" {4}
+paths:
+ /pet:
+ post:
+ x-fern-availability: deprecated
+```
+
+渲染效果如下:
+
+
+
+
+
+## 章节
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/base-path.mdx b/fern/translations/zh/products/api-def/openapi/extensions/base-path.mdx
new file mode 100644
index 000000000..3fc8c0a00
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/base-path.mdx
@@ -0,0 +1,19 @@
+---
+title: 基础路径
+headline: 基础路径(OpenAPI)
+description: 使用 `x-fern-base-path` 在 OpenAPI 中配置基础路径。为您的 API 定义设置端点前缀,如 /v1,配合 Fern 使用。
+sidebar-title: 基础路径
+---
+
+使用 `x-fern-base-path` 扩展来配置添加到每个端点前面的基础路径。
+
+下面的示例配置了 `/v1` 基础路径,因此完整的端点路径是
+`https://api.example.com/v1/users`。
+
+```yaml title="在 openapi.yml 中设置基础路径" {1}
+x-fern-base-path: /v1
+servers:
+ - url: https://api.example.com
+paths:
+ /users: ...
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/default.mdx b/fern/translations/zh/products/api-def/openapi/extensions/default.mdx
new file mode 100644
index 000000000..e35c234be
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/default.mdx
@@ -0,0 +1,77 @@
+---
+title: 默认值
+headline: 默认值 (OpenAPI)
+description: 使用 `x-fern-default` 为生成的 SDK 中的路径、头部和查询参数设置客户端默认值。
+sidebar-title: 默认值
+---
+
+`x-fern-default` 扩展允许您为路径、头部或查询参数指定客户端默认值,包括在 [`x-fern-global-headers`](/learn/api-definitions/openapi/extensions/global-headers) 下定义的头部。当存在时,生成的 SDK 会使参数变为可选的,并在调用方省略该参数时自动发送默认值。`x-fern-default` 支持 `string` 和 `boolean` 值;其他类型(如数字)会被忽略。
+
+这对于固定 API 版本头部或区域路径参数非常有用,同时仍允许调用方覆盖该值。
+
+
+ `x-fern-default` 支持 TypeScript、Python、Go、Java、C#、PHP 和 Ruby SDK。
+
+
+## 路径参数
+
+在下面的示例中,当调用方未指定 `region` 时,SDK 会发送 `us-east-1`。
+
+```yaml {9} title="openapi.yml"
+paths:
+ /regions/{region}/resources:
+ get:
+ operationId: list_resources
+ parameters:
+ - name: region
+ in: path
+ required: true
+ x-fern-default: "us-east-1"
+ schema:
+ type: string
+```
+
+## 头部
+
+在下面的示例中,当调用方未指定 `X-API-Version` 时,SDK 会发送 `2024-02-08`。
+
+```yaml {8} title="openapi.yml"
+paths:
+ /users:
+ get:
+ operationId: list_users
+ parameters:
+ - name: X-API-Version
+ in: header
+ x-fern-default: "2024-02-08"
+ schema:
+ type: string
+```
+
+## 查询参数
+
+在下面的示例中,当调用方未指定 `verbose` 时,SDK 会发送 `false`。
+
+```yaml {8} title="openapi.yml"
+paths:
+ /search:
+ get:
+ operationId: search
+ parameters:
+ - name: verbose
+ in: query
+ x-fern-default: false
+ schema:
+ type: boolean
+```
+
+## 全局头部
+
+在下面的示例中,当调用方未指定 `X-API-Version` 全局头部时,SDK 会发送 `2024-02-08`。
+
+```yaml {4} title="openapi.yml"
+x-fern-global-headers:
+ - header: X-API-Version
+ name: version
+ x-fern-default: "2024-02-08"
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/enums.mdx b/fern/translations/zh/products/api-def/openapi/extensions/enums.mdx
new file mode 100644
index 000000000..79833b4bd
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/enums.mdx
@@ -0,0 +1,97 @@
+---
+title: 枚举描述、名称、大小写和可用性
+headline: 枚举描述、名称、大小写和可用性(OpenAPI)
+description: 使用 `x-fern-enum` 扩展为 OpenAPI 枚举值添加描述、自定义名称、按语言的大小写覆盖和弃用状态。
+sidebar-title: 枚举描述、名称、大小写和可用性
+---
+
+OpenAPI 原生不支持为枚举值添加描述。要在 Fern 中实现此功能,您可以使用 `x-fern-enum` 扩展。
+
+## 描述和可用性
+
+使用 `description` 为单个枚举值添加文档,使用 `deprecated` 将值标记为已弃用而不会弃用整个枚举。这些设置会传播到生成的 SDK 和文档网站中。
+
+```yaml title="openapi.yml" {11, 13-14, 16, 18}
+components:
+ schemas:
+ CardSuit:
+ enum:
+ - clubs
+ - diamonds
+ - hearts
+ - spades
+ x-fern-enum:
+ clubs:
+ description: 梅花花色
+ diamonds:
+ description: "已弃用。请使用红心。"
+ deprecated: true
+ hearts:
+ description: 红心花色
+ spades:
+ description: 黑桃花色
+```
+
+## 自定义名称
+
+使用 `name` 字段自定义生成代码中枚举值的名称。当枚举值依赖符号字符而可能导致生成的代码无法编译时,这特别有用。
+
+例如,以下 OpenAPI:
+
+```yaml title="openapi.yml" {9,12}
+components:
+ schemas:
+ Operand:
+ enum:
+ - '>'
+ - '<'
+ x-fern-enum:
+ '>':
+ name: GreaterThan
+ description: 检查值是否大于
+ '<':
+ name: LessThan
+ description: 检查值是否小于
+```
+
+将生成:
+
+```typescript title="operand.ts"
+export enum Operand {
+ GreaterThan = ">",
+ LessThan = "<"
+}
+```
+
+## 自定义大小写
+
+使用 `casing` 字段为每个目标语言的命名约定指定确切的大小写。这比仅使用 `name` 提供了更精细的控制,后者只为生成的代码设置单个默认名称。
+
+`casing` 字段支持四个可选的子字段:
+
+- `snake` — snake_case 的覆盖(用于 Python 等语言)
+- `camel` — camelCase 的覆盖(用于 TypeScript/Java 等语言)
+- `screamingSnake` — SCREAMING_SNAKE_CASE 的覆盖(用于 Go 等语言)
+- `pascal` — PascalCase 的覆盖(用于 C# 等语言)
+
+```yaml title="openapi.yml" {13-17}
+components:
+ schemas:
+ Status:
+ type: string
+ enum:
+ - active
+ - in-progress
+ x-fern-enum:
+ active:
+ description: 项目处于活动状态
+ in-progress:
+ name: InProgress
+ casing:
+ snake: in_progress
+ camel: inProgress
+ screamingSnake: IN_PROGRESS
+ pascal: InProgress
+```
+
+您可以将 `casing` 与 `name` 一起使用。`name` 字段设置默认生成的名称,而 `casing` 提供按语言的覆盖。如果两者都指定,`casing` 值对其各自的语言目标具有优先级。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/examples.mdx b/fern/translations/zh/products/api-def/openapi/extensions/examples.mdx
new file mode 100644
index 000000000..0fa22079b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/examples.mdx
@@ -0,0 +1,74 @@
+---
+title: 请求 + 响应示例
+headline: 请求 + 响应示例(OpenAPI)
+description: 使用 x-fern-examples 配置 OpenAPI 请求和响应示例。在您的 API 定义中关联路径参数、查询参数和响应。
+sidebar-title: 请求 + 响应示例
+og:title: OpenAPI 请求 + 响应示例
+---
+
+
+
+Fern 使用 [AI 生成的示例](/learn/docs/ai-features/ai-examples) 自动生成真实的示例,默认启用。使用 `x-fern-examples` 手动定义特定的示例值。手动示例优先于 AI 生成的示例。您也可以[完全禁用 AI 示例](/learn/docs/configuration/site-level-settings#ai-examplesenabled)。
+
+
+当您需要关联特定的请求和响应对,或为端点定义多个命名示例时,请使用 `x-fern-examples`。虽然 OpenAPI 有多个示例字段,但它无法将请求与其对应的响应关联起来。如果您需要您的示例与非 Fern 的 OpenAPI 工具兼容,请使用 [`fern api enrich`](/learn/cli-api-reference/cli-reference/commands#fern-api-enrich) 将 `x-fern-examples` 转换为原生 OpenAPI 示例字段。
+
+`x-fern-examples` 是一个数组,其中每个元素可以包含关联的 `path-parameters`、`query-parameters`、`request` 和 `response` 值。可选地,添加 `name` 字段为每个示例提供描述性标签。
+
+如果您[通过 `x-fern-global-headers` 扩展定义了全局标头](/api-definitions/openapi/extensions/global-headers),您必须在示例中包含这些标头。
+
+```yaml title="openapi.yml" {4-21}
+paths:
+ /users/{userId}:
+ get:
+ x-fern-examples:
+ - name: Headers example # 可选的描述性标签
+ headers:
+ custom_api_key: "capi_12345" # 使用 x-global-header 扩展定义的标头
+ userpool_id: "pool_67890" # 使用 x-global-header 扩展定义的标头
+ - name: Get user 1234
+ path-parameters:
+ userId: user-1234
+ response:
+ body:
+ name: Foo
+ ssn: 1234
+ - path-parameters:
+ userId: user-4567
+ response:
+ body:
+ name: Foo
+ ssn: 4567
+components:
+ schemas:
+ User:
+ type: object
+ properties:
+ name:
+ type: string
+ ssn:
+ type: integer
+```
+
+### 代码示例
+
+Fern 生成器会自动添加 SDK 代码示例。如果您想为示例指定自定义代码示例,请使用 `code-samples`。
+
+```yaml title="openapi.yml" {11-16}
+paths:
+ /users/{userId}:
+ get:
+ x-fern-examples:
+ - path-parameters:
+ userId: user-1234
+ response:
+ body:
+ name: Foo
+ ssn: 1234
+ code-samples:
+ - sdk: typescript
+ code: |
+ import { UserClient } from "...";
+
+ client.users.get("user-1234")
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/explorer.mdx b/fern/translations/zh/products/api-def/openapi/extensions/explorer.mdx
new file mode 100644
index 000000000..2adceddb5
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/explorer.mdx
@@ -0,0 +1,59 @@
+---
+title: API Explorer 控制
+headline: API Explorer 控制 (OpenAPI)
+description: 使用 `x-fern-explorer` 启用或禁用 API Explorer
+sidebar-title: API Explorer 控制
+---
+
+[API Explorer](/learn/docs/api-references/api-explorer) 默认为所有端点启用。使用 `x-fern-explorer` 全局禁用或按操作覆盖。这通常用于对破坏性操作、支付处理或仅限管理员的端点禁用 Explorer。
+
+## 全局
+
+要为整个 API 禁用 API Explorer,请在根级别添加 `x-fern-explorer`:
+
+```yaml title="openapi.yml" {2}
+openapi: 3.0.2
+x-fern-explorer: false # 为所有端点禁用 Explorer
+info:
+ title: My API
+ version: 1.0.0
+paths:
+ /payments:
+ get:
+ operationId: list_payments
+```
+
+## 端点
+
+要控制各个端点的 API Explorer,请使用 `x-fern-explorer`:
+
+```yaml title="openapi.yml" {4,9}
+paths:
+ /payments:
+ get:
+ x-fern-explorer: true # 为安全的读取操作启用 Explorer
+ /payments/charge:
+ post:
+ x-fern-explorer: false # 禁用以防止意外交易
+```
+
+## 结合全局和端点级别设置
+
+您可以结合使用两种扩展来全局设置默认行为并为特定端点覆盖:
+
+```yaml title="openapi.yml" {2,10}
+openapi: 3.0.2
+x-fern-explorer: false # 全局禁用 Explorer
+info:
+ title: My API
+ version: 1.0.0
+paths:
+ /payments:
+ get:
+ operationId: list_payments
+ x-fern-explorer: true # 为安全的读取操作启用 Explorer
+ /payments/charge:
+ post:
+ operationId: charge_payment
+ # 保持禁用(应用全局设置)
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/global-headers.mdx b/fern/translations/zh/products/api-def/openapi/extensions/global-headers.mdx
new file mode 100644
index 000000000..f2ab7cbbf
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/global-headers.mdx
@@ -0,0 +1,73 @@
+---
+title: 全局请求头
+headline: 全局请求头 (OpenAPI)
+description: 使用 `x-fern-global-headers` 扩展配置在所有端点中使用的请求头
+sidebar-title: 全局请求头
+---
+
+有时,您的 API 会在每个端点或大部分端点中使用某些请求头,我们称之为"全局请求头"。为了方便起见,生成的 Fern SDK 提供了"全局请求头"功能,可以轻松地在 API 调用中更新它们。以 API 密钥为例,如果我们将 API 密钥声明为全局请求头,用户将能够轻松地插入他们的密钥:
+
+```python
+import os
+
+class Client:
+
+ def __init__(self, *, apiKey: str):
+```
+
+Fern 会自动提取在每个请求或大多数请求中使用的请求头,并将它们标记为全局的。
+
+## 在您的 OpenAPI 规范中
+
+要将其他请求头标记为全局的,或为全局请求头设置别名,请使用 `x-fern-global-headers` 扩展:
+
+```yaml title="openapi.yml"
+x-fern-global-headers:
+ - header: custom_api_key
+ name: api_key
+ - header: userpool_id
+ optional: true
+```
+
+
+ 当您使用 `x-fern-global-headers` 定义全局请求头时,您必须[在 `x-fern-examples` 中包含它们](/api-definitions/openapi/extensions/request-response-examples)。
+
+
+### 默认值
+
+使用 [`x-fern-default`](/learn/api-definitions/openapi/extensions/default-values) 为全局请求头设置客户端默认值。生成的 SDK 会将请求头设置为可选,并在调用者省略时发送默认值:
+
+```yaml {4} title="openapi.yml"
+x-fern-global-headers:
+ - header: X-API-Version
+ name: version
+ x-fern-default: "2024-02-08"
+```
+
+## 在 `generators.yml` 中
+
+或者,您可以将请求头添加到[`generators.yml` 文件中的 `api` 块](/learn/sdks/reference/generators-yml#headers):
+
+```yaml title="generators.yml"
+api:
+ - openapi: ./path/to/openapi
+ headers:
+ custom_api_key:
+ name: api_key
+ type: string
+ userpool_id:
+ name: userpool_id
+ type: optional
+```
+
+## 生成的 SDK 行为
+
+两种配置都会产生以下客户端代码:
+
+```python
+import os
+
+class Client:
+
+ def __init__(self, *, apiKey: str, userpoolId: typing.Optional[str])
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/idempotency-headers.mdx b/fern/translations/zh/products/api-def/openapi/extensions/idempotency-headers.mdx
new file mode 100644
index 000000000..cfa872f40
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/idempotency-headers.mdx
@@ -0,0 +1,60 @@
+---
+title: 幂等性
+headline: 幂等性 (OpenAPI)
+description: 使用 x-fern-idempotency-headers 和 x-fern-idempotent 扩展配置幂等性,实现安全的请求重试
+sidebar-title: 幂等性
+---
+
+
+
+
+Fern 通过两个协同工作的扩展支持幂等性配置:`x-fern-idempotency-headers` 配置您的 API 使用的幂等性头部,`x-fern-idempotent` 将单个端点标记为幂等的。配置后,Fern 生成的 SDK 允许用户指定幂等性头部以进行安全的请求重试。
+
+## 配置幂等性头部
+
+在 OpenAPI 规范的根级别添加 `x-fern-idempotency-headers` 扩展,以定义您的 API 用于幂等性的头部:
+
+```yaml title="openapi.yml"
+x-fern-idempotency-headers:
+ - header: Idempotency-Key
+ name: idempotency_key
+ - header: Idempotency-Expiration
+ name: idempotency_expiration
+```
+
+每个幂等性头部支持以下属性:
+
+| 属性 | 描述 |
+| --- | --- |
+| `header` | HTTP 头部名称(例如:`Idempotency-Key`) |
+| `name` | 生成的 SDK 中使用的参数名称(例如:`idempotency_key`) |
+
+## 将端点标记为幂等的
+
+在单个端点上添加 `x-fern-idempotent` 扩展并将其设置为 `true`,以将它们标记为幂等的:
+
+```yaml title="openapi.yml" {1-3,8}
+x-fern-idempotency-headers:
+ - header: Idempotency-Key
+ name: idempotency_key
+
+paths:
+ /plants:
+ post:
+ x-fern-idempotent: true
+ operationId: create_plant
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ species:
+ type: string
+ responses:
+ '201':
+ description: Plant created successfully
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/ignore.mdx b/fern/translations/zh/products/api-def/openapi/extensions/ignore.mdx
new file mode 100644
index 000000000..18f6c32c9
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/ignore.mdx
@@ -0,0 +1,74 @@
+---
+title: 忽略元素
+headline: 忽略元素 (OpenAPI)
+description: 使用 x-fern-ignore 从您的 OpenAPI 规范中排除端点、模式、属性或参数。控制 Fern 读取和处理的内容。
+sidebar-title: 忽略元素
+---
+
+如果您希望 Fern 跳过读取任何端点、模式、属性或参数,请使用 `x-fern-ignore` 扩展。
+
+## 忽略端点
+
+要跳过端点,请在操作级别添加 `x-fern-ignore: true`。
+
+```yaml title="openapi.yml 中操作级别的 x-fern-ignore" {4}
+paths:
+ /users:
+ get:
+ x-fern-ignore: true
+ ...
+```
+## 忽略模式
+
+要跳过模式,请在模式级别添加 `x-fern-ignore: true`。
+
+```yaml title="openapi.yml 中模式级别的 x-fern-ignore" {4}
+components:
+ schemas:
+ SchemaToSkip:
+ x-fern-ignore: true
+ ...
+```
+
+## 忽略属性
+要跳过模式中的属性,请在属性级别添加 `x-fern-ignore: true`。
+
+```yaml title="openapi.yml 中属性级别的 x-fern-ignore" {9}
+components:
+ schemas:
+ User:
+ type: object
+ properties:
+ name:
+ type: string
+ internalField:
+ x-fern-ignore: true
+ type: string
+```
+
+## 忽略参数
+
+要跳过参数,请在参数级别添加 `x-fern-ignore: true`。
+```yaml title="openapi.yml 中参数级别的 x-fern-ignore" {7}
+paths:
+ /users:
+ get:
+ parameters:
+ - name: internalParam
+ in: query
+ x-fern-ignore: true
+ schema:
+ type: string
+```
+
+
+要在不修改基础规范的情况下跳过参数,请在您的[覆盖文件](/learn/api-definitions/openapi/overrides)中使用 `null` 值来删除参数:
+
+```yaml title="overrides.yml" {5}
+paths:
+ /users:
+ get:
+ parameters:
+ - null # 从基础规范中删除第一个参数
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/method-names.mdx b/fern/translations/zh/products/api-def/openapi/extensions/method-names.mdx
new file mode 100644
index 000000000..b102d2922
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/method-names.mdx
@@ -0,0 +1,53 @@
+---
+title: 自定义 SDK 方法名
+headline: 自定义 SDK 方法名 (OpenAPI)
+description: 使用 `x-fern-sdk-method-name` 和 `x-fern-sdk-group-name` 来精细调整 SDK 命名。
+sidebar-title: 自定义 SDK 方法名
+---
+
+使用 `x-fern-sdk-group-name` 和 `x-fern-sdk-method-name` 扩展来控制端点在 SDK 中的组织方式。
+
+
+ 如果没有扩展存在,Fern 使用您的操作 ID 来生成 SDK 方法名。将操作 ID 格式化为 `{tag_name}_{operation_name}`(例如:`users_get`)来自动生成像 `users.get()` 这样的方法。如果操作 ID 不以标签开头,Fern 将直接使用它作为方法名。
+
+
+在下面的示例中,Fern 将为 `POST /users` 端点生成一个名为 `client.users.create()` 的方法。
+
+```yaml title="openapi.yaml" {4-5}
+paths:
+ /users:
+ post:
+ x-fern-sdk-group-name: users
+ x-fern-sdk-method-name: create
+```
+
+### 顶级方法
+
+如果您省略 `x-fern-sdk-group-name` 扩展,生成的 SDK 方法将位于客户端的根级别,而不是嵌套在资源组下。在下面的示例中,Fern 将生成一个名为 `client.send()` 的方法:
+
+```yaml title="openapi.yaml" {4}
+paths:
+ /send:
+ post:
+ x-fern-sdk-method-name: send
+```
+
+### 多级嵌套
+
+
+查看 merge.dev 如何使用嵌套组 [这里](https://github.com/merge-api/merge-node-client?tab=readme-ov-file#create-link-token)。
+
+
+如果您添加多个 `x-fern-sdk-group-name` 扩展,那么生成的 SDK 将嵌套组名。生成的 SDK 方法保持组名的顺序。
+
+在下面的示例中,Fern 将生成一个名为 `client.users.notifications.send()` 的方法:
+
+```yaml title="openapi.yaml"
+paths:
+ /users/notifications:
+ post:
+ x-fern-sdk-group-name:
+ - users
+ - notifications
+ x-fern-sdk-method-name: send
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/pagination.mdx b/fern/translations/zh/products/api-def/openapi/extensions/pagination.mdx
new file mode 100644
index 000000000..8ebeeff7a
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/pagination.mdx
@@ -0,0 +1,151 @@
+---
+title: 分页
+headline: 分页 (OpenAPI)
+description: 使用 x-fern-pagination 扩展为列表端点配置自动分页
+sidebar-title: 分页
+---
+
+
+
+
+`x-fern-pagination` 扩展为 OpenAPI 规范中的列表端点配置自动分页。[Fern 生成的 SDK](/learn/sdks/deep-dives/auto-pagination) 提供简单的迭代器,可以自动处理分页,因此 SDK 用户可以遍历所有结果,而无需手动管理分页复杂性。
+
+要配置分页:
+
+1. 使用 `x-fern-pagination` 扩展注解所需的分页端点
+2. 指定分页方案(`offset`、`cursor`、`next_uri` 或 `next_path`)
+3. 使用点访问表示法指定 `results` 的位置
+
+
+```yaml title="偏移分页" {5-7}
+paths:
+ /plants:
+ get:
+ operationId: list_plants
+ x-fern-pagination:
+ offset: $request.page_number
+ results: $response.results
+ parameters:
+ - name: page_number
+ in: query
+ schema:
+ type: integer
+ responses:
+ '200':
+ description: List of plants
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Plant'
+```
+
+```yaml title="游标分页" {5-8}
+paths:
+ /plants:
+ get:
+ operationId: list_plants
+ x-fern-pagination:
+ cursor: $request.cursor
+ next_cursor: $response.next
+ results: $response.results
+ parameters:
+ - name: cursor
+ in: query
+ schema:
+ type: string
+ responses:
+ '200':
+ description: List of plants
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ next:
+ type: string
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Plant'
+```
+
+```yaml title="URI 分页" {5-7}
+paths:
+ /plants:
+ get:
+ operationId: list_plants
+ x-fern-pagination:
+ next_uri: $response.next_page_url
+ results: $response.results
+ responses:
+ '200':
+ description: List of plants
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ next_page_url:
+ type: string
+ nullable: true
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Plant'
+```
+
+```yaml title="路径分页" {5-7}
+paths:
+ /plants:
+ get:
+ operationId: list_plants
+ x-fern-pagination:
+ next_path: $response.next_page_path
+ results: $response.results
+ responses:
+ '200':
+ description: List of plants
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ next_page_path:
+ type: string
+ nullable: true
+ results:
+ type: array
+ items:
+ $ref: '#/components/schemas/Plant'
+```
+
+
+## 配置选项
+
+`x-fern-pagination` 扩展支持以下属性:
+
+
+
+
+
+如果您的结果嵌套在响应对象中,请使用点访问表示法指定路径。例如,如果结果位于 `my_nested_object.inner_list` 中,`results` 路径将是 `$response.my_nested_object.inner_list`。
+
+```yaml {4, 7}
+MyResponseObject:
+ type: object
+ properties:
+ my_nested_object:
+ type: object
+ properties:
+ inner_list:
+ type: array
+ items:
+ $ref: '#/components/schemas/Plant'
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/parameter-names.mdx b/fern/translations/zh/products/api-def/openapi/extensions/parameter-names.mdx
new file mode 100644
index 000000000..7519fe35c
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/parameter-names.mdx
@@ -0,0 +1,65 @@
+---
+title: 自定义参数名称
+headline: 自定义参数名称 (OpenAPI)
+description: 使用 `x-fern-parameter-name` 来自定义查询参数、请求头和路径参数的命名。
+sidebar-title: 自定义参数名称
+---
+
+
+
+ `x-fern-parameter-name` 扩展允许您在生成的 SDK 中自定义参数的变量名称。
+
+
+## 请求头
+
+在下面的示例中,请求头 `X-API-Version` 在生成的 SDK 中被重命名为 `version`。这种重命名使 SDK 更具可读性。
+
+```yaml {8}
+paths:
+ "/user":
+ get:
+ operationId: list_user
+ parameters:
+ - in: header
+ name: X-API-Version
+ x-fern-parameter-name: version
+ schema:
+ type: string
+ required: true
+```
+
+## 查询参数
+
+在下面的示例中,查询参数 `q` 在生成的 SDK 中被重命名为 `search_terms`。这种重命名使参数对最终用户更加友好。
+
+```yaml {8}
+paths:
+ "/user/search":
+ get:
+ operationId: search_user
+ parameters:
+ - in: query
+ name: q
+ x-fern-parameter-name: search_terms
+ schema:
+ type: string
+ required: false
+```
+
+## 路径参数
+
+在下面的示例中,路径参数 `userId` 在生成的 SDK 中被重命名为 `id`。这种重命名使 SDK 更加简洁。
+
+```yaml {8}
+paths:
+ "/user/{userId}":
+ get:
+ operationId: get_user
+ parameters:
+ - in: path
+ name: userId
+ x-fern-parameter-name: id
+ schema:
+ type: string
+ required: false
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/property-names.mdx b/fern/translations/zh/products/api-def/openapi/extensions/property-names.mdx
new file mode 100644
index 000000000..e8c7a0f5d
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/property-names.mdx
@@ -0,0 +1,19 @@
+---
+title: 属性名称
+headline: 属性名称 (OpenAPI)
+description: 使用 `x-fern-property-name` 扩展自定义对象属性的变量名称
+sidebar-title: 属性名称
+---
+
+`x-fern-property-name` 扩展允许您自定义对象属性的变量名称。
+
+例如,如果您的模式中有一个名为 `_metadata` 的属性,但您希望在 SDK 中将变量称为 `data`,您可以执行以下操作:
+
+```yaml {6}
+components:
+ schemas:
+ MyUser:
+ _metadata:
+ type: object
+ x-fern-property-name: data
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/retries.mdx b/fern/translations/zh/products/api-def/openapi/extensions/retries.mdx
new file mode 100644
index 000000000..26a9c9f40
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/retries.mdx
@@ -0,0 +1,51 @@
+---
+title: 重试行为
+sidebar-title: 重试行为
+headline: 重试行为 (OpenAPI)
+description: 使用 x-fern-retries 扩展控制 API 重试逻辑。配置端点级别的重试行为,并为支付处理和订单创建禁用重试。
+---
+
+
+
+ `x-fern-retries` 扩展仅在 Python SDK 中受支持。
+
+
+`x-fern-retries` 扩展在您的 OpenAPI 规范中为每个端点配置重试行为,覆盖 SDK 用户配置的任何重试设置。使用它可以为非幂等操作(如支付处理或订单创建)禁用重试。
+
+要为特定端点禁用重试,请设置 `disabled: true`。
+
+```yaml title="openapi.yml" {4-5,15-16}
+paths:
+ /plants/{plantId}:
+ get:
+ x-fern-retries:
+ disabled: true
+ operationId: get_plant
+ parameters:
+ - name: plantId
+ in: path
+ required: true
+ schema:
+ type: string
+ /plants:
+ post:
+ x-fern-retries:
+ disabled: true
+ operationId: create_plant
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ species:
+ type: string
+ responses:
+ '201':
+ description: Plant created successfully
+```
+
+当在端点级别禁用重试时,生成的 SDK 不会重试对该端点的失败请求,无论 SDK 用户的自定义配置如何。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/schema-names.mdx b/fern/translations/zh/products/api-def/openapi/extensions/schema-names.mdx
new file mode 100644
index 000000000..c3fa6f467
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/schema-names.mdx
@@ -0,0 +1,84 @@
+---
+title: 模式名称
+sidebar-title: 模式名称
+headline: 模式名称 (OpenAPI)
+description: 使用 `x-fern-type-name` 扩展覆盖内联模式的自动生成名称
+---
+
+OpenAPI 允许您定义没有名称的内联模式。
+
+```yaml title="openapi.yml 中的内联类型" {11}
+components:
+ schemas:
+ Movie:
+ type: object
+ properties:
+ name:
+ type: string
+ cast:
+ type: array
+ items:
+ type: object
+ properties:
+ firstName:
+ type: string
+ lastName:
+ type: string
+ age:
+ type: integer
+```
+
+Fern 会自动为所有内联模式生成名称。例如,在这个示例中,
+Fern 会为内联数组项模式生成名称 `CastItem`。
+
+```typescript title="自动生成的名称" {6}
+export interface Movie {
+ name?: string;
+ cast?: CastItem[];
+}
+
+export interface CastItem {
+ firstName?: string;
+ lastName?: string;
+ age?: integer;
+}
+```
+
+如果您想覆盖生成的名称,可以使用扩展 `x-fern-type-name`。
+
+```yaml title="openapi.yml" {12}
+components:
+ schemas:
+ Movie:
+ type: object
+ properties:
+ name:
+ type: string
+ cast:
+ type: array
+ items:
+ type: object
+ x-fern-type-name: Person
+ properties:
+ firstName:
+ type: string
+ lastName:
+ type: string
+ age:
+ type: integer
+```
+
+这将用 `Person` 替换 `CastItem`,生成的代码将读起来更加自然:
+
+```typescript title="覆盖的名称" {6}
+export interface Movie {
+ name?: string;
+ cast?: Person[];
+}
+
+export interface Person {
+ firstName?: string;
+ lastName?: string;
+ age?: integer;
+}
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/sdk-variables.mdx b/fern/translations/zh/products/api-def/openapi/extensions/sdk-variables.mdx
new file mode 100644
index 000000000..8c140ea09
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/sdk-variables.mdx
@@ -0,0 +1,80 @@
+---
+title: SDK 变量
+headline: SDK 变量(OpenAPI)
+description: 使用 `x-fern-sdk-variables` 在所有请求中设置通用路径参数
+sidebar-title: SDK 变量
+---
+
+`x-fern-sdk-variables` 扩展允许您定义在 SDK 客户端初始化时设置一次的变量,并在所有端点调用的路径参数中自动使用。这对于在许多端点路径中出现的通用参数(如租户 ID、组织 ID 或环境标识符)非常有用。
+
+
+ SDK 变量在 TypeScript (v2.6.3+)、Python (v4.24.0+) 和 Java (v3.6.3+) 中受支持。仅支持字符串类型。
+
+
+## 配置
+
+使用 `x-fern-sdk-variables` 在文档级别定义变量,然后使用 `x-fern-sdk-variable` 将路径参数标记为变量:
+
+```yaml {1-7,17,23} title="openapi.yml"
+x-fern-sdk-variables:
+ gardenId:
+ type: string
+ description: The unique identifier for your garden
+ zoneId:
+ type: string
+ description: The zone within the garden
+
+paths:
+ /gardens/{gardenId}/zones/{zoneId}/plants:
+ get:
+ operationId: list_plants_in_zone
+ parameters:
+ - name: gardenId
+ in: path
+ required: true
+ x-fern-sdk-variable: gardenId
+ schema:
+ type: string
+ - name: zoneId
+ in: path
+ required: true
+ x-fern-sdk-variable: zoneId
+ schema:
+ type: string
+```
+
+## SDK 使用
+
+变量成为必需的构造函数参数,而不是传递给单个方法调用:
+
+
+```typescript {2-3}
+const client = new PlantClient({
+ gardenId: "garden_123",
+ zoneId: "zone_456",
+ apiKey: "your-api-key"
+});
+
+const plants = await client.listPlantsInZone();
+```
+
+```python {2-3}
+client = PlantClient(
+ garden_id="garden_123",
+ zone_id="zone_456",
+ api_key="your-api-key"
+)
+
+plants = client.list_plants_in_zone()
+```
+
+```java {2-3}
+PlantClient client = PlantClient.builder()
+ .gardenId("garden_123")
+ .zoneId("zone_456")
+ .apiKey("your-api-key")
+ .build();
+
+List plants = client.listPlantsInZone();
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/server-names.mdx b/fern/translations/zh/products/api-def/openapi/extensions/server-names.mdx
new file mode 100644
index 000000000..03c552677
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/server-names.mdx
@@ -0,0 +1,84 @@
+---
+title: 服务器名称和 URL 模板化
+headline: 服务器名称和 URL 模板化(OpenAPI)
+description: 了解如何在 OpenAPI 规范中使用 x-fern-server-name、x-fern-default-url 和 URL 模板变量,以便更好地生成 SDK。
+sidebar-title: 服务器名称和 URL 模板化
+---
+
+Fern 支持多个扩展来配置 OpenAPI 规范中的 `servers` 块。使用 `x-fern-server-name` 为服务器提供可读的名称,然后将其与 URL 模板变量和 `x-fern-default-url` 结合使用,以在生成的 SDK 中支持动态基础 URL。
+
+## `x-fern-server-name`
+
+使用 `x-fern-server-name` 为每个服务器条目提供可读的名称。Fern 在生成的环境枚举中使用此名称。
+
+`x-fern-server-name` 扩展用于命名您的服务器。
+
+```yaml title="openapi.yml"
+servers:
+ - url: https://api.example.com
+ x-fern-server-name: Production
+ - url: https://sandbox.example.com
+ x-fern-server-name: Sandbox
+```
+
+在生成的 TypeScript SDK 中,您会看到:
+
+```typescript title="environment.ts"
+export const ExampleEnvironment = {
+ Production: "https://api.example.com",
+ Sandbox: "https://sandbox.example.com",
+} as const;
+
+export type ExampleEnvironment = typeof ExampleEnvironment.Production;
+```
+
+### 多个基础 URL
+
+不同的端点可以针对不同的服务器。直接在端点上添加 `servers` 块以覆盖该路径的顶级服务器。使用 `x-fern-server-name` 为每个端点级服务器提供不同的名称,以便 Fern 能够正确分组。
+
+```yaml title="openapi.yml"
+paths:
+ /auth/token:
+ post:
+ servers:
+ - url: https://auth.example.com
+ x-fern-server-name: Auth
+```
+
+当 Fern 检测到多个命名服务器时,生成的 SDK 客户端会自动将每个端点解析到正确的基础 URL。
+
+`x-fern-server-name` 也与 URL 模板变量一起使用,如下所示。
+
+## URL 模板化和 `x-fern-default-url`
+
+URL 模板变量和 `x-fern-default-url` 目前仅支持 Python 和 Java SDK 生成。
+
+对于跨多个区域、环境或自定义域部署的 API,您可以使用 `{variable}` 语法在服务器 `url` 中定义变量占位符。Fern 读取这些变量并将其作为生成的 SDK 中的可配置参数公开,以便用户可以在运行时自定义基础 URL。
+
+由于像 `https://api.{region}.example.com/v1` 这样的模板化 URL 本身并不有效,因此使用 `x-fern-default-url` 提供具体的回退值。这样,不需要自定义变量的 SDK 用户就能获得开箱即用的工作客户端。
+
+```yaml title="openapi.yml"
+servers:
+ - url: https://api.{region}.{environment}.example.com/v1
+ description: Regional API server
+ x-fern-server-name: Default
+ x-fern-default-url: https://api.example.com/v1
+ variables:
+ region:
+ default: us-east-1
+ enum:
+ - us-east-1
+ - us-west-2
+ - eu-west-1
+ environment:
+ default: prod
+ enum:
+ - prod
+ - staging
+ - dev
+```
+
+每个变量都在 `variables` 映射下定义,并支持以下字段:
+
+- `default` — 当 SDK 用户未提供值时使用的回退值。此字段是 OpenAPI 规范所要求的。
+- `enum` — 允许值的可选列表。当提供时,Fern 在 SDK 中将变量生成为类型化枚举,而不是开放字符串。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/extensions/tag-display-name.mdx b/fern/translations/zh/products/api-def/openapi/extensions/tag-display-name.mdx
new file mode 100644
index 000000000..92d6e7f3b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/extensions/tag-display-name.mdx
@@ -0,0 +1,48 @@
+---
+title: 标签显示名称
+headline: 标签显示名称 (OpenAPI)
+description: 使用 `x-displayName` 扩展自定义标签名称在 API Reference 中的显示方式
+sidebar-title: 标签显示名称
+---
+
+默认情况下,OpenAPI 规范中的标签名称会成为 API Reference 中的章节名称。使用 `x-displayName` 扩展来控制这些章节名称在生成的文档中的显示方式。这有助于控制大小写和创建用户友好的名称。
+
+在 OpenAPI 规范的根级别定义带有显示名称的标签,然后在操作中按名称引用它们:
+
+```yaml title="openapi.yml"
+openapi: 3.0.0
+info:
+ title: Plant Care API
+ version: 1.0.0
+
+tags:
+ - name: plant
+ x-displayName: Plants
+ description: Operations for managing plants
+ - name: watering-schedule
+ x-displayName: Watering Schedules
+ description: Handle watering schedule operations
+
+paths:
+ /plants:
+ get:
+ tags:
+ - plant
+ summary: List all plants
+ /plants/{plantId}:
+ get:
+ tags:
+ - plant
+ summary: Get a plant by ID
+ /watering-schedules:
+ get:
+ tags:
+ - watering-schedule
+ summary: List watering schedules
+```
+
+您还可以在[覆盖文件](/learn/api-definitions/openapi/overrides)中设置显示名称。
+
+
+ 或者,您也可以直接在[`docs.yml` 文件](/learn/docs/api-references/customize-api-reference-layout)中重命名章节。
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/overlays.mdx b/fern/translations/zh/products/api-def/openapi/overlays.mdx
new file mode 100644
index 000000000..4bcae0386
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/overlays.mdx
@@ -0,0 +1,195 @@
+---
+title: Overlays
+description: 使用 OpenAPI Overlay 规范来自定义您的 OpenAPI 定义,而无需修改原始规范。
+sidebar-title: Overlays
+---
+
+Overlays 让您可以自定义 OpenAPI 规范而无需修改原始文件。这在以下情况下很有用:
+
+- 您的 API 规范是从服务器代码自动生成的
+- 您需要为 SDK 和文档配置不同的设置
+- 您想要添加 Fern 配置,如分页或 SDK 方法名称
+- 您想要使用 JSONPath 通配符对多个端点进行批量更改
+
+Overlays 遵循 [OpenAPI Overlay 规范](https://spec.openapis.org/overlay/v1.0.0.html),并且在 OpenAPI 生态系统中是可移植的。
+
+
+ Fern 建议对 OpenAPI 规范使用 overlays 而不是 overrides。
+
+ [Overrides](/learn/api-definitions/openapi/overrides) 也完全受支持。如果 overrides 对您的团队有效,则无需切换。您也可以同时使用两者(先应用 overrides,然后应用 overlays)。
+
+
+## 配置 overlays
+
+要使用 overlays,请在与您的规范相同的文件夹中创建一个 `overlays` 文件,并在 `generators.yml` 中引用它:
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: openapi.json
+ overlays: overlays.yml
+```
+
+## 定义 overlays 文件
+
+overlay 中的每个动作使用 [JSONPath](https://datatracker.ietf.org/doc/html/rfc9535) 定位元素,并应用 `update` 或 `remove` 操作:
+
+```yaml title="openapi-overlays.yml"
+overlay: 1.0.0 # 必需:Overlay 规范版本
+info:
+ title: 自定义植物商店 API # 必需:overlay 目的的可读描述
+ version: 1.0.0 # 必需:用于跟踪此 overlay 更改的版本标识符
+actions: # 必需:要应用的更改的有序列表
+ - target: $.info # 选择要修改的元素的 JSONPath 表达式
+ update: # 要与目标元素合并的属性
+ x-fern-sdk-group-name: plants
+ - target: $.paths['/plants/{plantId}'].get.parameters[?(@.name == 'plantId')]
+ update:
+ x-fern-parameter-name: id
+```
+
+
+Fern 要求在 JSONPath 筛选表达式周围使用括号。请使用 `[?(@.name == 'plantId')]` 而不是 `[?@.name == 'plantId']`。
+
+
+
+
+
+使用 `update` 来更改标准 OpenAPI 属性,如描述、摘要或其他字段:
+
+```yaml title="openapi-overlays.yml"
+overlay: 1.0.0
+info:
+ title: 改进 API 文档
+ version: 1.0.0
+actions:
+ - target: $.paths['/plants'].get
+ update:
+ summary: 列出所有可用植物
+ description: 返回商店库存中植物的分页列表。
+```
+
+
+
+
+使用 `update` 添加 [Fern 扩展](/api-definitions/openapi/extensions/overview):
+
+```yaml title="openapi-overlays.yml"
+overlay: 1.0.0
+info:
+ title: 添加 Fern SDK 自定义
+ version: 1.0.0
+actions:
+ # 添加 SDK 组和方法名称
+ - target: $.paths['/plants'].get
+ update:
+ x-fern-sdk-group-name: plants
+ x-fern-sdk-method-name: list
+ - target: $.paths['/plants'].post
+ update:
+ x-fern-sdk-group-name: plants
+ x-fern-sdk-method-name: create
+ # 重命名参数
+ - target: $.paths['/plants/{plantId}'].get.parameters[?(@.name == 'includeDetails')]
+ update:
+ x-fern-parameter-name: withDetails
+```
+
+
+
+
+使用 `remove: true` 从您的规范中删除元素:
+
+```yaml title="openapi-overlays.yml" {8}
+overlay: 1.0.0
+info:
+ title: 移除内部端点
+ version: 1.0.0
+actions:
+ - target: $.paths['/internal/debug']
+ description: 从公共 SDK 中移除调试端点
+ remove: true
+```
+
+
+
+
+## 跨 API 管理 overlays
+
+`generators.yml` 中的每个规范接受一个 overlay 文件。您可以在规范中引用相同的文件,或为不同的配置使用单独的文件。
+
+
+
+
+当多个规范需要相同的自定义时,将它们指向同一个 overlay 文件以避免重复:
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: ./payments-api.yml
+ overlays: shared-overlays.yml # 两个规范使用相同的 overlay
+ - openapi: ./users-api.yml
+ overlays: shared-overlays.yml
+```
+
+如果每个规范需要唯一的自定义,请为每个规范创建单独的 overlay 文件:
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: ./payments-api.yml
+ overlays: payments-overlays.yml
+ - openapi: ./users-api.yml
+ overlays: users-overlays.yml
+```
+
+
+
+
+通过创建具有自己的 `generators.yml` 的单独文件夹,为 SDK 生成和文档使用不同的 overlay 文件:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```yaml title="sdks/generators.yml"
+api:
+ specs:
+ - openapi: ../openapi.yml
+ overlays: sdk-overlays.yml
+```
+
+
+
+
+为生产环境与内部 API 配置不同的 overlays:
+
+```yaml title="generators.yml" {5, 11}
+groups:
+ production:
+ specs:
+ - openapi: openapi.yml
+ overlays: production-overlays.yml
+ generators:
+ ...
+ internal:
+ specs:
+ - openapi: openapi.yml
+ overlays: internal-overlays.yml
+ generators:
+ ...
+```
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/overview.mdx b/fern/translations/zh/products/api-def/openapi/overview.mdx
new file mode 100644
index 000000000..79d8c00ff
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/overview.mdx
@@ -0,0 +1,167 @@
+---
+title: 什么是 OpenAPI 规范?
+description: OpenAPI 是用于记录 REST API 的标准
+sidebar-title: 什么是 OpenAPI 规范?
+---
+
+OpenAPI 规范 (OAS) 是开发人员用来记录 REST API 的框架。该规范以 JSON 或 YAML 格式编写,包含所有端点、参数、模式和身份验证方案。Fern 兼容最新的 OAS 版本,目前是 [v3.1.1](https://spec.openapis.org/#openapi-specification)。
+
+以下是 OpenAPI 文件的示例:
+
+```yaml title="openapi.yml" maxLines=10
+openapi: 3.0.2
+info:
+ title: Petstore - OpenAPI 3.0
+ description: |-
+ This is a sample Pet Store Server based on the OpenAPI 3.0 specification.
+paths:
+ "/pet":
+ put:
+ tags:
+ - pet
+ summary: Update an existing pet
+ description: Update an existing pet by Id
+ operationId: updatePet
+ requestBody:
+ description: Update an existent pet in the store
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/Pet"
+ required: true
+ responses:
+ '200':
+ description: Successful operation
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/Pet"
+ '400':
+ description: Invalid ID supplied
+ '404':
+ description: Pet not found
+ '405':
+ description: Validation exception
+ security:
+ - api_key
+components:
+ schemas:
+ Category:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ example: 1
+ name:
+ type: string
+ example: Dogs
+ Tag:
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ name:
+ type: string
+ Pet:
+ required:
+ - name
+ - photoUrls
+ type: object
+ properties:
+ id:
+ type: integer
+ format: int64
+ example: 10
+ name:
+ type: string
+ example: doggie
+ category:
+ "$ref": "#/components/schemas/Category"
+ photoUrls:
+ type: array
+ items:
+ type: string
+ tags:
+ type: array
+ items:
+ "$ref": "#/components/schemas/Tag"
+ status:
+ type: string
+ description: pet status in the store
+ enum:
+ - available
+ - pending
+ - sold
+ securitySchemes:
+ api_key:
+ type: apiKey
+ name: api_key
+ in: header
+```
+## 最佳实践
+
+遵循这些最佳实践,确保您的 OpenAPI 规范生成高质量的 SDK 和文档:
+
+- **使用合适的项目结构进行组织。** 按照[项目结构](/api-definitions/overview/project-structure)中的说明,清晰地组织包含您的定义和其他相关文件的目录。
+- **为端点添加 `operationId`。** 为每个端点包含清晰的 `operationId`,以控制在 SDK 中生成的函数名称。(或使用[扩展来自定义组和方法名称](/api-definitions/openapi/extensions/method-names)。)
+- **引用模式而不是内联。** 在 `components/schemas` 部分定义可重用的模式,并使用 `$ref` 引用它们。这促进了一致性,减少了重复,并使维护更容易。
+
+ ```yaml title="openapi.yml" {8, 14, 17-25}
+ paths:
+ /pets:
+ post:
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet' # Clean reference
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet' # Reused easily
+ components:
+ schemas:
+ Pet: # Defined once, used everywhere
+ type: object
+ properties:
+ name:
+ type: string
+ status:
+ type: string
+ enum: [available, pending, sold]
+ ```
+
+- **使用覆盖层和 Fern 扩展进行自定义。** 使用 Fern [扩展](/api-definitions/openapi/extensions/overview)来自定义您的规范,这些扩展保存在[覆盖层文件](/api-definitions/openapi/overlays)中。这使您能够修改生成行为,而不更改核心 OpenAPI 定义。
+
+一旦您的 OpenAPI 规范遵循这些实践,您就可以设置 fern 文件夹了。
+
+## 设置您的 fern 文件夹
+
+ 正在考虑生成 OpenAPI 规范的选项?在[这里](https://fern-community.slack.com/join/shared_invite/zt-2dpftfmif-MuAegl8AfP_PK8s2tx350Q%EF%BB%BF#/shared-invite/email)获得实时支持
+
+首先使用 OpenAPI 规范初始化您的 fern 文件夹
+
+
+```sh file
+fern init --openapi ./path/to/openapi
+```
+```sh url
+fern init --openapi https://host/path/to/openapi
+```
+
+
+这将初始化如下所示的目录:
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/reference/generators-reference.mdx b/fern/translations/zh/products/api-def/openapi/reference/generators-reference.mdx
new file mode 100644
index 000000000..a69d2c11f
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/reference/generators-reference.mdx
@@ -0,0 +1,11 @@
+---
+title: OpenAPI generators.yml 参考
+description: 在 generators.yml 文件中配置 OpenAPI 规范的参考指南
+sidebar-title: OpenAPI generators.yml 参考
+---
+
+`generators.yml` 文件有两个作用:它在 `api.specs` 部分声明你的 OpenAPI 规范位置,并在可选的 `groups` 部分配置 SDK 生成。
+
+这里声明的 API 可以通过 `docs.yml` 在你的文档中渲染。请参阅[生成你的 API 参考文档](/learn/docs/api-references/generate-api-ref)。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/server-frameworks/fastapi.mdx b/fern/translations/zh/products/api-def/openapi/server-frameworks/fastapi.mdx
new file mode 100644
index 000000000..81e381eb4
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/server-frameworks/fastapi.mdx
@@ -0,0 +1,94 @@
+---
+title: FastAPI Instrumentation
+description: 了解在对 FastAPI 应用程序进行工具化时创建丰富 OpenAPI 规范的最佳实践。
+sidebar-title: FastAPI Instrumentation
+---
+
+
+[FastAPI](https://fastapi.tiangolo.com/) 是由 [tiangolo](https://github.com/tiangolo) 开发的一个流行的 Python Web 框架。
+
+该产品的品牌定位是
+
+> FastAPI 是一个现代、快速(高性能)的 Web 框架,用于基于标准 Python 类型提示构建 API。
+
+FastAPI 与 Fern 配合得非常好,因为它具有输出 OpenAPI 规范的能力!下面我们将概述一些使用 FastAPI 生成丰富 OpenAPI 的技巧。
+
+
+## OpenAPI 生成
+
+默认情况下,FastAPI 将根据您的路由和数据模型为您生成 OpenAPI 规范!您可以通过访问 FastAPI 服务器上的 `/docs` 来查看此规范。
+
+如果您没有看到任何 OpenAPI 规范(或 Swagger UI),您可能需要检查您的 FastAPI 服务器配置,因为路径可能已被更改或完全省略。
+
+```python {6-8}
+from fastapi import FastAPI
+
+...
+
+FastAPI(
+ openapi_url="/openapi.json", # <-- 这是访问 OpenAPI 规范所需的文件和 URL,`docs_url` 和 `redoc_url` 是在 UI 中显示文件的便捷包装器!
+ docs_url="/docs", # <-- 这是访问 Swagger UI 的 URL,它将指向您的 OpenAPI 规范
+ redoc_url="/redoc" # <-- 这是访问 ReDoc UI 的 URL,它将指向您的 OpenAPI 规范
+)
+```
+
+## 指定服务器
+
+Fern 将自动生成指向您在 OpenAPI 规范中配置的服务器的客户端,因此指定您的 API 将托管的服务器很重要。
+
+```python {5}
+from fastapi import FastAPI
+
+...
+
+app = FastAPI(servers=[{"url": "http://prod.test.com", "description": "Production server"}])
+# 这在您的 OpenAPI 规范中创建了以下服务器对象:
+# "servers":[{"url":"http://prod.test.com","description":"Production server"}],
+```
+
+## OpenAPI 扩展
+
+FastAPI 允许您通过使用 `openapi_extra` 参数直接在路由中添加额外的 OpenAPI 配置。
+下面,我们注释了 FastAPI 中的一个"良好"路由,它具有类型标注以及 Fern 扩展来帮助命名。
+
+```python {5-9}
+@router.post(
+ "/your/post/endpoint",
+ response_model=YourResponseModel, # <-- 在 FastAPI 中,指定响应模型很重要,这样它就会出现在 OpenAPI 规范中
+ summary="Get some response for your req", # <-- 如果您想为端点添加描述,可以在这里添加
+ openapi_extra={ # <-- 最后,您可以在这里添加 Fern 扩展,这些扩展将产生类似于 python 中 `client.endpoints.create(...)` 的 SDK 代码
+ "x-fern-sdk-method-name": "create",
+ "x-fern-sdk-group-name": "endpoints",
+ "x-fern-availability": "beta",
+ },
+)
+async def your_post_endpoint(
+ payload: YourRequestModel,
+) -> YourResponseModel:
+```
+
+## 指定示例
+
+FastAPI 允许您为数据模型指定示例,Fern 将自动获取并在生成的 SDK 和文档中使用这些示例。
+
+有关在 Fern 中利用示例的更多信息,请参阅 [Fern 文档](/learn/api-definitions/openapi/extensions/request-response-examples)。
+
+有关此 FastAPI 功能的更多信息,请参阅 [FastAPI 文档](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)。
+
+```python {7-11}
+from pydantic import BaseModel
+
+class MyObject(BaseModel):
+ id: str
+
+ class Config:
+ schema_extra = {
+ "example": {
+ "id": "a-cool-uuid",
+ }
+ }
+```
+
+## 其他自定义
+
+FastAPI 在如何自定义 OpenAPI 规范方面具有很大的灵活性。更多信息请参阅 [FastAPI 文档](https://fastapi.tiangolo.com/how-to/extending-openapi/#modify-the-openapi-schema)。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/servers.mdx b/fern/translations/zh/products/api-def/openapi/servers.mdx
new file mode 100644
index 000000000..f68d4420b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/servers.mdx
@@ -0,0 +1,80 @@
+---
+title: 服务器
+description: 配置服务器 URL 和环境以帮助用户连接到您的 API。
+subtitle: 定义服务器 URL 和环境以帮助用户连接到您的 API。
+sidebar-title: 服务器
+---
+
+
+OpenAPI 允许您在 `servers` 键下指定一个或多个基础 URL。
+
+```yml openapi.yml
+
+servers:
+ - url: https://api.yourcompany.com/
+ - url: https://api.eu.yourcompany.com/
+```
+
+指定服务器对 SDK 和文档都很有价值:
+- 对于 SDK,您的用户无需在客户端实例化时手动指定 baseURL
+- 对于文档,您的 API 调试工具将自动连接到正确的服务器
+
+## 命名您的服务器
+
+如果您有多个服务器,我们建议指定 `x-fern-server-name` 来为服务器命名。
+
+```yml openapi.yml {3,5}
+servers:
+ - x-fern-server-name: Production
+ url: https://api.yourcompany.com/
+ - x-fern-server-name: Production_EU
+ url: https://api.eu.yourcompany.com/
+```
+
+## 单个 API 的多个基础 URL
+
+如果您采用微服务架构,可能会有不同的端点托管在不同的 URL 上。例如,您的 AI 端点可能托管在 `ai.yourcompany.com`,而其余端点可能托管在 `api.yourcompany.com`。
+
+要指定这种情况,您需要在 `generators.yml` 和 OpenAPI 规范中都添加配置。下面的代码片段显示了如何在 `generators.yml` 中配置具有多个 URL 的环境。
+
+```yml generators.yml {3-8}
+api:
+ default-environment: Production
+ default-url: api
+ environments:
+ Production:
+ api: api.yourcompany.com
+ ai: ai.yourcompany.com
+ specs:
+ - openapi: ./path/to/your/openapi
+ overrides: ./path/to/your/overrides # optional
+```
+
+一旦您在 `generators.yml` 中指定了环境,就可以使用 `x-fern-server-name` 扩展来指定操作所属的服务器。
+
+```yml openapi.yml {4}
+paths:
+ /chat:
+ post:
+ x-fern-server-name: ai
+```
+
+如果您有多个环境,如开发或测试环境,也可以在 `generators.yml` 中建模。
+
+```yml generators.yml {7-12}
+api:
+ default-environment: Production
+ default-url: api
+ environments:
+ Production:
+ api: api.yourcompany.com
+ ai: ai.yourcompany.com
+ Staging:
+ api: api.staging.yourcompany.com
+ ai: ai.staging.yourcompany.com
+ Dev:
+ api: api.dev.yourcompany.com
+ ai: ai.dev.yourcompany.com
+```
+
+要查看生产环境中的示例,请查看 Chariot [generators.yml](https://github.com/chariot-giving/chariot-openapi/blob/main/fern/apis/2025-02-24/generators.yml)
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openapi/webhooks.mdx b/fern/translations/zh/products/api-def/openapi/webhooks.mdx
new file mode 100644
index 000000000..1fafe9ecb
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openapi/webhooks.mdx
@@ -0,0 +1,188 @@
+---
+title: Webhooks
+description: 了解如何使用 OpenAPI 3.1 原生支持或 Fern 的扩展定义 webhooks。生成 webhook 文档和 SDK 验证工具。
+sidebar-title: Webhooks
+max-toc-depth: 3
+---
+
+
+Fern 支持两种在 OpenAPI 规范中定义 webhooks 的方法:
+
+1. 使用 OpenAPI 3.1 的原生 webhook 支持(推荐)
+2. 使用 Fern 的 `x-fern-webhook` 扩展
+
+## OpenAPI 3.1 webhooks
+
+对于 OpenAPI 3.1 规范,使用 `webhooks` 顶级字段来定义您的 webhook 操作。每个 webhook 都需要一个 `operationId` 才能被 Fern 正确处理。
+
+```yaml openapi.yml {4, 7-8, 42-48}
+webhooks:
+ newPlant:
+ post:
+ operationId: newPlantWebhook # Defines webhook
+ summary: New Plant Added
+ description: Information about a new plant that was added to the store
+ tags:
+ - Plants # Creates dedicated page
+ requestBody:
+ description: The plant data when a new plant is added
+ content:
+ application/json:
+ schema:
+ description: The Webhook payload for when a new plant is added to the store
+ properties:
+ triggerType:
+ description: The type of event that triggered the request
+ type: string
+ example: "new_plant"
+ payload:
+ type: object
+ description: The payload of data sent from the plant store
+ properties:
+ plantId:
+ type: string
+ description: The unique identifier for the plant
+ example: "64f1a2b3c5d6e7f8a9b0c1d2"
+ name:
+ type: string
+ description: The name of the plant
+ example: "Monstera Deliciosa"
+ price:
+ type: number
+ format: float
+ description: The price of the plant in dollars
+ example: 29.99
+ addedAt:
+ type: string
+ format: date-time
+ description: The timestamp when the plant was added
+ example: "2024-01-15T10:30:00.000Z"
+ example: # Full payload example for docs
+ triggerType: "new_plant"
+ payload:
+ plantId: "64f1a2b3c5d6e7f8a9b0c1d2"
+ name: "Monstera Deliciosa"
+ price: 29.99
+ addedAt: "2024-01-15T10:30:00.000Z"
+ responses:
+ '200':
+ description: Return a 200 status to indicate that the data was received successfully
+```
+
+## Fern webhook 扩展
+
+对于 OpenAPI 3.0,使用 `x-fern-webhook: true` 扩展来定义 webhooks。Fern 会将 `requestBody` 视为 webhook 负载。
+
+```yaml openapi.yml {6-8, 23-25}
+paths:
+ /payment/updated/:
+ post:
+ summary: Payment Initiated
+ operationId: initiatePayment
+ tags:
+ - Payments # Creates dedicated page
+ x-fern-webhook: true # Defines webhooks
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ amount:
+ type: number
+ example: 99.99
+ currency:
+ $ref: '#/components/schemas/Currency'
+ required:
+ - amount
+ - currency
+ example: # Full payload example for docs
+ amount: 99.99
+ currency: "USD"
+```
+
+
+定义 webhook 时选择的路径可以是任意的。由于 webhooks 可以发送到任何服务器,Fern 会忽略路径。
+
+
+## 生成 webhook 参考
+
+Fern Docs 可以从您的定义中自动生成 webhook 参考文档。在您的 `docs.yml` 文件中进行设置。
+
+您的 webhook 参考可以是单个文档页面:
+
+```yml docs.yml
+navigation:
+ - api: Webhook Reference # Display name for this page
+ api-name: webhooks-v1 # Name of webhook definition directory
+```
+
+或者您可以为每个 webhook 事件配置单独的文档页面:
+
+```yaml title="docs.yml"
+navigation:
+ - subpackage_plants.newPlantWebhook # subpackage_{tag}.{webhook-event-name}
+```
+
+有关如何在 `docs.yml` 中配置 webhook 参考的更多信息,请参阅[生成 webhook 参考](/docs/api-references/generate-webhook-ref)。
+
+## SDK 签名验证
+
+使用 `x-fern-webhook-signature` 扩展来配置 webhook 签名验证。配置后,Fern 会生成 SDK 工具,允许用户验证 webhook 签名并确保事件来自您的 API。
+
+配置可以在**文档级别**(适用于所有 webhook 端点)或**每个端点**(覆盖文档级别的默认设置)设置。两个级别都接受相同的配置选项。
+
+Fern 支持两种验证方法:**HMAC**(使用共享密钥的对称密钥验证)和**非对称**(使用 RSA、ECDSA 或 Ed25519 密钥的公钥验证)。
+
+
+
+```yaml title="openapi.yml"
+x-fern-webhook-signature:
+ type: hmac
+ header: x-webhook-signature
+ algorithm: sha256
+ encoding: hex
+
+paths:
+ /webhooks/payment:
+ post:
+ x-fern-webhook: true
+ # Inherits document-level signature config
+
+ /webhooks/order:
+ post:
+ x-fern-webhook: true
+ # Inherits document-level signature config
+```
+
+
+```yaml title="openapi.yml"
+x-fern-webhook-signature:
+ type: hmac
+ header: x-webhook-signature
+ algorithm: sha256
+ encoding: hex
+
+paths:
+ /webhooks/payment:
+ post:
+ x-fern-webhook: true
+ # Inherits document-level config
+
+ /webhooks/refund:
+ post:
+ x-fern-webhook: true
+ x-fern-webhook-signature:
+ # Override with asymmetric
+ type: asymmetric
+ header: x-refund-signature
+ asymmetric-algorithm: rsa-sha256
+ encoding: base64
+ jwks-url: https://api.example.com/.well-known/jwks.json
+```
+
+
+
+### 配置选项
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/auth.mdx b/fern/translations/zh/products/api-def/openrpc/auth.mdx
new file mode 100644
index 000000000..da2ccfb2d
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/auth.mdx
@@ -0,0 +1,236 @@
+---
+title: Authentication
+subtitle: 为 JSON-RPC API 建模身份验证方案,包括 Bearer、Basic 和 API Key 身份验证
+sidebar-title: 身份验证
+---
+
+OpenRPC 中的身份验证可以在服务器级别或方法级别进行配置,具体取决于您的 JSON-RPC 实现。与 REST API 不同,JSON-RPC 通常通过传输层(HTTP 头)或在 JSON-RPC 请求负载中处理身份验证。
+
+## HTTP 传输身份验证
+
+当使用 HTTP 作为 JSON-RPC 的传输方式时,您可以使用标准的 HTTP 身份验证方案。
+
+### Bearer token 身份验证
+
+为基于 HTTP 的 JSON-RPC 配置 bearer token 身份验证:
+
+```yml title="openrpc.yml" {4-9}
+servers:
+ - name: production
+ url: https://api.example.com/rpc
+ description: Production JSON-RPC server
+ security:
+ - bearerAuth: []
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ bearerFormat: JWT
+```
+
+这会生成需要 token 的 SDK 方法:
+
+```typescript
+const client = new JSONRPCClient({
+ url: "https://api.example.com/rpc",
+ auth: {
+ bearer: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
+ }
+});
+
+// 调用 JSON-RPC 方法
+const result = await client.call("calculate.add", { a: 5, b: 3 });
+```
+
+### API Key 身份验证
+
+配置 API Key 身份验证:
+
+```yml title="openrpc.yml" {4-9}
+servers:
+ - name: production
+ url: https://api.example.com/rpc
+ description: Production JSON-RPC server
+ security:
+ - apiKeyAuth: []
+components:
+ securitySchemes:
+ apiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+```
+
+在 SDK 中的使用方式:
+
+```typescript
+const client = new JSONRPCClient({
+ url: "https://api.example.com/rpc",
+ auth: {
+ apiKey: "your-api-key-here"
+ }
+});
+```
+
+### Basic 身份验证
+
+配置 Basic 身份验证:
+
+```yml title="openrpc.yml" {4-9}
+servers:
+ - name: production
+ url: https://api.example.com/rpc
+ description: Production JSON-RPC server
+ security:
+ - basicAuth: []
+components:
+ securitySchemes:
+ basicAuth:
+ type: http
+ scheme: basic
+```
+
+在 SDK 中的使用方式:
+
+```typescript
+const client = new JSONRPCClient({
+ url: "https://api.example.com/rpc",
+ auth: {
+ username: "user@example.com",
+ password: "password123"
+ }
+});
+```
+
+## 方法级别的身份验证
+
+一些 JSON-RPC 实现可能需要为特定方法使用不同的身份验证:
+
+```yml title="openrpc.yml" {6-7, 15-16}
+methods:
+ - name: public.getInfo
+ summary: Get public information
+ description: Publicly accessible method (no auth required)
+ params: []
+ result:
+ name: info
+ schema:
+ type: object
+ - name: user.getProfile
+ summary: Get user profile
+ description: Requires user authentication
+ security:
+ - bearerAuth: []
+ params:
+ - name: userId
+ schema:
+ type: string
+ required: true
+ result:
+ name: profile
+ schema:
+ $ref: '#/components/schemas/UserProfile'
+```
+
+## WebSocket 身份验证
+
+对于 WebSocket 传输,身份验证通常在连接建立过程中进行:
+
+```yml title="openrpc.yml" {4-8}
+servers:
+ - name: websocket
+ url: wss://api.example.com/rpc
+ description: WebSocket JSON-RPC server
+ variables:
+ token:
+ description: Authentication token for WebSocket connection
+ default: ""
+ security:
+ - wsAuth: []
+components:
+ securitySchemes:
+ wsAuth:
+ type: apiKey
+ in: query
+ name: token
+ description: Authentication token passed as query parameter
+```
+
+## 自定义身份验证参数
+
+对于在请求负载内处理身份验证的 JSON-RPC API:
+
+```yml title="openrpc.yml" {8-16}
+methods:
+ - name: auth.login
+ summary: Authenticate user
+ description: Login method that returns authentication token
+ params:
+ - name: credentials
+ schema:
+ type: object
+ properties:
+ username:
+ type: string
+ password:
+ type: string
+ required:
+ - username
+ - password
+ result:
+ name: authResult
+ schema:
+ type: object
+ properties:
+ token:
+ type: string
+ expiresIn:
+ type: integer
+ refreshToken:
+ type: string
+```
+
+## Fern 身份验证扩展
+
+使用 Fern 扩展来自定义身份验证行为:
+
+```yml title="openrpc.yml" {5-8}
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ x-fern-token:
+ name: authToken
+ env: AUTH_TOKEN
+```
+
+这允许用户通过环境变量或构造函数参数设置身份验证,使 SDK 更加灵活和安全。
+
+## 身份验证的错误处理
+
+为身份验证失败定义标准化的错误响应:
+
+```yml title="openrpc.yml" {2-12}
+components:
+ errors:
+ - code: -32001
+ message: Authentication required
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ const: "Authentication token is required"
+ - code: -32002
+ message: Invalid authentication
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ const: "Invalid or expired authentication token"
+```
+
+这些错误代码遵循 JSON-RPC 2.0 约定,同时为 API 消费者提供清晰的身份验证反馈。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/automation.mdx b/fern/translations/zh/products/api-def/openrpc/automation.mdx
new file mode 100644
index 000000000..0ee2204d6
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/automation.mdx
@@ -0,0 +1,317 @@
+---
+title: 同步 OpenRPC 规范
+subtitle: 自动化 OpenRPC 规范同步,保持 SDK 和文档的最新状态。使用 Fern 设置 GitHub Actions、webhook 和 CI/CD 集成。
+sidebar-title: 同步 OpenRPC 规范
+---
+
+保持 OpenRPC 规范与代码库同步对于维护准确的 SDK 和文档至关重要。Fern 提供多种自动化选项来简化这一过程。
+
+## GitHub Actions
+
+使用 Fern 的 GitHub Action 在 OpenRPC 规范发生变化时自动更新 SDK 和文档:
+
+```yaml title=".github/workflows/fern.yml"
+name: Fern
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ fern-check:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Check OpenRPC spec
+ uses: fern-api/action@v0
+ with:
+ command: check
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+
+ fern-generate:
+ runs-on: ubuntu-latest
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Generate SDKs and docs
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## Webhook 集成
+
+设置 webhook 在 OpenRPC 规范更新时触发 SDK 生成:
+
+```yaml title="generators.yml" {4-8}
+api:
+ specs:
+ - spec: openrpc.yml
+ github:
+ repository: your-org/your-repo
+ webhooks:
+ - url: https://your-api.com/webhooks/fern
+ events: [generate]
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@your-org/jsonrpc-sdk"
+```
+
+## 从源自动同步
+
+配置 Fern 自动从各种源拉取 OpenRPC 规范:
+
+### 从 URL
+```yaml title="generators.yml" {3-4}
+api:
+ specs:
+ - spec: https://api.yourcompany.com/openrpc.yml
+ auto-sync: true
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+### 从 git 仓库
+```yaml title="generators.yml" {3-7}
+api:
+ specs:
+ - spec:
+ git:
+ repository: https://github.com/your-org/api-specs
+ path: openrpc/api.yml
+ branch: main
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+## CI/CD 集成
+
+### CircleCI
+```yaml title=".circleci/config.yml" {15-23}
+version: 2.1
+
+orbs:
+ fern: fernapi/fern@1.0
+
+workflows:
+ version: 2
+ build-and-test:
+ jobs:
+ - build
+ - test:
+ requires:
+ - build
+ - fern/generate:
+ requires:
+ - test
+ filters:
+ branches:
+ only: main
+ context:
+ - fern-context
+```
+
+### GitLab CI
+```yaml title=".gitlab-ci.yml" {13-20}
+stages:
+ - build
+ - test
+ - generate
+
+variables:
+ FERN_TOKEN: $FERN_TOKEN
+
+build:
+ stage: build
+ script:
+ - echo "Building JSON-RPC service..."
+
+generate-sdks:
+ stage: generate
+ image: fernapi/fern:latest
+ script:
+ - fern generate
+ only:
+ - main
+```
+
+## 定期更新
+
+设置定期更新以确保 SDK 保持最新状态:
+
+```yaml title=".github/workflows/scheduled-update.yml"
+name: Scheduled OpenRPC Update
+
+on:
+ schedule:
+ - cron: '0 2 * * 1' # Every Monday at 2 AM UTC
+ workflow_dispatch:
+
+jobs:
+ update-specs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Update OpenRPC specs
+ run: |
+ curl -o fern/openrpc/openrpc.yml https://api.yourcompany.com/openrpc.yml
+
+ - name: Generate with latest spec
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## 从 JSON-RPC 服务器生成代码
+
+对于能够生成自己的 OpenRPC 规范的服务器:
+
+```yaml title=".github/workflows/auto-generate.yml"
+name: Auto-generate from JSON-RPC server
+
+on:
+ push:
+ paths:
+ - 'src/**/*.py' # Trigger on server code changes
+ - 'src/**/*.js'
+ - 'src/**/*.ts'
+
+jobs:
+ generate-spec:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+
+ - name: Setup environment
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.9'
+
+ - name: Install dependencies
+ run: |
+ pip install -r requirements.txt
+
+ - name: Generate OpenRPC spec
+ run: |
+ python scripts/generate_openrpc.py --output fern/openrpc/openrpc.yml
+
+ - name: Generate SDKs
+ uses: fern-api/action@v0
+ with:
+ command: generate
+ env:
+ FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
+```
+
+## 监控变更
+
+跟踪 OpenRPC 规范的变更:
+
+```yaml title="generators.yml" {4-9}
+api:
+ specs:
+ - spec: openrpc.yml
+ change-detection:
+ enabled: true
+ breaking-changes: error
+ notifications:
+ slack: ${{ secrets.SLACK_WEBHOOK }}
+ email: team@yourcompany.com
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+## 多环境同步
+
+为不同环境同步不同的规范:
+
+```yaml title="generators.yml" {3-7, 12-16, 21-25}
+environments:
+ production:
+ specs:
+ - spec: https://api.prod.yourcompany.com/openrpc.yml
+ overlays:
+ - prod-overlay.yml
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@yourcompany/prod-sdk"
+ staging:
+ specs:
+ - spec: https://api.staging.yourcompany.com/openrpc.yml
+ overlays:
+ - staging-overlay.yml
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: npm
+ package-name: "@yourcompany/staging-sdk"
+ development:
+ specs:
+ - spec: http://localhost:8080/openrpc.yml
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+ output:
+ location: local
+ path: ./generated-sdk
+```
+
+## JSON-RPC 服务器内省
+
+对于支持 OpenRPC 发现的服务器:
+
+```python title="scripts/sync_from_server.py"
+import requests
+import yaml
+import json
+
+def fetch_openrpc_spec(server_url):
+ """Fetch OpenRPC spec from a JSON-RPC server that supports introspection"""
+ payload = {
+ "jsonrpc": "2.0",
+ "method": "rpc.discover",
+ "id": 1
+ }
+
+ response = requests.post(f"{server_url}/rpc", json=payload)
+ spec = response.json()["result"]
+
+ return spec
+
+def save_spec_as_yaml(spec, output_path):
+ """Convert JSON spec to YAML and save"""
+ with open(output_path, 'w') as f:
+ yaml.dump(spec, f, default_flow_style=False)
+
+if __name__ == "__main__":
+ spec = fetch_openrpc_spec("https://api.yourcompany.com")
+ save_spec_as_yaml(spec, "fern/openrpc/openrpc.yml")
+```
+
+这确保了对 OpenRPC 规范的任何破坏性更改都能被检测到,并且在更改传播到 SDK 和文档之前,相关团队成员会收到通知。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/audiences.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/audiences.mdx
new file mode 100644
index 000000000..97333977a
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/audiences.mdx
@@ -0,0 +1,297 @@
+---
+title: 使用受众过滤您的 API
+headline: 使用受众过滤您的 API (OpenRPC)
+subtitle: 使用 `x-fern-audiences` 过滤相关方法、参数和模式
+sidebar-title: 使用受众过滤 API
+---
+
+受众是一个有用的工具,用于为不同的消费者分割您的 JSON-RPC API。常见的受众示例包括 `public`
+和 `beta`。
+
+
+ 记住在指定受众后过滤您的 SDK 和文档。如果**未指定受众**,
+ 将不会过滤任何内容。
+
+
+
+
+以下示例配置 SDK 过滤到 `public` 受众:
+
+```yaml title="generators.yml" {3-4}
+groups:
+ sdks:
+ audiences:
+ - public
+ generators:
+ - name: fernapi/fern-typescript-sdk
+ version: 0.8.8
+```
+
+
+
+以下示例配置文档过滤到 `public` 受众:
+
+```yaml title="docs.yml" {3-4}
+navigation:
+ - api: API Reference
+ audiences:
+ - public
+```
+
+
+
+
+
+## 过滤方法
+
+向方法添加 `x-fern-audiences` 来控制特定受众包含哪些方法:
+
+```yaml title="openrpc.yml" {5-6, 12-13}
+methods:
+ - name: public.getInfo
+ summary: Get public API information
+ description: Publicly available information about the API
+ x-fern-audiences:
+ - public
+ params: []
+ result:
+ name: info
+ schema:
+ $ref: '#/components/schemas/ApiInfo'
+ - name: admin.getUsers
+ summary: Get all users (admin only)
+ x-fern-audiences:
+ - admin
+ params:
+ - name: limit
+ schema:
+ type: integer
+ default: 100
+ result:
+ name: users
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+```
+
+## 过滤方法参数
+
+您可以过滤方法内的特定参数:
+
+```yaml title="openrpc.yml" {8-9, 14-15}
+methods:
+ - name: user.create
+ summary: Create a new user
+ params:
+ - name: userData
+ schema:
+ type: object
+ properties:
+ email:
+ type: string
+ format: email
+ name:
+ type: string
+ adminNotes:
+ type: string
+ x-fern-audiences:
+ - admin
+ internalId:
+ type: string
+ x-fern-audiences:
+ - internal
+ required:
+ - email
+ - name
+ required: true
+ result:
+ name: user
+ schema:
+ $ref: '#/components/schemas/User'
+```
+
+## 过滤模式
+
+将整个模式过滤到不同的受众:
+
+```yaml title="openrpc.yml" {5-6, 20-21}
+components:
+ schemas:
+ PublicUser:
+ type: object
+ x-fern-audiences:
+ - public
+ properties:
+ id:
+ type: string
+ name:
+ type: string
+ email:
+ type: string
+ required:
+ - id
+ - name
+ - email
+ AdminUser:
+ allOf:
+ - $ref: '#/components/schemas/PublicUser'
+ - type: object
+ x-fern-audiences:
+ - admin
+ properties:
+ role:
+ type: string
+ permissions:
+ type: array
+ items:
+ type: string
+ createdAt:
+ type: string
+ format: date-time
+ lastLoginAt:
+ type: string
+ format: date-time
+```
+
+## 过滤模式属性
+
+您可以过滤模式内的各个属性:
+
+```yaml title="openrpc.yml" {9-10, 13-14, 17-18}
+components:
+ schemas:
+ Order:
+ type: object
+ properties:
+ id:
+ type: string
+ amount:
+ type: number
+ x-fern-audiences:
+ - public
+ internalCost:
+ type: number
+ x-fern-audiences:
+ - internal
+ debugInfo:
+ type: object
+ x-fern-audiences:
+ - debug
+ customerInfo:
+ type: object
+ properties:
+ id:
+ type: string
+ email:
+ type: string
+ x-fern-audiences:
+ - admin
+```
+
+## 过滤错误响应
+
+根据受众过滤错误信息:
+
+```yaml title="openrpc.yml" {7-12, 14-19}
+methods:
+ - name: payment.process
+ summary: Process a payment
+ params:
+ - name: paymentData
+ schema:
+ $ref: '#/components/schemas/PaymentRequest'
+ errors:
+ - code: -32001
+ message: Payment failed
+ x-fern-audiences:
+ - public
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ const: "Payment could not be processed"
+ - code: -32001
+ message: Payment failed
+ x-fern-audiences:
+ - admin
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ errorCode:
+ type: string
+ gatewayResponse:
+ type: object
+ debugTrace:
+ type: string
+```
+
+## 服务器级别过滤
+
+在服务器级别应用受众过滤:
+
+```yaml title="openrpc.yml" {4-5, 10-11}
+servers:
+ - name: public-api
+ url: https://api.example.com/rpc
+ x-fern-audiences:
+ - public
+ description: Public API server
+ - name: admin-api
+ url: https://admin-api.example.com/rpc
+ x-fern-audiences:
+ - admin
+ description: Admin API server with additional privileges
+```
+
+## 条件方法可用性
+
+使用受众使方法仅在特定上下文中可用:
+
+```yaml title="openrpc.yml" {5-6, 15-16, 25-26}
+methods:
+ - name: debug.getSystemInfo
+ summary: Get system debug information
+ description: Internal system information for debugging
+ x-fern-audiences:
+ - debug
+ params: []
+ result:
+ name: systemInfo
+ schema:
+ type: object
+ additionalProperties: true
+ - name: beta.advancedSearch
+ summary: Advanced search functionality
+ x-fern-audiences:
+ - beta
+ params:
+ - name: query
+ schema:
+ type: object
+ properties:
+ text:
+ type: string
+ filters:
+ type: object
+ additionalProperties: true
+ result:
+ name: results
+ schema:
+ $ref: '#/components/schemas/SearchResults'
+ - name: internal.resetCache
+ summary: Reset internal caches
+ x-fern-audiences:
+ - internal
+ params:
+ - name: cacheType
+ schema:
+ type: string
+ enum: [user, product, session, all]
+ # Notification - no result expected
+```
+
+这允许您为不同类型的消费者创建同一个 JSON-RPC API 的不同视图,确保每个受众只看到与其用例相关的方法和数据。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/availability.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/availability.mdx
new file mode 100644
index 000000000..767038674
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/availability.mdx
@@ -0,0 +1,25 @@
+---
+title: 可用性
+sidebar-title: 可用性
+headline: 可用性 (OpenRPC)
+description: 使用 `x-fern-availability` 扩展标记特定 SDK 版本中可用的功能
+---
+
+在特定 SDK 版本中标记功能为可用:
+
+```yaml title="openrpc.yml" {4-6}
+methods:
+ - name: beta.advancedSearch
+ summary: Advanced search functionality
+ x-fern-availability:
+ status: beta
+ message: "This feature is in beta and may change"
+ params:
+ - name: searchQuery
+ schema:
+ $ref: '#/components/schemas/AdvancedSearchQuery'
+ result:
+ name: searchResults
+ schema:
+ $ref: '#/components/schemas/SearchResults'
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/examples.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/examples.mdx
new file mode 100644
index 000000000..01618218e
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/examples.mdx
@@ -0,0 +1,53 @@
+---
+title: 请求 + 响应示例
+headline: 请求 + 响应示例 (OpenRPC)
+description: 使用 x-fern-examples 为 OpenRPC 方法添加多个请求和响应示例。通过真实的用例改善您的 SDK 文档。
+og:title: OpenRPC 请求 + 响应示例
+sidebar-title: 请求 + 响应示例
+---
+
+
+为更好的 SDK 文档提供额外的示例:
+
+```yaml title="openrpc.yml" {8-25}
+methods:
+ - name: user.create
+ summary: Create a new user
+ params:
+ - name: userData
+ schema:
+ $ref: '#/components/schemas/CreateUserRequest'
+ required: true
+ x-fern-examples:
+ - name: StandardUser
+ description: Create a regular user account
+ params:
+ userData:
+ email: "john@example.com"
+ name: "John Doe"
+ role: "user"
+ result:
+ id: "user_123"
+ email: "john@example.com"
+ name: "John Doe"
+ role: "user"
+ createdAt: "2024-01-15T10:30:00Z"
+ - name: AdminUser
+ description: Create an admin user account
+ params:
+ userData:
+ email: "admin@example.com"
+ name: "Admin User"
+ role: "admin"
+ permissions: ["read", "write", "delete"]
+ result:
+ id: "user_456"
+ email: "admin@example.com"
+ name: "Admin User"
+ role: "admin"
+ createdAt: "2024-01-15T10:30:00Z"
+ result:
+ name: user
+ schema:
+ $ref: '#/components/schemas/User'
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/ignore.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/ignore.mdx
new file mode 100644
index 000000000..41b0d5193
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/ignore.mdx
@@ -0,0 +1,31 @@
+---
+title: 忽略方法或模式
+headline: 忽略方法或模式 (OpenRPC)
+description: 使用 `x-fern-ignore` 扩展跳过读取特定 OpenRPC 元素
+sidebar-title: 忽略方法或模式
+---
+
+使用 `x-fern-ignore` 从 SDK 生成中排除特定方法或模式:
+
+```yaml title="openrpc.yml" {4-5, 12-13}
+methods:
+ - name: debug.internalMethod
+ summary: Internal debugging method
+ x-fern-ignore: true
+ params:
+ - name: debugData
+ schema:
+ type: object
+ result:
+ name: debugResult
+ schema:
+ type: object
+ - name: test.experimentalFeature
+ summary: Experimental feature (not ready for public use)
+ x-fern-ignore: true
+ params: []
+ result:
+ name: result
+ schema:
+ type: string
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/method-names.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/method-names.mdx
new file mode 100644
index 000000000..e4076294d
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/method-names.mdx
@@ -0,0 +1,230 @@
+---
+title: SDK 方法名称
+headline: SDK 方法名称 (OpenRPC)
+description: 在 OpenRPC 规范中控制 SDK 方法名称。使用 `x-fern-sdk-method-name` 为您的 JSON-RPC API 定义直观的、特定语言的方法名称。
+sidebar-title: SDK 方法名称
+---
+
+默认情况下,Fern 基于您的 OpenRPC 方法名称生成 SDK 方法名称。您可以使用 `x-fern-sdk-method-name` 扩展来覆盖此行为。
+
+## 自定义方法名称
+
+使用 `x-fern-sdk-method-name` 为您的 JSON-RPC 方法指定自定义方法名称:
+
+```yaml title="openrpc.yml" {4-5, 12-13}
+methods:
+ - name: user.getById
+ summary: Get user by ID
+ x-fern-sdk-method-name: getUser
+ params:
+ - name: id
+ schema:
+ type: string
+ required: true
+ result:
+ name: user
+ schema:
+ $ref: '#/components/schemas/User'
+ - name: order.createNew
+ summary: Create a new order
+ x-fern-sdk-method-name: create
+ params:
+ - name: orderData
+ schema:
+ $ref: '#/components/schemas/CreateOrderRequest'
+ required: true
+ result:
+ name: order
+ schema:
+ $ref: '#/components/schemas/Order'
+```
+
+这将生成如下的 SDK 方法:
+
+```typescript
+// 代替 client.user.getById()
+const user = await client.user.getUser({ id: "user_123" });
+
+// 代替 client.order.createNew()
+const order = await client.order.create({ orderData: {...} });
+```
+
+## 方法命名约定
+
+在命名 SDK 方法时遵循这些约定:
+
+### CRUD 操作
+使用标准的 CRUD 命名:
+
+```yaml title="openrpc.yml" {4-5}
+methods:
+ - name: user.createUser
+ summary: Create a new user
+ x-fern-sdk-method-name: create
+ # 生成: client.user.create()
+
+ - name: user.getUserById
+ summary: Get user by ID
+ x-fern-sdk-method-name: get
+ # 生成: client.user.get()
+
+ - name: user.updateUser
+ summary: Update user information
+ x-fern-sdk-method-name: update
+ # 生成: client.user.update()
+
+ - name: user.deleteUser
+ summary: Delete a user
+ x-fern-sdk-method-name: delete
+ # 生成: client.user.delete()
+```
+
+### 列表操作
+为列表操作使用描述性名称:
+
+```yaml title="openrpc.yml" {4-5}
+methods:
+ - name: user.getAllUsers
+ summary: Get all users
+ x-fern-sdk-method-name: list
+ # 生成: client.user.list()
+
+ - name: user.searchUsers
+ summary: Search for users
+ x-fern-sdk-method-name: search
+ # 生成: client.user.search()
+
+ - name: order.getUserOrders
+ summary: Get orders for a user
+ x-fern-sdk-method-name: listByUser
+ # 生成: client.order.listByUser()
+```
+
+### 动作操作
+使用面向动作的名称:
+
+```yaml title="openrpc.yml" {4-5}
+methods:
+ - name: email.sendNotification
+ summary: Send email notification
+ x-fern-sdk-method-name: send
+ # 生成: client.email.send()
+
+ - name: payment.processPayment
+ summary: Process a payment
+ x-fern-sdk-method-name: process
+ # 生成: client.payment.process()
+
+ - name: cache.invalidateCache
+ summary: Invalidate cache entries
+ x-fern-sdk-method-name: invalidate
+ # 生成: client.cache.invalidate()
+```
+
+## 特定语言的方法名称
+
+您可以为不同的编程语言指定不同的方法名称:
+
+```yaml title="openrpc.yml" {4-9}
+methods:
+ - name: user.getUserPreferences
+ summary: Get user preferences
+ x-fern-sdk-method-name:
+ python: get_preferences
+ typescript: getPreferences
+ go: GetPreferences
+ java: getPreferences
+ csharp: GetPreferences
+ params:
+ - name: userId
+ schema:
+ type: string
+ required: true
+ result:
+ name: preferences
+ schema:
+ $ref: '#/components/schemas/UserPreferences'
+```
+
+## 命名空间方法名称
+
+对于带有命名空间前缀的方法,自定义最终的方法名称:
+
+```yaml title="openrpc.yml" {4-5, 12-13}
+methods:
+ - name: analytics.track.pageView
+ summary: Track page view event
+ x-fern-sdk-method-name: trackPageView
+ params:
+ - name: eventData
+ schema:
+ $ref: '#/components/schemas/PageViewEvent'
+ required: true
+ - name: analytics.track.conversion
+ summary: Track conversion event
+ x-fern-sdk-method-name: trackConversion
+ params:
+ - name: eventData
+ schema:
+ $ref: '#/components/schemas/ConversionEvent'
+ required: true
+```
+
+生成:
+```typescript
+await client.analytics.trackPageView({ eventData: {...} });
+await client.analytics.trackConversion({ eventData: {...} });
+```
+
+## 通知方法名称
+
+对于通知方法(单向调用),使用适当的命名:
+
+```yaml title="openrpc.yml" {4-5, 12-13}
+methods:
+ - name: log.recordError
+ summary: Record an error event
+ x-fern-sdk-method-name: logError
+ params:
+ - name: errorData
+ schema:
+ $ref: '#/components/schemas/ErrorData'
+ required: true
+ # 无结果 - 这是一个通知
+ - name: metrics.incrementCounter
+ summary: Increment a metric counter
+ x-fern-sdk-method-name: increment
+ params:
+ - name: metric
+ schema:
+ type: string
+ required: true
+ - name: value
+ schema:
+ type: number
+ default: 1
+ # 无结果 - 这是一个通知
+```
+
+## 异步方法命名
+
+对于返回 promise 或 future 的方法,考虑异步命名:
+
+```yaml title="openrpc.yml" {4-5}
+methods:
+ - name: report.generateReport
+ summary: Generate a report (long-running)
+ x-fern-sdk-method-name: generateAsync
+ params:
+ - name: reportConfig
+ schema:
+ $ref: '#/components/schemas/ReportConfig'
+ required: true
+ result:
+ name: jobId
+ schema:
+ type: string
+ description: Job ID for tracking report generation
+```
+
+这确保方法名称遵循每个目标语言的约定,同时为开发者维护清晰直观的 API。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/sdk-group-name.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/sdk-group-name.mdx
new file mode 100644
index 000000000..daed5de4a
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/sdk-group-name.mdx
@@ -0,0 +1,37 @@
+---
+title: SDK 组名称
+sidebar-title: SDK 组名称
+headline: SDK 组名称 (OpenRPC)
+description: 学习如何在 OpenRPC 中使用 x-fern-sdk-group-name 将相关方法组织成逻辑组,以获得更清洁、更直观的 SDK 代码。
+---
+
+在 SDK 中将相关方法分组:
+
+```yaml title="openrpc.yml" {4-5, 12-13}
+methods:
+ - name: user.create
+ summary: Create user
+ x-fern-sdk-group-name: users
+ params: [...]
+ result: {...}
+
+ - name: user.get
+ summary: Get user
+ x-fern-sdk-group-name: users
+ params: [...]
+ result: {...}
+
+ - name: order.create
+ summary: Create order
+ x-fern-sdk-group-name: orders
+ params: [...]
+ result: {...}
+```
+
+这会生成具有分组方法的 SDK:
+
+```typescript
+client.users.create(...)
+client.users.get(...)
+client.orders.create(...)
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/extensions/server-name.mdx b/fern/translations/zh/products/api-def/openrpc/extensions/server-name.mdx
new file mode 100644
index 000000000..5b0bd20df
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/extensions/server-name.mdx
@@ -0,0 +1,20 @@
+---
+title: 服务器名称
+headline: 服务器名称 (OpenRPC)
+description: 使用 `x-fern-server-name` 扩展为服务器指定自定义名称
+sidebar-title: 服务器名称
+---
+
+为服务器指定自定义名称:
+
+```yaml title="openrpc.yml" {3-4}
+servers:
+ - name: production
+ url: https://api.yourcompany.com/rpc
+ x-fern-server-name: Production
+ description: Production JSON-RPC server
+ - name: staging
+ url: https://staging-api.yourcompany.com/rpc
+ x-fern-server-name: Staging
+ description: Staging environment
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/methods/rpc-methods.mdx b/fern/translations/zh/products/api-def/openrpc/methods/rpc-methods.mdx
new file mode 100644
index 000000000..088490d5b
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/methods/rpc-methods.mdx
@@ -0,0 +1,278 @@
+---
+title: JSON-RPC 方法
+subtitle: 使用参数、结果和错误处理来记录 JSON-RPC 方法
+sidebar-title: JSON-RPC 方法
+---
+
+OpenRPC 中的方法是 JSON-RPC API 的核心构建块。每个方法都定义了过程名称、参数、返回值和潜在错误。
+
+```yml title="openrpc.yml" {2-19}
+methods:
+ - name: user.create
+ summary: Create a new user
+ description: Creates a new user account with the provided information
+ params:
+ - name: userData
+ schema:
+ $ref: '#/components/schemas/CreateUserRequest'
+ required: true
+ description: User data for account creation
+ result:
+ name: createdUser
+ schema:
+ $ref: '#/components/schemas/User'
+ description: The newly created user object
+ examples:
+ - name: CreateUserExample
+ description: Example of creating a user
+ params:
+ userData:
+ email: "john@example.com"
+ name: "John Doe"
+ age: 30
+ result:
+ id: "user_123"
+ email: "john@example.com"
+ name: "John Doe"
+ age: 30
+ createdAt: "2024-01-15T10:30:00Z"
+```
+
+## 方法参数
+
+JSON-RPC 中的参数可以是位置参数(按位置)或命名参数(按名称):
+
+### 命名参数
+```yml title="openrpc.yml" {4-14}
+methods:
+ - name: calculate.add
+ summary: Add two numbers
+ paramStructure: by-name
+ params:
+ - name: a
+ schema:
+ type: number
+ required: true
+ description: First number
+ - name: b
+ schema:
+ type: number
+ required: true
+ description: Second number
+ result:
+ name: sum
+ schema:
+ type: number
+```
+
+### 位置参数
+```yml title="openrpc.yml" {4-12}
+methods:
+ - name: calculate.multiply
+ summary: Multiply two numbers
+ paramStructure: by-position
+ params:
+ - schema:
+ type: number
+ description: First number (multiplicand)
+ - schema:
+ type: number
+ description: Second number (multiplier)
+ result:
+ name: product
+ schema:
+ type: number
+```
+
+## 复杂参数类型
+
+为方法参数使用复杂的模式:
+
+```yml title="openrpc.yml" {6-24}
+methods:
+ - name: order.create
+ summary: Create a new order
+ description: Creates a new order with items and shipping information
+ params:
+ - name: orderData
+ schema:
+ type: object
+ properties:
+ items:
+ type: array
+ items:
+ $ref: '#/components/schemas/OrderItem'
+ minItems: 1
+ shippingAddress:
+ $ref: '#/components/schemas/Address'
+ paymentMethod:
+ type: string
+ enum: [credit_card, paypal, bank_transfer]
+ notes:
+ type: string
+ maxLength: 500
+ required:
+ - items
+ - shippingAddress
+ - paymentMethod
+ required: true
+ result:
+ name: order
+ schema:
+ $ref: '#/components/schemas/Order'
+```
+
+## 方法结果
+
+定义成功方法响应的结构:
+
+```yml title="openrpc.yml" {8-20}
+methods:
+ - name: search.products
+ summary: Search for products
+ params:
+ - name: query
+ schema:
+ type: string
+ required: true
+ result:
+ name: searchResults
+ schema:
+ type: object
+ properties:
+ products:
+ type: array
+ items:
+ $ref: '#/components/schemas/Product'
+ totalCount:
+ type: integer
+ hasMore:
+ type: boolean
+ nextCursor:
+ type: string
+ required:
+ - products
+ - totalCount
+ - hasMore
+```
+
+## 错误处理
+
+为您的方法定义自定义错误:
+
+```yml title="openrpc.yml" {10-24}
+methods:
+ - name: user.login
+ summary: Authenticate user
+ params:
+ - name: email
+ schema:
+ type: string
+ format: email
+ required: true
+ errors:
+ - code: -32001
+ message: Invalid credentials
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ const: "Email or password is incorrect"
+ - code: -32002
+ message: Account locked
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ const: "Account temporarily locked due to failed login attempts"
+ unlockTime:
+ type: string
+ format: date-time
+ result:
+ name: authResult
+ schema:
+ $ref: '#/components/schemas/AuthToken'
+```
+
+## 方法示例
+
+提供全面的示例以获得更好的文档:
+
+```yml title="openrpc.yml" {12-35}
+methods:
+ - name: file.upload
+ summary: Upload a file
+ params:
+ - name: fileData
+ schema:
+ type: object
+ properties:
+ filename:
+ type: string
+ content:
+ type: string
+ format: base64
+ mimeType:
+ type: string
+ required: true
+ examples:
+ - name: ImageUpload
+ description: Upload a JPEG image
+ params:
+ fileData:
+ filename: "photo.jpg"
+ content: "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAABAAEDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAv/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwC/gA=="
+ mimeType: "image/jpeg"
+ result:
+ fileId: "file_abc123"
+ url: "https://cdn.example.com/files/file_abc123.jpg"
+ size: 1024000
+ - name: DocumentUpload
+ description: Upload a PDF document
+ params:
+ fileData:
+ filename: "document.pdf"
+ content: "JVBERi0xLjQKJdPr6eEKMSAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMiAwIFIKPj4KZW5kb2JqCgoyIDAgb2JqCjw8Ci9UeXBlIC9QYWdlcwo="
+ mimeType: "application/pdf"
+ result:
+ fileId: "file_def456"
+ url: "https://cdn.example.com/files/file_def456.pdf"
+ size: 256000
+```
+
+## 可选参数
+
+定义带有默认值的可选参数:
+
+```yml title="openrpc.yml" {6-19}
+methods:
+ - name: report.generate
+ summary: Generate a report
+ params:
+ - name: reportType
+ schema:
+ type: string
+ enum: [daily, weekly, monthly, yearly]
+ required: true
+ - name: format
+ schema:
+ type: string
+ enum: [pdf, csv, json]
+ default: pdf
+ required: false
+ description: Output format (defaults to PDF)
+ - name: includeCharts
+ schema:
+ type: boolean
+ default: true
+ required: false
+ description: Include charts in the report
+ result:
+ name: report
+ schema:
+ $ref: '#/components/schemas/Report'
+```
+
+方法是 JSON-RPC API 的基础,提供了一个清晰的契约来说明哪些操作是可用的、它们期望什么数据以及返回什么。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/overview.mdx b/fern/translations/zh/products/api-def/openrpc/overview.mdx
new file mode 100644
index 000000000..cbfe5a3ba
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/overview.mdx
@@ -0,0 +1,210 @@
+---
+title: 什么是 OpenRPC 规范?
+description: 了解如何使用 OpenRPC 规范与 Fern 来文档化 JSON-RPC API。设置您的 fern 文件夹并配置 OpenRPC v1.3.2 或 v1.2.6。
+sidebar-title: 什么是 OpenRPC 规范?
+---
+
+
+
+
+OpenRPC 规范是开发人员用来文档化 JSON-RPC API 的框架。该规范使用 JSON 或 YAML 编写,包含您的所有方法、参数、模式和服务器配置。Fern 兼容 OpenRPC 规范 [v1.3.2](https://spec.open-rpc.org/) 和 [v1.2.6](https://github.com/open-rpc/spec/releases/tag/1.2.6)。
+
+以下是 OpenRPC 文件的示例:
+
+```yaml openrpc.yml
+openrpc: 1.3.2
+info:
+ title: Calculator API
+ version: 1.0.0
+ description: |
+ A simple calculator API that performs basic arithmetic operations
+ using JSON-RPC 2.0 protocol.
+servers:
+ - name: production
+ url: https://api.calculator.com/rpc
+ description: Production JSON-RPC server
+ - name: development
+ url: http://localhost:8080/rpc
+ description: Development server
+methods:
+ - name: add
+ summary: Add two numbers
+ description: Performs addition of two numeric values
+ params:
+ - name: a
+ schema:
+ type: number
+ required: true
+ description: First number to add
+ - name: b
+ schema:
+ type: number
+ required: true
+ description: Second number to add
+ result:
+ name: sum
+ schema:
+ type: number
+ description: The sum of the two numbers
+ examples:
+ - name: AddExample
+ description: Example of adding two numbers
+ params:
+ a: 5
+ b: 3
+ result: 8
+ - name: divide
+ summary: Divide two numbers
+ description: Performs division of two numeric values
+ params:
+ - name: dividend
+ schema:
+ type: number
+ required: true
+ description: Number to be divided
+ - name: divisor
+ schema:
+ type: number
+ required: true
+ description: Number to divide by
+ result:
+ name: quotient
+ schema:
+ type: number
+ description: The result of the division
+ errors:
+ - code: -32602
+ message: Division by zero
+ data:
+ type: object
+ properties:
+ error:
+ type: string
+ const: "Cannot divide by zero"
+ examples:
+ - name: DivideExample
+ description: Example of dividing two numbers
+ params:
+ dividend: 10
+ divisor: 2
+ result: 5
+ - name: notify_calculation
+ summary: Notify about calculation
+ description: Send a notification about a completed calculation (no response expected)
+ params:
+ - name: operation
+ schema:
+ type: string
+ enum: [add, subtract, multiply, divide]
+ required: true
+ - name: result
+ schema:
+ type: number
+ required: true
+ - name: timestamp
+ schema:
+ type: string
+ format: date-time
+ required: true
+components:
+ schemas:
+ CalculationRequest:
+ type: object
+ properties:
+ operation:
+ type: string
+ enum: [add, subtract, multiply, divide]
+ operands:
+ type: array
+ items:
+ type: number
+ minItems: 2
+ maxItems: 2
+ precision:
+ type: integer
+ minimum: 0
+ maximum: 10
+ default: 2
+ required:
+ - operation
+ - operands
+ CalculationResult:
+ type: object
+ properties:
+ result:
+ type: number
+ operation:
+ type: string
+ timestamp:
+ type: string
+ format: date-time
+ required:
+ - result
+ - operation
+ - timestamp
+```
+
+## 设置您的 fern 文件夹
+
+ 正在考虑生成 OpenRPC 规范的选项?在[这里](https://fern-community.slack.com/join/shared_invite/zt-2dpftfmif-MuAegl8AfP_PK8s2tx350Q%EF%BB%BF#/shared-invite/email)获取实时支持
+
+
+
+在项目根目录中创建一个 `fern/` 文件夹。
+
+```
+fern/
+```
+
+
+将您的 OpenRPC 规范添加到 fern 目录中。您可以将其放在名为 `openrpc` 的子文件夹中,或直接放在 fern 目录中。
+
+```
+fern/
+ └─ openrpc/
+ └─ openrpc.yml
+```
+
+
+在您的 fern 目录中添加一个 `fern.config.json` 文件,列出您的组织和当前版本的 Fern CLI:
+
+```json title="fern.config.json"
+{
+ "organization": "your-organization",
+ "version": ""
+}
+```
+
+```
+fern/
+ ├─ fern.config.json
+ └─ openrpc/
+ └─ openrpc.yml
+```
+
+
+在您的 fern 目录中创建一个 `generators.yml` 文件,并添加对您的 OpenRPC 规范的引用:
+
+```yaml title="generators.yml"
+# Your API definition
+api:
+ specs:
+ - openrpc: ./openrpc/openrpc.yml
+
+groups:
+ external:
+ generators:
+ # Your generator configurations here
+```
+
+您的最终目录结构:
+
+```
+fern/
+ ├─ fern.config.json
+ ├─ generators.yml
+ └─ openrpc/
+ └─ openrpc.yml
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/openrpc/servers.mdx b/fern/translations/zh/products/api-def/openrpc/servers.mdx
new file mode 100644
index 000000000..b29d298d4
--- /dev/null
+++ b/fern/translations/zh/products/api-def/openrpc/servers.mdx
@@ -0,0 +1,196 @@
+---
+title: 服务器
+description: 为您的 JSON-RPC API 配置服务器 URL 和传输协议
+subtitle: 为您的 JSON-RPC API 定义服务器 URL 和传输机制
+sidebar-title: 服务器
+---
+
+
+OpenRPC 允许您指定一个或多个服务器配置,定义客户端如何连接到您的 JSON-RPC API。
+
+```yml openrpc.yml
+servers:
+ - name: production
+ url: https://api.yourcompany.com/rpc
+ description: Production HTTP JSON-RPC server
+ - name: websocket
+ url: wss://api.yourcompany.com/rpc
+ description: Production WebSocket JSON-RPC server
+```
+
+指定服务器对于 SDK 和文档都很有价值:
+- 对于 SDK,您的用户无需在客户端实例化时手动指定服务器 URL
+- 对于文档,您的 API playground 将自动连接到正确的服务器
+
+## 传输协议
+
+JSON-RPC 可以通过各种传输协议使用:
+
+### HTTP/HTTPS 传输
+```yml openrpc.yml
+servers:
+ - name: http-production
+ url: https://api.yourcompany.com/rpc
+ description: HTTPS JSON-RPC endpoint
+ - name: http-staging
+ url: https://staging-api.yourcompany.com/rpc
+ description: Staging HTTPS endpoint
+```
+
+### WebSocket 传输
+```yml openrpc.yml
+servers:
+ - name: websocket-production
+ url: wss://api.yourcompany.com/rpc
+ description: WebSocket JSON-RPC for real-time communication
+ - name: websocket-dev
+ url: ws://localhost:8080/rpc
+ description: Development WebSocket server
+```
+
+### TCP 传输
+```yml openrpc.yml
+servers:
+ - name: tcp-production
+ url: tcp://api.yourcompany.com:9090
+ description: TCP JSON-RPC server for high-performance applications
+```
+
+## 服务器变量
+
+使用变量使您的服务器配置更加灵活:
+
+```yml openrpc.yml {3-12}
+servers:
+ - name: production
+ url: https://{environment}.api.yourcompany.com/rpc
+ description: Production JSON-RPC server
+ variables:
+ environment:
+ default: prod
+ enum:
+ - prod
+ - staging
+ - dev
+ description: Environment name
+```
+
+## 多环境配置
+
+配置不同的环境并提供适当的描述:
+
+```yml openrpc.yml
+servers:
+ - name: production
+ url: https://api.yourcompany.com/rpc
+ description: Production environment - high availability, rate limited
+ - name: staging
+ url: https://staging-api.yourcompany.com/rpc
+ description: Staging environment - for testing new features
+ - name: development
+ url: http://localhost:8080/rpc
+ description: Local development server
+ - name: sandbox
+ url: https://sandbox-api.yourcompany.com/rpc
+ description: Sandbox environment - safe for testing
+```
+
+## 服务器特定配置
+
+添加服务器特定的元数据和配置:
+
+```yml openrpc.yml {4-12}
+servers:
+ - name: production
+ url: https://api.yourcompany.com/rpc
+ description: Production JSON-RPC server
+ variables:
+ version:
+ default: v1
+ enum: [v1, v2]
+ description: API version
+ summary: High-performance production server
+ tags:
+ - name: production
+ description: Production environment
+```
+
+## 负载均衡和多个 URL
+
+为负载均衡配置多个服务器 URL:
+
+```yml openrpc.yml
+servers:
+ - name: primary
+ url: https://api-primary.yourcompany.com/rpc
+ description: Primary production server
+ - name: secondary
+ url: https://api-secondary.yourcompany.com/rpc
+ description: Secondary production server (fallback)
+ - name: regional-us
+ url: https://us.api.yourcompany.com/rpc
+ description: US regional server
+ - name: regional-eu
+ url: https://eu.api.yourcompany.com/rpc
+ description: EU regional server
+```
+
+## WebSocket 特定配置
+
+配置带有连接参数的 WebSocket 服务器:
+
+```yml openrpc.yml {4-10}
+servers:
+ - name: websocket-main
+ url: wss://api.yourcompany.com/rpc
+ description: Main WebSocket JSON-RPC server
+ variables:
+ protocol:
+ default: "jsonrpc-2.0"
+ description: JSON-RPC protocol version
+ heartbeat:
+ default: "30"
+ description: Heartbeat interval in seconds
+```
+
+## 安全配置
+
+在服务器级别配置身份验证和安全性:
+
+```yml openrpc.yml {4-6}
+servers:
+ - name: secure-production
+ url: https://api.yourcompany.com/rpc
+ description: Secure production server with authentication
+ security:
+ - bearerAuth: []
+ - apiKeyAuth: []
+components:
+ securitySchemes:
+ bearerAuth:
+ type: http
+ scheme: bearer
+ apiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+```
+
+## 传输特定优化
+
+为特定用例配置服务器:
+
+```yml openrpc.yml
+servers:
+ - name: bulk-operations
+ url: https://bulk.api.yourcompany.com/rpc
+ description: Optimized for batch requests and bulk operations
+ - name: real-time
+ url: wss://realtime.api.yourcompany.com/rpc
+ description: WebSocket server optimized for real-time notifications
+ - name: analytics
+ url: https://analytics.api.yourcompany.com/rpc
+ description: Dedicated server for analytics and reporting methods
+```
+
+服务器配置帮助客户端了解如何连接到您的 JSON-RPC API,以及哪种传输机制最适合他们的用例。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/asyncapi-empty.mdx b/fern/translations/zh/products/api-def/pages/asyncapi-empty.mdx
new file mode 100644
index 000000000..4fd67a668
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/asyncapi-empty.mdx
@@ -0,0 +1,8 @@
+---
+title: AsyncAPI 定义重定向页面
+description: 这是一个用于重定向到 AsyncAPI 定义页面的空页面。
+sidebar-title: AsyncAPI 定义重定向页面
+---
+
+
+此页面为空。请访问 [AsyncAPI 定义](/api-definitions/asyncapi/overview) 页面获取更多信息。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/ferndef-empty.mdx b/fern/translations/zh/products/api-def/pages/ferndef-empty.mdx
new file mode 100644
index 000000000..1e4382560
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/ferndef-empty.mdx
@@ -0,0 +1,8 @@
+---
+title: Fern 定义重定向页面
+description: 这是一个用于重定向到 Fern 定义页面的空白页面。
+sidebar-title: Fern 定义重定向页面
+---
+
+
+此页面为空。请访问 [Fern 定义](/api-definitions/ferndef/overview) 页面获取更多信息。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/grpc-empty.mdx b/fern/translations/zh/products/api-def/pages/grpc-empty.mdx
new file mode 100644
index 000000000..0c8da60a7
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/grpc-empty.mdx
@@ -0,0 +1,8 @@
+---
+title: gRPC 定义重定向页面
+description: 这是一个用于重定向到 gRPC 定义页面的空页面。
+sidebar-title: gRPC 定义重定向页面
+---
+
+
+此页面为空。请访问 [gRPC 定义](/api-definitions/grpc/overview) 页面获取更多信息。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/openapi-empty.mdx b/fern/translations/zh/products/api-def/pages/openapi-empty.mdx
new file mode 100644
index 000000000..37aa06162
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/openapi-empty.mdx
@@ -0,0 +1,8 @@
+---
+title: OpenAPI 定义重定向页面
+description: 这是一个用于重定向到 OpenAPI 定义页面的空白页面。
+sidebar-title: OpenAPI 定义重定向页面
+---
+
+
+此页面为空。请访问 [OpenAPI 定义](/api-definitions/openapi/overview) 页面获取更多信息。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/openrpc-empty.mdx b/fern/translations/zh/products/api-def/pages/openrpc-empty.mdx
new file mode 100644
index 000000000..24938a12c
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/openrpc-empty.mdx
@@ -0,0 +1,8 @@
+---
+title: OpenRPC 定义重定向页面
+description: 这是一个用于重定向到 OpenRPC 定义页面的空页面。
+sidebar-title: OpenRPC 定义重定向页面
+---
+
+
+此页面为空。请访问 [OpenRPC 定义](/api-definitions/openrpc/overview) 页面获取更多信息。
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/overrides.mdx b/fern/translations/zh/products/api-def/pages/overrides.mdx
new file mode 100644
index 000000000..be985c1b2
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/overrides.mdx
@@ -0,0 +1,191 @@
+---
+title: 覆盖
+description: 使用单独的覆盖文件自定义您的 API 定义。
+sidebar-title: 覆盖
+---
+
+使用覆盖文件可以在不修改原始规范的情况下自定义您的 OpenAPI、AsyncAPI 或 OpenRPC 定义。这在以下情况下很有用:
+
+* 您的 API 规范是从服务器代码自动生成的
+* 您需要为 SDK 和文档配置不同的设置
+
+覆盖功能适用于 OpenAPI、AsyncAPI 和 OpenRPC 规范。对于 [Fern Definition](/api-definitions/ferndef/overview) 不需要覆盖,因为您可以直接编辑这些文件。
+
+
+ 对于 OpenAPI 规范,Fern 建议使用 [叠加层](/learn/api-definitions/openapi/overlays) 而不是覆盖。叠加层遵循官方 [OpenAPI 叠加层规范](https://spec.openapis.org/overlay/v1.0.0.html),支持使用 JSONPath 通配符进行批量更改,并且在 OpenAPI 生态系统中具有可移植性。
+
+ 覆盖功能也完全受支持。如果覆盖对您的团队有效,则无需切换。您也可以同时使用两者(首先应用覆盖,然后应用叠加层)。
+
+
+## 实现覆盖
+
+
+
+
+在包含您的 API 定义的文件夹中[创建一个 `overrides.yml` 文件](/cli-api-reference/cli-reference/commands#fern-write-overrides):
+
+```bash {6}
+fern/
+ ├─ fern.config.json
+ ├─ generators.yml
+ └─ spec-folder/
+ ├─ spec-file.yml # API 定义
+ └─ overrides.yml
+```
+
+ 覆盖文件的格式独立于规范。例如,即使您的 OpenAPI 规范是 JSON 格式,您也可以用 yaml 编写覆盖。
+
+
+
+
+对于 OpenAPI、AsyncAPI 和 OpenRPC,您可以使用 [Fern 的扩展](/learn/api-definitions/asyncapi/overrides#definition-specific-extensions) 来应用自定义。
+
+```yml title="overrides.yml" {4-5}
+paths:
+ /users:
+ post:
+ x-fern-sdk-group-name: users
+ x-fern-sdk-method-name: create
+```
+
+
+
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: spec-file.yml
+ overrides: ./overrides.yml
+```
+
+您也可以指定[多个覆盖文件](#managing-overrides-across-apis)。
+
+
+
+现在当您运行 `fern generate` 时,Fern 会将您的原始 API 规范与覆盖文件合并:
+
+
+```yml openapi.yml
+paths:
+ /users:
+ post:
+ description: Create a User
+ operationId: users_post
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+```
+```yml title="overrides.yml" {4-5}
+paths:
+ /users:
+ post:
+ x-fern-sdk-group-name: users
+ x-fern-sdk-method-name: create
+```
+```yml title="合并后" {4-5}
+paths:
+ /users/post:
+ post:
+ x-fern-sdk-group-name: users
+ x-fern-sdk-method-name: create
+ description: Create a User
+ operationId: users_post
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+```
+
+
+
+
+## 跨 API 管理覆盖
+
+`overrides` 字段接受单个路径或路径列表。当提供多个路径时,覆盖会按顺序依次应用,后面的文件对于冲突键会优先于前面的文件。
+
+
+
+
+当您的项目有多个需要相同基础覆盖的规范时,使用共享基础文件并在其上分层应用特定规范的覆盖。这避免了在每个规范中重复常见的覆盖(例如,SDK 方法名称或身份验证扩展):
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: ./payments-api.yml
+ overrides:
+ - ./shared-overrides.yml # 所有规范的通用覆盖
+ - ./payments-overrides.yml # 支付特定的覆盖
+ - openapi: ./users-api.yml
+ overrides:
+ - ./shared-overrides.yml # 相同的通用覆盖
+ - ./users-overrides.yml # 用户特定的覆盖
+```
+
+
+
+
+当您需要为 SDK 生成和文档使用完全不同的覆盖时,使用带有各自 `generators.yml` 的单独文件夹。每个文件夹只引用与其关注点相关的覆盖:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```yaml title="sdks/generators.yml"
+api:
+ specs:
+ - openapi: ../openapi.yml
+ overrides: sdk-overrides.yml
+```
+
+如果 SDK 和文档覆盖共享一个通用基础,您可以在每个文件夹内使用多个覆盖文件来避免重复:
+
+```yaml title="sdks/generators.yml"
+api:
+ specs:
+ - openapi: ../openapi.yml
+ overrides:
+ - ../shared-overrides.yml # SDK 和文档的通用覆盖
+ - sdk-overrides.yml # SDK 特定的覆盖
+```
+
+
+
+
+当您的公共和内部 API 共享相同的规范但需要不同的覆盖时,使用多个覆盖文件在公共基础上分层添加内部特定的内容。这在内部 API 是公共 API 超集时特别有用:
+
+```yaml title="generators.yml" {5, 12-13}
+groups:
+ public:
+ specs:
+ - openapi: openapi.yml
+ overrides: public-overrides.yml
+ generators:
+ ...
+ internal:
+ specs:
+ - openapi: openapi.yml
+ overrides:
+ - public-overrides.yml # 基础:所有公共覆盖
+ - internal-overrides.yml # 附加:仅内部覆盖
+ generators:
+ ...
+```
+
+这避免了在内部配置中重复公共覆盖。`internal-overrides.yml` 文件只需包含内部 API 特定的添加内容。
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/project-structure.mdx b/fern/translations/zh/products/api-def/pages/project-structure.mdx
new file mode 100644
index 000000000..8b9908bd9
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/project-structure.mdx
@@ -0,0 +1,233 @@
+---
+title: 项目结构
+description: 描述 Fern 文件夹结构
+sidebar-title: 项目结构
+---
+
+配置 fern 从 `fern` 文件夹开始,该文件夹包含你的 API 定义、SDK 生成器和你的 CLI 版本。
+
+Fern 推荐使用多仓库结构,将你的 fern 文件夹放在源代码仓库中(包含你的 API 定义和生成配置),并[将每个生成的 SDK 放在其自己单独的仓库中](/sdks/overview/project-structure)。
+
+## 目录结构
+
+当你运行 `fern init`(对于 Fern Definition)或 `fern init --spec-type path/to/spec`(对于其他规范)时,你的 fern 文件夹将使用以下文件进行初始化:
+
+
+
+
+
+
+
+
+
+
+
+## 核心配置文件
+
+
+ 除了核心文件之外,你可以选择使用 [overlays (OpenAPI)](/learn/api-definitions/openapi/overlays) 或 [overrides](/learn/api-definitions/asyncapi/overrides) 文件来自定义你的 API 定义,而无需修改原始规范。
+
+
+### `fern.config.json`
+
+`fern.config.json` 文件存储你的组织名称和 Fern CLI 版本。固定版本可以提供确定性构建。
+
+```json title="fern.config.json"
+{
+ "organization": "plant-catalog",
+ "version": ""
+}
+```
+
+
+ 当使用本地安装的 CLI 时,将 `version` 设置为 `"*"`。详细信息请参见[本地安装 Fern CLI](/cli-api-reference/cli-reference/overview#install-fern-cli-locally)。
+
+
+### `generators.yml`
+
+对于 OpenAPI/AsyncAPI,`generators.yml` 文件是必需的,用于声明你的 API 规范位置。这还启用了 [API 参考文档](/learn/docs/api-references/overview)。
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: ./openapi/openapi.yml
+```
+
+**对于 Fern Definition**,不需要 `generators.yml` 来[生成 API 参考文档](/learn/docs/api-references/overview)。Fern 通过检查 `definition/` 目录自动检测你的 API。
+
+对于 SDK 生成,所有规范格式都需要 `generators.yml`。添加 `groups` 部分来配置要生成哪些 SDK。详细信息请参见 [SDKs 项目结构](/sdks/overview/project-structure#generatorsyml)。
+
+### API 定义文件
+
+对于 Fern Definition,你的 API 配置分为两个文件:`api.yml` 用于 API 范围的配置,单独的 `.yml` 文件用于你的实际端点和类型定义。有关更多信息,请参见[什么是 Fern Definition?](/api-definitions/ferndef/overview)。
+
+对于其他规范格式([OpenAPI](/api-definitions/openapi/overview)、[AsyncAPI](/api-definitions/asyncapi/overview)、[OpenRPC](/api-definitions/openrpc/overview) 和 [gRPC](/api-definitions/grpc/overview)),你将拥有一个独立的规范文件。
+
+## 存储 API 定义的位置
+
+有三种常见的管理 API 定义的方式:
+
+- **直接提交到你的 Fern 仓库(推荐)。** 将你的 API 定义文件检入包含你的 Fern 配置的同一个仓库中。如果你不在其他地方维护定义,这是最简单的方法。
+- **从源代码仓库同步。** 将你的 API 定义存储在与你的 API 源代码相同的仓库中,并将更新同步到你的 Fern 仓库。你可以使用 [`fern api update`](/cli-api-reference/cli-reference/commands#fern-api-update) CLI 命令或 [sync-openapi GitHub Action](/learn/api-definitions/openapi/sync-your-open-api-specification) 来自动化这个过程。
+- **在公共 URL 托管。** 从可公开访问的端点提供定义,并在 `generators.yml` 中配置 [`origin`](/learn/sdks/reference/generators-yml#openapi) 字段,以便 Fern 可以获取它。当你希望有一个多个消费者可以引用的单一规范定义时,这很有用。
+
+## 多个 API
+
+Fern 支持两种处理多个 API 定义的方法。两种方法都需要一个 `apis` 文件夹 — 这个文件夹必须使用这个确切的名称。
+
+1. **为每个 API 生成单独的 SDK** - 每个 API 生成自己独立的 SDK 包集合(例如,`@company/user-api`、`@company/payments-api` 或版本化的如 `@company/sdk-v1`、`@company/sdk-v2`)
+2. **从多个 API 合并 SDK** - 多个 API 合并到一个 SDK 包中,并可选择使用命名空间(例如,`client.users`、`client.payments` 或版本化的如 `client.v1`、`client.v2`)
+
+### 为每个 API 生成单独的 SDK
+
+当每个 API 应该生成自己独立的 SDK 集合时使用这种方法。这适用于不同的 API(例如,`user-api` 和 `payments-api`)和版本化 API,你希望每个版本都可以独立安装(例如,`@company/sdk-v1`、`@company/sdk-v2`)。
+
+
+
+将每个 API 或 API 版本放入 `fern/apis/` 的单独子文件夹中:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+每个 API 目录包含自己的 `generators.yml` 文件,引用同一文件夹中的规范:
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: openapi.yml # 同一文件夹中的规范文件
+groups:
+ # SDK 生成器配置
+```
+
+
+
+### 从多个 API 合并 SDK
+
+
+ 此功能仅适用于 [Pro 和企业版计划](https://buildwithfern.com/pricing)。在 Pro 计划中,你可以将最多五个 API 合并到单个 SDK 中,在企业版计划中可以合并无限个 API。要开始使用,请联系 support@buildwithfern.com。
+
+
+当你想要将多个 API 合并到单个 SDK 包中,并可选择使用命名空间来组织它们时,使用这种方法。这适用于不同的 API 和版本化 API,但会增加包大小,因为所有 API 都捆绑在一起。
+
+对于版本化 API,命名空间让你可以在同一个包中访问不同版本,如 `client.v1` 和 `client.v2`。
+
+
+
+将每个 API 放入 `fern/apis/` 的单独子文件夹中:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+在单个 `generators.yml` 中列出所有 API:
+
+```yaml title="generators.yml"
+api:
+ specs:
+ - openapi: user-api/openapi.yml
+ - openapi: payments-api/openapi.yml
+groups:
+ # SDK 生成器配置
+```
+
+
+
+添加 [`namespace`](/learn/sdks/reference/generators-yml#namespace) 来处理 API 之间重叠的模式名称或组织不同的 API 版本:
+
+
+
+```yaml title="generators.yml" {4}
+api:
+ specs:
+ - openapi: apis/user-api/openapi.yml
+ - namespace: payments
+ openapi: apis/payments-api/openapi.yml
+groups:
+ # SDK 生成器配置
+```
+
+
+在单个 `generators.yml` 中列出所有 API 版本并使用命名空间:
+
+```yaml title="generators.yml" {3, 5}
+api:
+ specs:
+ - namespace: v1
+ openapi: apis/v1/openapi.yml
+ - namespace: v2
+ openapi: apis/v2/openapi.yml
+groups:
+ # SDK 生成器配置
+```
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/api-def/pages/what-is-an-api-definition.mdx b/fern/translations/zh/products/api-def/pages/what-is-an-api-definition.mdx
new file mode 100644
index 000000000..64c8066fe
--- /dev/null
+++ b/fern/translations/zh/products/api-def/pages/what-is-an-api-definition.mdx
@@ -0,0 +1,353 @@
+---
+title: 什么是 API 定义?
+description: 描述 API 提供方和 API 消费者之间的契约
+sidebar-title: 什么是 API 定义?
+---
+
+
+API 定义是对您的 API 结构的机器可读规范,包括**端点**、**请求和响应模式**,以及**身份验证**要求。API 定义能够自动生成这些工件,而不需要手动保持 SDK 和文档与 API 变更的同步。
+
+Fern 集成了多种 API 定义格式:
+
+
+
+ OpenAPI 原称 Swagger,是最受欢迎的 API 定义格式。[OpenAPI](https://swagger.io/specification/) 可用于记录 RESTful API,并在 YAML 或 JSON 文件中定义。
+
+ 在[此处](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)查看 Petstore API 的 OpenAPI 规范示例
+
+ ```yaml maxLines={0}
+ openapi: 3.0.2
+ tags:
+ - name: pet
+ description: Everything about your Pets
+ paths:
+ /pet:
+ post:
+ tags:
+ - pet
+ summary: Add a new pet to the store
+ description: Add a new pet to the store
+ operationId: addPet
+ requestBody:
+ description: Create a new pet in the store
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ application/xml:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ responses:
+ '200':
+ description: Successful operation
+ content:
+ application/xml:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pet'
+ '405':
+ description: Invalid input
+ components:
+ schemas:
+ Pet:
+ required:
+ - name
+ - photoUrls
+ properties:
+ id:
+ type: integer
+ format: int64
+ example: 10
+ name:
+ type: string
+ example: doggie
+ category:
+ $ref: '#/components/schemas/Category'
+ photoUrls:
+ type: array
+ xml:
+ wrapped: true
+ items:
+ type: string
+ xml:
+ name: photoUrl
+ tags:
+ type: array
+ xml:
+ wrapped: true
+ items:
+ $ref: '#/components/schemas/Tag'
+ xml:
+ name: tag
+ status:
+ type: string
+ description: pet status in the store
+ enum:
+ - available
+ - pending
+ - sold
+ xml:
+ name: pet
+ type: object
+ ```
+
+
+ [AsyncAPI](https://v2.asyncapi.com/docs) 是用于定义事件驱动 API 的规范。它用于记录使用 WebSocket、MQTT 和其他消息传递协议的 API。
+
+ 查看下面聊天应用程序的 AsyncAPI 规范示例:
+
+ ```yaml maxLines={0}
+ asyncapi: 2.0.0
+ info:
+ title: Chat server
+ version: 1.0.0
+
+ servers:
+ Production:
+ url: chat.com
+ protocol: ws
+
+ channels:
+ "/application":
+ bindings:
+ ws:
+ query:
+ type: object
+ properties:
+ apiKey:
+ type: string
+ description: The API key for the client
+ minimum: 1
+ bindingVersion: 0.1.0
+ subscribe:
+ operationId: sendMessage
+ message:
+ $ref: '#/components/messages/SendMessage'
+ publish:
+ operationId: receiveMessage
+ message:
+ $ref: '#/components/messages/ReceiveMessage'
+
+ components:
+ messages:
+ SendMessage:
+ payload:
+ message: string
+ ReceiveMessage:
+ payload:
+ message: string
+ from:
+ type: string
+ description: The userId for the sender of the message
+ ```
+
+
+
+ [OpenRPC](https://open-rpc.org/) 是用于描述 JSON-RPC 2.0 API 的规范。它为 JSON-RPC 生态系统提供了交互式文档和代码生成工具。
+
+ 查看下面加密钱包服务的 OpenRPC 规范示例:
+
+ ```yaml maxLines=0
+ # yaml-language-server: $schema=https://meta.open-rpc.org/
+ $schema: https://meta.open-rpc.org/
+ openrpc: 1.2.4
+ info:
+ title: Basic Wallet API JSON-RPC Specification
+ description: A simple JSON-RPC API for querying wallet balances.
+ version: 0.0.1
+ servers:
+ - url: https://wallet.example.com/json-rpc
+ name: Mainnet
+ methods:
+ - name: getBalance
+ description: Get the balance of a wallet address.
+ params:
+ - name: address
+ required: true
+ description: The wallet address to query.
+ schema:
+ type: string
+ result:
+ name: balance
+ description: The balance of the wallet address.
+ schema:
+ type: number
+ examples:
+ - name: getBalance example
+ params:
+ - name: address
+ value: "0x1234567890abcdef1234567890abcdef12345678"
+ result:
+ name: balance
+ value: 42.5
+ ```
+
+
+ [gRPC](https://grpc.io/) 是由 Google 开发的现代开源 RPC 框架。它使用 Protocol Buffers 作为接口定义语言,支持多种编程语言,并具有高效的二进制序列化功能。
+
+ gRPC API 使用 Protocol Buffer(.proto)文件定义,这些文件指定服务和消息类型。查看下面的 gRPC 服务定义示例:
+
+ ```proto maxLines={0}
+ syntax = "proto3";
+
+ package petstore;
+
+ // The pet store service definition
+ service PetStoreService {
+ // Get a pet by ID
+ rpc GetPet(GetPetRequest) returns (Pet);
+
+ // Add a new pet to the store
+ rpc AddPet(AddPetRequest) returns (Pet);
+
+ // List all pets with optional filtering
+ rpc ListPets(ListPetsRequest) returns (ListPetsResponse);
+ }
+
+ // Request message for getting a pet
+ message GetPetRequest {
+ int64 pet_id = 1;
+ }
+
+ // Request message for adding a pet
+ message AddPetRequest {
+ string name = 1;
+ string category = 2;
+ repeated string photo_urls = 3;
+ PetStatus status = 4;
+ }
+
+ // Request message for listing pets
+ message ListPetsRequest {
+ int32 page_size = 1;
+ string page_token = 2;
+ PetStatus status = 3;
+ }
+
+ // Response message for listing pets
+ message ListPetsResponse {
+ repeated Pet pets = 1;
+ string next_page_token = 2;
+ }
+
+ // Pet message definition
+ message Pet {
+ int64 id = 1;
+ string name = 2;
+ string category = 3;
+ repeated string photo_urls = 4;
+ PetStatus status = 5;
+ }
+
+ // Pet status enumeration
+ enum PetStatus {
+ PET_STATUS_UNSPECIFIED = 0;
+ PET_STATUS_AVAILABLE = 1;
+ PET_STATUS_PENDING = 2;
+ PET_STATUS_SOLD = 3;
+ }
+ ```
+
+
+ Fern Definition 是我们对更简单 API 定义格式的理解。它采用**最佳实践**设计,同时支持 **RESTful 和事件驱动 API**,并针对 **SDK 生成**进行了优化。
+
+
+ Fern Definition 受到了 [Amazon](https://smithy.io/2.0/index.html)、[Google](https://grpc.io/)、[Palantir](https://blog.palantir.com/introducing-conjure-palantirs-toolchain-for-http-json-apis-2175ec172d32)、Twilio 和 Stripe 等公司内部 API Definition 格式的启发。这些公司**拒绝了** OpenAPI 并构建了自己的版本。
+
+
+ 查看下面的 Fern Definition 示例:
+
+ ```yaml maxLines={0}
+ types:
+ MovieId: string
+
+ Movie:
+ properties:
+ id: MovieId
+ title: string
+ rating:
+ type: double
+ docs: The rating scale is one to five stars
+
+ CreateMovieRequest:
+ properties:
+ title: string
+ rating: double
+
+ service:
+ auth: false
+ base-path: /movies
+ endpoints:
+ createMovie:
+ docs: Add a movie to the database
+ method: POST
+ path: /create-movie
+ request: CreateMovieRequest
+ response: MovieId
+
+ getMovie:
+ method: GET
+ path: /{movieId}
+ path-parameters:
+ movieId: MovieId
+ response: Movie
+ errors:
+ - MovieDoesNotExistError
+
+ errors:
+ MovieDoesNotExistError:
+ status-code: 404
+ type: MovieId
+ ```
+
+
+
+
+## 为什么要创建 API 定义?
+
+一旦您拥有 API 定义,Fern 就会将其用作输入来生成诸如 SDK 和 API 参考文档等工件。每当您更新 API 定义时,都可以重新生成这些工件以确保它们始终保持最新状态。
+
+
+
+ 多语言客户端库,自动与您的 API 保持同步。
+
+
+ 具有代码示例和实时测试功能的交互式 API 文档。
+
+ }
+ href="/docs/integrations/postman"
+ >
+ 预填充示例请求和响应的即用型集合。
+
+ }
+ href="/api-definitions/openapi/frameworks/fastapi"
+ >
+ 用于 FastAPI 的 Pydantic 模型或用于 Spring Boot 应用程序的控制器。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/cli-api-reference/pages/cli-get-started.mdx b/fern/translations/zh/products/cli-api-reference/pages/cli-get-started.mdx
new file mode 100644
index 000000000..374b530c8
--- /dev/null
+++ b/fern/translations/zh/products/cli-api-reference/pages/cli-get-started.mdx
@@ -0,0 +1,106 @@
+---
+title: 概述
+subtitle: 通过命令行管理和配置您的 Fern 项目。
+description: 了解如何使用 Fern CLI 管理 API 项目、验证定义、预览更改以及发布文档和 SDK。
+sidebar-title: 概述
+---
+
+Fern CLI 让您能够初始化项目、验证 API 定义、在本地预览更改,以及发布文档和 SDK。本页介绍安装和常用命令,帮助您快速入门。
+
+## 安装
+
+
+
+
+Fern CLI 需要 [Node.js](https://nodejs.org/) 版本 22 或更高版本,以及 npm 版本 10.0.0 或更高版本(随 Node.js 22 一起发布)。
+
+```bash
+node -v # 必须是 v22.0.0 或更高版本
+```
+
+如果您的版本低于最低要求,请[下载最新的 Node.js LTS](https://nodejs.org/),它包含兼容的 npm 版本。
+
+
+
+
+
+运行以下命令从 [npm](https://www.npmjs.com/) 全局安装 Fern CLI:
+
+```bash
+npm install -g fern-api
+fern -v # 验证安装
+```
+
+
+
+
+
+
+如果您希望将 Fern 作为项目依赖项管理,或者在网络连接有限的环境中工作,可以本地安装 CLI:
+
+
+
+
+```bash
+npm install fern-api
+```
+
+
+
+
+
+在您的 `fern.config.json` 中,将版本设置为 `*` 以使用本地安装的版本:
+
+```json fern.config.json {3}
+{
+ "organization": "your-org",
+ "version": "*"
+}
+```
+
+有关更多详细信息,请参阅 [fern.config.json 参考](/learn/sdks/overview/project-structure#fernconfigjson)。
+
+
+
+
+
+```bash
+npm fern check
+npm fern generate
+```
+
+
+
+
+
+
+## 按产品分类的 CLI 工作流程
+
+Fern CLI 管理文档和 SDK 工作流程。以下是每个产品常用命令的简要概述。所有命令都支持[全局选项](/learn/cli-api-reference/cli-reference/options),如用于调试的 `--log-level`。
+
+有关完整的 CLI 文档,请参阅[命令参考](/learn/cli-api-reference/cli-reference/commands)。
+
+
+
+ 在使用 Fern Docs 时,您将使用这些 CLI 命令。有关完整说明,请参阅[文档快速入门](/learn/docs/getting-started/quickstart)。
+
+ | 命令 | 描述 |
+ |---------|-------------|
+ | `fern init --docs` | 创建新的文档项目 |
+ | `fern docs dev` | 在 `localhost:3000` 本地预览文档 |
+ | `fern generate --docs` | 将文档发布到生产环境 |
+
+
+
+ 在使用 Fern SDK 时,您将使用这些 CLI 命令。有关完整说明,请参阅[SDK 快速入门](/learn/sdks/overview/quickstart)。
+
+ | 命令 | 描述 |
+ |---------|-------------|
+ | `fern init` | 创建新的 SDK 项目 |
+ | `fern check` | 验证您的 API 定义 |
+ | `fern generate --preview` | 在 `.preview/` 中本地预览 SDK |
+ | `fern generate` | 将 SDK 发布到生产环境 |
+ | `fern generate --group ` | 生成特定的 SDK 组 |
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/cli-api-reference/pages/commands.mdx b/fern/translations/zh/products/cli-api-reference/pages/commands.mdx
new file mode 100644
index 000000000..1d2914ff8
--- /dev/null
+++ b/fern/translations/zh/products/cli-api-reference/pages/commands.mdx
@@ -0,0 +1,899 @@
+---
+title: '命令'
+description: 'Fern CLI 所有命令的完整参考,用于生成 SDK 和开发者文档。'
+subtitle: '了解 Fern CLI 命令。'
+sidebar-title: '命令'
+hideOnThisPage: true
+---
+
+
+| 命令 | 描述 |
+|---------|-------------|
+| [`fern init`](#fern-init) | 从 OpenAPI 规范或从头开始创建新的 Fern 项目 |
+| [`fern check`](#fern-check) | 验证 API 定义和配置 |
+| [`fern upgrade`](#fern-upgrade) | 将 Fern CLI 和生成器更新到最新版本 |
+| [`fern login`](#fern-login) | 通过 GitHub、Google、Postman 或企业 SSO 登录 Fern CLI |
+| [`fern logout`](#fern-logout) | 从 Fern CLI 注销 |
+| [`fern export`](#fern-export) | 导出 API 的 OpenAPI 规范 |
+| [`fern api update`](#fern-api-update) | 手动更新 OpenAPI 规范 |
+| [`fern api enrich`](#fern-api-enrich) | 将覆盖文件中的 `x-fern-examples` 合并到原生 OpenAPI 示例中 |
+
+## 文档命令
+
+| 命令 | 描述 |
+|---------|-------------|
+| [`fern docs dev`](#fern-docs-dev) | 运行本地文档预览服务器 |
+| [`fern docs diff`](#fern-docs-diff) Beta | 生成预览和生产文档之间的视觉差异 |
+| [`fern generate --docs`](#fern-generate---docs) | 构建并发布文档更新 |
+| [`fern docs preview list`](#fern-docs-preview-list) | 列出所有预览部署 |
+| [`fern docs preview delete`](#fern-docs-preview-delete) | 删除预览部署 |
+| [`fern docs md check`](#fern-docs-md-check) | 验证文档文件中的 MDX 语法 |
+| [`fern docs theme export`](#fern-docs-theme-export) | 从 `docs.yml` 导出主题兼容字段到独立目录 |
+| [`fern docs theme upload`](#fern-docs-theme-upload) | 上传主题到 Fern 注册表 |
+| [`fern docs theme list`](#fern-docs-theme-list) | 列出组织的所有主题 |
+
+## SDK 生成命令
+
+| 命令 | 描述 |
+|---------|-------------|
+| [`fern generate`](#fern-generate) | 构建并发布 SDK 更新 |
+| [`fern write-definition`](#fern-write-definition) | 将 OpenAPI 规范转换为 [Fern Definition](/learn/api-definitions/ferndef/overview) |
+| [`fern write-overrides`](#fern-write-overrides) | 创建 OpenAPI 自定义 |
+| [`fern generator upgrade`](#fern-generator-upgrade) | 将 SDK 生成器更新到最新版本 |
+
+## 详细命令文档
+
+
+
+
+ 使用 `fern init` 在当前文件夹中初始化新的 Fern 工作空间。默认情况下,您将看到 IMDb API 示例。
+
+
+ ```bash
+ fern init [--docs] [--openapi ]
+ ```
+
+
+ 使用 OpenAPI 初始化时,您的项目结构将如下所示:
+
+
+
+
+
+
+
+
+
+
+
+ 对于 Fern Definition 初始化(不使用 OpenAPI),您将看到以下结构:
+
+
+
+
+
+
+
+
+
+
+
+
+ ### openapi
+
+ 使用 `--openapi` 从 OpenAPI 规范初始化项目:
+
+ ```bash
+ # 从本地文件初始化
+ fern init --openapi ./path/to/openapi.yml
+
+ # 从 URL 初始化
+ fern init --openapi https://link.buildwithfern.com/petstore-openapi
+ ```
+
+ ### docs
+
+ 通过添加 `--docs`,您还将获得一个包含 API Reference 部分的示例文档网站。
+
+ ```bash
+ fern init --docs
+ ```
+
+ 添加的文件将包含:
+
+ ```yaml docs.yaml
+ instances:
+ - url: https://your-organization.docs.buildwithfern.com
+ title: Your Organization | Documentation
+ navigation:
+ - api: API Reference
+ colors:
+ accent-primary: '#ffffff'
+ background: '#000000'
+ ```
+
+ 要发布 API 文档,请运行 [`fern generate --docs`](/learn/cli-api/cli-reference/commands#fern-generate---docs)。
+
+ ### mintlify
+
+ 通过添加 `--mintlify PATH_TO_MINT_CONFIG`,CLI 将根据 `mint.json` 文件自动将您的 Mintlify 文档文件夹转换为 Fern 文档网站。
+
+ ```bash
+ fern init --mintlify PATH_TO_MINT_CONFIG
+ ```
+
+ CLI 将创建一个具有以下结构的 `fern/` 文件夹:
+
+
+
+
+
+
+
+
+
+ ### readme
+
+ `fern init` 命令支持导入 Readme 生成的文档网站。这需要安装本地 chromium 浏览器实例。
+ 您可以通过从源代码安装 `fern` cli 来确保已安装,请按照[这里](https://github.com/fern-api/fern/blob/main/CONTRIBUTING.md)的说明进行操作。
+
+ 通过添加 `--readme URL_TO_README_DOCS_SITE`,CLI 将自动将 Readme 生成的文档网站转换为 Fern 文档网站。
+
+ ```bash
+ fern init --readme URL_TO_README_DOCS_SITE
+ ```
+
+ CLI 将创建一个具有以下结构的 `fern/` 文件夹:
+
+
+
+
+
+
+
+
+
+
+ 有关入门的更多信息,请查看我们的[快速入门指南](/learn/docs/getting-started/quickstart)
+
+
+
+
+
+ 使用 `fern export` 为您的 API 生成 OpenAPI 规范。
+
+ 当您以 OpenAPI 以外的格式(例如 [Fern Definition](/api-definitions/ferndef/overview))定义了 API 并需要将其导出为 OpenAPI 规范以与其他工具或服务集成时,此命令非常有用。
+
+
+
+ ```bash
+ fern export [--api ] path/to/openapi.yml
+ fern export [--api ] path/to/openapi.json
+ ```
+
+
+ ### api
+
+ 当您在 `fern/apis/` 文件夹中定义了多个 API 时,使用 `--api` 指定要导出的 API。
+
+
+ ```bash
+ fern export --api public-api path/to/openapi.yml
+ fern export --api public-api path/to/openapi.json
+ ```
+
+
+
+
+
+ 使用 `fern generate` 运行 Fern 编译器并为您的 API 创建 SDK。
+
+
+ ```bash
+ fern generate [--group ] [--api ] [--version ] [--preview] [--fernignore ] [--local] [--force]
+ ```
+
+
+ ### group
+
+ 使用 `--group ` 指定要运行的生成器组。您可以使用组名或别名。别名在您的 [`generators.yml`](/learn/sdks/reference/generators-yml#aliases) 中定义并映射到多个组,允许您通过单个命令并行运行多个组。
+
+ ```bash
+ # 运行特定组
+ fern generate --group python-sdk
+
+ # 运行在"all"别名中定义的所有组
+ fern generate --group all
+
+ # 运行在"frontend"别名中定义的所有组
+ fern generate --group frontend
+
+ # 本地运行特定组(自托管)
+ fern generate --group python-sdk --local
+ ```
+
+ 您还可以在 `generators.yml` 中将别名设置为 `default-group`,这样运行不带任何参数的 `fern generate` 将运行该别名中的所有组。
+
+ `--group` 标志可以与其他标志组合使用,如用于[自托管 SDK 生成](/learn/sdks/deep-dives/self-hosted)的 `--local`、用于本地测试的 `--preview` 或用于指定 SDK 版本的 `--version`。
+
+ ### preview
+
+ 使用 `--preview` 在发布前本地测试 SDK 更改。这在开发期间特别有用:
+ - 将 SDK 生成到本地 `.preview/` 文件夹
+ - 允许在 Fern 定义上快速迭代
+ - 不会将更改发布到包管理器或 GitHub
+
+ ```bash
+ # 预览所有 SDK
+ fern generate --preview
+
+ # 预览特定 SDK 组
+ fern generate --group python-sdk --preview
+ ```
+
+ ### api
+
+ 使用 `--api ` 为 SDK 生成指定 API。当项目包含多个 API 定义时这很有用。API 名称应与 `fern/apis/` 文件夹中的目录名称匹配。
+
+ ```bash
+ fern generate --api public-api
+ ```
+
+ ### version
+
+ 使用 `--version` 指定 SDK 版本号,通常遵循语义版本控制(semver)格式(`MAJOR.MINOR.PATCH`)。这在发布 SDK 版本的 CI/CD 流水线中特别有用。
+
+ ```bash
+ # 使用版本 2.11.0 生成所有 SDK
+ fern generate --version 2.11.0
+
+ # 为支付 API 的 Python SDK 生成版本 1.2.3
+ fern generate --api payments-api --group python-sdk --version 1.2.3
+ ```
+
+ ### fernignore
+
+ 使用 `--fernignore` 为 SDK 生成指定自定义 `.fernignore` 文件路径。这允许您临时测试不同的忽略配置,而无需修改存储库中已提交的 `.fernignore`。
+
+ Fern 将使用指定的文件而不是主分支上的文件,并将新的 `.fernignore` 作为生成过程的一部分提交到您的存储库。
+
+ ```bash
+ fern generate --fernignore ./custom-fernignore
+ ```
+
+ ### local
+
+ 使用 `--local` 在您自己的机器上运行 SDK 生成,而不是使用 Fern 的云基础设施。这对于有严格安全或合规要求的组织很有用。请参阅[自托管 SDK](/learn/sdks/deep-dives/self-hosted) 获取设置说明。
+
+ ```bash
+ # 本地生成所有 SDK
+ fern generate --local
+
+ # 本地生成特定 SDK 组
+ fern generate --group python-sdk --local
+ ```
+
+
+ 您的机器上必须运行 Docker 守护进程,因为 SDK 生成在 Docker 容器内运行。
+
+
+ 默认情况下,CLI 从 Docker Hub 拉取生成器镜像。要从自定义容器注册表拉取,请在您的 `generators.yml` 中使用 [`image` 字段](/learn/sdks/reference/generators-yml#image) 而不是 `name`。请参阅[自定义容器注册表](/learn/sdks/deep-dives/self-hosted#optional-configure-a-custom-container-registry)了解详细信息。
+
+ ### force
+
+ 使用 `--force` 跳过生成过程中的确认提示。这在会阻塞流水线的交互式提示的 CI/CD 环境中很有用。
+
+ ```bash
+ # 不带确认提示生成
+ fern generate --group python-sdk --force
+ ```
+
+
+
+
+
+
+ `--broken-links` 和 `--strict-broken-links` 标志已弃用。请在 `docs.yml` 中使用 [`broken-links` 验证规则](/learn/docs/configuration/site-level-settings#check-configuration)。
+
+ 您还可以使用 [Fern Dashboard](https://dashboard.buildwithfern.com/) 验证实时发布网站上的内部和外部链接。
+
+
+ 使用 `fern check` 验证您的 API 定义和 Fern 配置,包括 [`fern.config.json`](/learn/sdks/overview/project-structure#fernconfigjson)、`generators.yml` 和 `docs.yml`。它检查损坏的链接、无效的 API 示例、配置错误等。当所有检查通过时,该命令不产生输出。
+
+
+ ```bash
+ fern check [--api ] [--warnings]
+ ```
+
+
+ 您可以在 `docs.yml` 文件中[使用 `check.rules` 属性](/learn/docs/configuration/site-level-settings#check-configuration)配置 `fern check` 运行的验证规则的严重性。
+
+ ```yaml docs.yml
+ check:
+ rules:
+ broken-links: error
+ example-validation: warn
+ missing-redirects: error
+ ```
+
+ ### api
+
+ 使用 `--api ` 指定要检查的 API。
+
+ ```bash
+ fern check --api public-api
+ ```
+
+ ### warnings
+
+ 使用 `--warnings` 除了记录错误外还记录警告。
+
+ ```bash
+ fern check --warnings
+ ```
+
+ ## 在 GitHub Action 中使用
+
+
+ ```yml maxLines=14
+ name: Fern Validation Check
+
+ on:
+ pull_request:
+ push:
+ branches:
+ - main
+
+ jobs:
+ validate-fern-api:
+ name: Validate using Fern's linter
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Install Fern CLI
+ run: npm install -g fern-api
+
+ - name: Validate API with Fern
+ run: fern check
+
+ ```
+
+
+
+
+
+
+ 使用 `fern generate --docs` 为您的 API 创建文档网站。
+
+
+ ```bash
+ fern generate --docs [instance ] [--preview] [--id ] [--force]
+ ```
+
+
+ ### instance
+
+ 使用 `--instance` 指定要为 `docs.yml` 中的哪个实例 URL 生成文档。
+
+ ```bash
+ fern generate --docs --instance your-organization.docs.buildwithfern.com
+ ```
+
+ ### preview
+
+ 使用 `--preview` 在将更改发布到生产网站之前预览文档更新。
+
+ ```bash
+ fern generate --docs --preview
+ ```
+
+ ### id
+
+ 使用 `--id` 与 `--preview` 一起创建稳定的命名预览链接。预览 URL 遵循格式 `{org}-preview-{id}.docs.buildwithfern.com`,因此使用相同的 `--id` 重新运行会就地更新现有预览,而不是创建新预览。
+
+ ```bash
+ fern generate --docs --preview --id my-feature
+ # -> https://your-org-preview-my-feature.docs.buildwithfern.com
+ ```
+
+ 这在您希望每个拉取请求有一个预览 URL 的 CI 工作流程中很有用。请参阅[预览更改](/learn/docs/preview-publish/preview-changes#preview-links)了解详细信息。
+
+ ### force
+
+ 当重用已存在的 `--id` 时,Fern 会提示您确认覆盖。使用 `--force` 跳过确认。这在 GitHub Actions 中会自动检测到,但在其他 CI 环境(如 Azure Pipelines)中需要。
+
+ ```bash
+ fern generate --docs --preview --id my-feature --force
+ ```
+
+
+
+
+
+ 使用 `fern docs preview list` 列出您组织的所有预览部署。
+
+
+ ```bash
+ fern docs preview list [--limit ] [--page ]
+ ```
+
+
+ ### limit
+
+ 使用 `--limit` 指定每页显示的预览部署数量。
+
+ ```bash
+ fern docs preview list --limit 20
+ ```
+
+ ### page
+
+ 使用 `--page` 指定要显示结果的页面。
+
+ ```bash
+ fern docs preview list --page 2
+ ```
+
+
+
+
+
+ 使用 `fern docs preview delete` 删除使用 `fern generate --docs --preview` 生成的预览部署。`` 参数是要删除的完整预览 URL。
+
+
+ ```bash
+ fern docs preview delete
+ ```
+
+
+
+
+
+
+ 使用 `fern docs dev` 运行本地开发服务器来预览您的文档。
+
+
+ ```bash
+ fern docs dev [--port ]
+ ```
+
+
+
+ 在 Windows 上,`fern docs dev` 需要启用[长路径支持](https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation#enable-long-paths-in-windows-10-version-1607-and-later)。
+
+ 要启用长路径支持,请在提升的 PowerShell 提示符中运行以下命令,然后重启您的终端:
+
+ ```powershell
+ New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1 -PropertyType DWORD -Force
+ ```
+
+ 如果您无法启用长路径支持,请使用 [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) 在 Linux 环境中运行 `fern docs dev`。
+
+
+ ### port
+
+ 使用 `--port ` 指定文档预览运行的端口。
+
+ ```bash
+ fern docs dev --port 57908
+ ```
+
+
+
+
+
+ 使用 `fern docs md check` 验证导航配置中引用的所有文档页面的 MDX 语法,包括 `docs.yml`、版本配置文件和产品特定的 YAML 文件。
+
+
+ ```bash
+ fern docs md check
+ ```
+
+
+ 该命令解析每个 MDX 文件并报告语法错误,包含文件路径和行:列号。该命令考虑 frontmatter 偏移量,因此报告的行号与文件中的实际行对应。
+
+ ```plaintext
+ fern/pages/quickstart.mdx:12:5
+ Unexpected closing tag, expected corresponding closing tag for ``
+
+ fern/pages/guide.mdx:45:1
+ Expected a closing tag for `` before the end of `paragraph`
+ ```
+
+ 当所有文件都有效时,您将看到成功消息:
+
+ ```plaintext
+ ✓ All 42 MDX files are valid
+ ```
+
+
+
+
+ Beta
+
+ 使用 `fern docs diff` 在预览部署和生产文档之间生成视觉差异。此命令旨在用于 [GitHub Actions](https://github.com/fern-api/docs/blob/main/.github/workflows/preview-docs.yml)。它捕获两个版本的截图并创建并排比较图像。
+
+
+ ```bash
+ fern docs diff [--output ]
+ ```
+
+
+ 传递来自 `fern generate --docs --preview` 的预览 URL 和一个或多个 MDX 文件路径。差异图像默认保存到 `.fern/diff`。
+
+ ```bash
+ fern docs diff acme-preview-abc123.docs.buildwithfern.com fern/pages/intro.mdx fern/pages/quickstart.mdx
+ ```
+
+ ### output
+
+ 使用 `--output` 为差异图像指定自定义目录。
+
+ ```bash
+ fern docs diff acme-preview-abc123.docs.buildwithfern.com fern/pages/intro.mdx --output ./my-diffs
+ ```
+
+
+
+
+
+ 使用 `fern upgrade` 将 [`fern.config.json`](/learn/sdks/overview/project-structure#fernconfigjson) 中的编译器版本升级到最新版本。它还将 `generators.yml` 中的生成器升级到其最低兼容版本。
+
+
+ ```bash
+ fern upgrade
+ ```
+
+
+
+
+
+
+ 使用 `fern login` 通过 GitHub 或 Google 登录 Fern CLI。登录允许您加入 GitHub 组织、获得权限并为项目做出贡献。
+
+
+ ```bash
+ fern login
+ fern login --device-code
+ fern login --email
+ ```
+
+
+ 默认情况下,`fern login` 打开浏览器进行 GitHub、Google 或 Postman 身份验证。有两种替代流程可用:
+
+ ### device-code
+
+ 在无法自动打开浏览器的环境中(例如 SSH 会话或容器),使用 `--device-code` 通过设备代码授权登录。
+
+ ```bash
+ fern login --device-code
+ ```
+
+ ### email
+
+ 使用 `--email` 通过企业 SSO 登录。传递与您组织的 SSO 提供商关联的电子邮件地址。
+
+ ```bash
+ fern login --email user@example.com
+ ```
+
+
+ 要启用 CI/CD,请使用 [`fern token`](/learn/cli-api/cli-reference/commands#fern-token)。
+
+
+
+
+
+
+ 使用 `fern logout` 从 Fern CLI 注销。这将清除您的身份验证凭据并撤销对您的 GitHub 组织和权限的访问。
+
+
+ ```bash
+ fern logout
+ ```
+
+
+ 注销后,您需要再次运行 [`fern login`](#fern-login) 来访问受保护的功能。
+
+
+
+
+
+
+
+ 请参阅[发布您的文档](/learn/docs/preview-publish/publishing-your-docs#usage-in-github-actions),了解在自动化发布工作流程中使用此令牌的说明。
+
+
+
+
+
+ 使用 `fern write-definition` 将您的 OpenAPI 规范转换为 Fern Definition。您必须有一个包含 `.json` 或 `.yaml` 格式的 OpenAPI 规范文件的 `fern/openapi/` 文件夹。
+
+
+ ```bash
+ fern write-definition [--api ]
+ ```
+
+
+ 运行此命令时,会在 `fern/` 内创建一个名为 `.definition/` 的新文件夹。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 如果您没有看到 `.definition/` 文件夹,请使用适当的命令或配置来查看隐藏文件夹(在 `bash` 和 `zsh` 中使用 `ls -a`)。
+
+
+ 如果您的 `fern/` 文件夹同时包含 `openapi/` 和 `definition/` 文件夹,Fern 默认读取您的 OpenAPI 规范。要使用您的 Fern Definition 作为输入,您必须:
+ - 将 `.definition/` 文件夹重命名为 `definition/`。
+ - 删除或重命名 `openapi/` 文件夹。例如,您可以将其重命名为 `.openapi/`。
+
+ ### api
+
+ 如果您在 `fern/apis/` 文件夹中定义了多个 API,请使用 `--api` 指定要为其编写定义的 API。
+
+ ```bash
+ fern write-definition --api public-api
+ ```
+
+
+
+
+ 使用 `fern write-overrides` 生成基本的 OpenAPI 覆盖文件。覆盖文件允许对 API 规范进行可逆修改,包括为 Fern Docs 中的代码片段添加请求和响应示例。
+
+
+ ```bash
+ fern write-overrides [--api ] [--exclude-models]
+ ```
+
+
+ 运行此命令时,会在 `fern/openapi/` 内创建一个名为 `openapi-overrides.yml` 的新文件。
+
+
+
+
+
+
+
+
+
+
+
+
+ ### api
+
+ 如果定义了多个 API,请使用 `--api` 指定要对其运行命令的 API。
+
+ ```bash
+ fern write-overrides --api public-api
+ ```
+
+ ### exclude-models
+
+ 使用 `--exclude-models` 在生成初始覆盖时存根模型(除了端点)。
+
+ ```bash
+ fern write-overrides --exclude-models
+ ```
+
+
+
+
+ 使用 `fern generator upgrade` 将 `generators.yml` 中的所有生成器更新到其最新版本。
+
+
+ 这与更新 Fern CLI 版本的 `fern upgrade` 不同。使用这两个命令来保持整个 Fern 工具链的最新状态。
+
+
+
+ ```bash
+ fern generator upgrade [--list] [--generator ] [--group ] [--include-major]
+ ```
+
+
+ 此命令将:
+ - 检查 `generators.yml` 中指定的所有生成器的更新
+ - 将生成器版本更新到其最新兼容版本
+ - 保持与当前 Fern 编译器版本的兼容性
+
+ 当有可用更新时,您可能会看到:
+
+ ```plaintext
+ ┌───────────────────────────────────────────────────────────────────────────────────┐
+ │ │
+ │ Upgrades available │
+ │ │
+ │ │
+ │ C# SDK (API: openapi, Group: csharp-sdk) 1.9.11 → 1.9.15 │
+ │ Java SDK (API: openapi, Group: java-sdk) 2.2.0 → 2.11.3 │
+ │ Python SDK (API: openapi, Group: python-sdk) 4.3.10 → 4.3.11 │
+ │ │
+ │ Run fern generator upgrade to upgrade your generators. │
+ │ Run fern generator upgrade --list to see the full list of generator upgrades │
+ │ available. │
+ │ │
+ └───────────────────────────────────────────────────────────────────────────────────┘
+ ```
+
+ ### list
+
+ 使用 `--list` 查看可用生成器升级的完整列表。
+
+ ```bash
+ fern generator upgrade --list
+ ```
+
+ ### generator
+
+ 使用 `--generator` 指定要升级的特定生成器类型。
+
+ ```bash
+ fern generator upgrade --generator fernapi/fern-typescript-sdk
+ fern generator upgrade --generator fernapi/fern-python-sdk
+ ```
+
+ ### group
+
+ 使用 `--group` 升级 `generators.yml` 中特定组内的生成器。如果未指定,将升级指定类型的所有生成器。
+
+ ```bash
+ fern generator upgrade --group public
+ ```
+
+ ### include-major
+
+ ```bash
+ fern generator upgrade --include-major
+ ```
+
+ 使用 `--include-major` 包括主要版本升级。默认跳过主要版本以防止破坏性更改。
+
+
+
+ 从 `generators.yml` 中指定的 `origin` 拉取最新的 OpenAPI 规范并更新本地规范。或者,您可以[通过设置 GitHub Action 来自动化此过程](/api-definitions/openapi/sync-your-open-api-specification)。
+
+
+ ```bash
+ fern api update [--api ]
+ ```
+
+
+ ### api
+
+ 如果 `generators.yml` 中有多个定义了 `origin` 的规范,请使用 `--api` 指定要更新的 API。如果您不指定 API,所有有 `origin` 的 OpenAPI 规范都将被更新。
+
+
+ ```bash
+ fern api update --api public-api
+ ```
+
+
+
+
+
+ 使用 `fern api enrich` 将 [AI 生成的示例](/learn/docs/ai-features/ai-examples)或手动创作的 [`x-fern-examples`](/learn/api-definitions/openapi/extensions/request-response-examples) 转换为任何兼容 OpenAPI 的工具都可以使用的可移植 OpenAPI 示例。
+
+
+ ```bash
+ fern api enrich -f -o
+ ```
+
+
+ 该命令将覆盖文件中的示例合并到原生 OpenAPI `example` 字段中,并从输出中剥离 `x-fern-examples` 键。当端点有多个示例时,每个示例都作为命名条目存储在复数 `examples` 字段下。
+
+ 该命令需要两个标志:
+
+ - `-f`(或 `--file`)— 包含 `x-fern-examples` 的覆盖文件(例如,`ai_examples_override.yml`)。
+ - `-o`(或 `--output`)— 丰富输出文件的路径。支持 `.yml` 和 `.json` 扩展名。
+
+ ```bash
+ # 输出为 YAML
+ fern api enrich openapi.yml -f overrides.yml -o enriched-openapi.yml
+
+ # 输出为 JSON
+ fern api enrich openapi.yml -f overrides.yml -o enriched-openapi.json
+ ```
+
+ 每个 `x-fern-examples` 字段都映射到其标准 OpenAPI 位置:
+
+ - `path-parameters` → `parameters[].example`(其中 `in: path`)
+ - `query-parameters` → `parameters[].example`(其中 `in: query`)
+ - `headers` → `parameters[].example`(其中 `in: header`)
+ - `request.body` → `requestBody.content.*.example`
+ - `response.body` → `responses..content.*.example`
+
+
+
+
+
+ 使用 `fern docs theme export` 将 `docs.yml` 中的[主题兼容字段](/learn/docs/customization/global-themes)提取到独立目录中。导出的 `theme.yml` 及其资源然后可以通过 `fern docs theme upload` 上传。
+
+
+ ```bash
+ fern docs theme export [--output ]
+ ```
+
+
+ 默认情况下,文件写入 `./fern/theme/`。
+
+ ### output
+
+ 使用 `--output` 为导出的主题指定自定义目录。
+
+ ```bash
+ fern docs theme export --output ./my-theme
+ ```
+
+
+
+
+
+ 使用 `fern docs theme upload` 将[主题](/learn/docs/customization/global-themes)上传到 Fern 的注册表。该命令从 `./fern/theme/` 读取 `theme.yml` 并连同任何引用的文件资源一起上传。
+
+
+ ```bash
+ fern docs theme upload [--name ] [--org ]
+ ```
+
+
+ ### name
+
+ 使用 `--name` 设置主题名称。默认为 `default`。
+
+ ```bash
+ fern docs theme upload --name my-theme
+ ```
+
+ ### org
+
+ 使用 `--org` 覆盖来自 `fern.config.json` 的组织 ID。
+
+ ```bash
+ fern docs theme upload --org my-org
+ ```
+
+
+
+
+
+ 使用 `fern docs theme list` 列出为您的组织上传的所有[主题](/learn/docs/customization/global-themes)。
+
+
+ ```bash
+ fern docs theme list [--json] [--org ]
+ ```
+
+
+ 默认情况下,每行输出一个主题名称。
+
+ ### json
+
+ 使用 `--json` 将完整列表输出为 JSON 数组,包括 `updatedAt` 时间戳。
+
+ ```bash
+ fern docs theme list --json
+ ```
+
+ ### org
+
+ 使用 `--org` 覆盖来自 `fern.config.json` 的组织 ID。
+
+ ```bash
+ fern docs theme list --org my-org
+ ```
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/cli-api-reference/pages/global-options.mdx b/fern/translations/zh/products/cli-api-reference/pages/global-options.mdx
new file mode 100644
index 000000000..c93f9be77
--- /dev/null
+++ b/fern/translations/zh/products/cli-api-reference/pages/global-options.mdx
@@ -0,0 +1,66 @@
+---
+title: '全局选项'
+description: 'Fern CLI 的全局选项'
+subtitle: '了解 Fern CLI 全局选项。'
+sidebar-title: '全局选项'
+---
+
+
+这些选项适用于任何 Fern CLI 命令,用于控制日志记录和获取帮助。
+
+| 选项 | 描述 | 示例 |
+|--------|-------------|---------|
+| [`--help`](#help) | 显示命令帮助和选项 | `fern --help` |
+| [`--log-level`](#log-level) | 设置日志详细程度 | `fern generate --log-level debug` |
+
+
+使用 `--log-level debug` 在故障排除时查看详细输出。
+
+
+## help
+
+使用 `--help` 选项与任何 Fern CLI 命令一起查看说明和可用选项。
+
+
+```bash maxLines=10 title="fern add --help"
+fern add --help
+fern add
+
+Add a code generator to generators.yml
+
+Positionals:
+ generator [string] [required]
+
+Options:
+ --help Show help [boolean]
+ --log-level [choices: "debug", "info", "warn", "error"] [default: "info"]
+ --api Only run the command on the provided API [string]
+ --group Add the generator to the specified group [string]
+```
+
+```bash maxLines=10 title="fern write-definition --help"
+fern write-definition --help
+fern write-definition
+
+Write underlying Fern Definition for OpenAPI Specifications and API Dependencies.
+
+Options:
+ --help Show help [boolean]
+ --log-level [choices: "debug", "info", "warn", "error"] [default: "info"]
+ --api Only run the command on the provided API [string]
+```
+
+
+## log-level
+
+使用 `--log-level` 选项设置 Fern 日志输出的详细程度。默认级别为 `info`。
+
+可用级别(从详细到简略):
+- `debug`:调试消息、信息消息、警告和错误
+- `info`:信息消息、警告和错误
+- `warn`:仅警告和错误
+- `error`:仅错误消息
+
+```bash
+fern generate --log-level debug
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-01-05.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-01-05.mdx
new file mode 100644
index 000000000..92cb3475a
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-01-05.mdx
@@ -0,0 +1,14 @@
+---
+tags: ["seo"]
+---
+
+## 链接检查器
+
+Fern Dashboard 现在包含一个链接检查器,可以扫描您已发布的文档中的损坏链接,验证内部链接(指向文档内其他页面的链接)和外部链接(指向外部网站的链接)。
+
+要检查损坏链接,请打开 [Fern Dashboard](https://dashboard.buildwithfern.com),导航到**链接检查器**选项卡,并选择要扫描的域名。检查器会显示找到的任何损坏(404)或被阻止(403)的链接,以及源页面和链接类型。
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-01-07.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-01-07.mdx
new file mode 100644
index 000000000..7425656a7
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-01-07.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["customization"]
+---
+
+## 在控制面板中设置自定义域名
+
+您现在可以直接在 [Fern Dashboard](https://dashboard.buildwithfern.com/) 中为您的文档网站配置自定义域名。控制面板会根据您的域名类型自动显示需要添加到域名注册商的 DNS 记录。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-01-20.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-01-20.mdx
new file mode 100644
index 000000000..413a95e37
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-01-20.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["security"]
+---
+
+## 用户权限
+
+您现在可以为组织中的团队成员分配角色,以控制谁可以发布到生产环境和管理组织设置。可以选择管理员、编辑者或查看者角色,并可选择限制对特定文档网站的访问。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-02-13.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-02-13.mdx
new file mode 100644
index 000000000..bff965c35
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-02-13.mdx
@@ -0,0 +1,21 @@
+---
+tags: ["pdf-export"]
+---
+
+## PDF 导出
+
+您现在可以直接从 Fern Dashboard 将整个文档网站导出为 PDF。
+
+每个导出包括:
+- 带有可自定义标题和副标题的封面页
+- 带有可点击链接的自动生成目录
+- 所有内容页面
+- 带有页码占位符的可选页眉和页脚
+
+
+
+要开始使用,请在 [Dashboard](https://dashboard.buildwithfern.com/) 中转到**概览** > **⋮** > **导出为 PDF**。
+
+
+
+[查看实时网站](https://docs.cohere.com/)
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-02-23.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-02-23.mdx
new file mode 100644
index 000000000..1a12bcf4d
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-02-23.mdx
@@ -0,0 +1,13 @@
+---
+tags: ["security"]
+---
+
+## 密码保护
+
+您现在可以直接从 Fern Dashboard 为您的文档网站启用密码保护。
+
+启用后,访问者必须输入共享密码才能查看任何内容。您也可以随时从网站的**设置**页面重置或删除密码。
+
+要开始使用,请在 [Dashboard](https://dashboard.buildwithfern.com/) 中转到**设置** > **密码**。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-03-02.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-03-02.mdx
new file mode 100644
index 000000000..be1348fdb
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-03-02.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["pdf-export"]
+---
+
+## PDF 导出:选择产品和版本
+
+导出 PDF 时,您现在可以选择要导出哪个[产品](/learn/docs/configuration/products)和/或[版本](/learn/docs/configuration/versions)。以前,PDF 导出包含您的整个网站。现在,您一次导出一个产品的一个版本。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/changelog/2026-03-17.mdx b/fern/translations/zh/products/dashboard/pages/changelog/2026-03-17.mdx
new file mode 100644
index 000000000..cdffd982d
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/changelog/2026-03-17.mdx
@@ -0,0 +1,11 @@
+---
+tags: ["security"]
+---
+
+## 基于密码的 RBAC
+
+您现在可以在 Dashboard 中设置多个密码,每个密码映射到不同的角色。结合[基于角色的访问控制 (RBAC)](/learn/docs/authentication/features/rbac),这让您可以控制不同组可以访问哪些页面和部分 — 无需 JWT 或 OAuth。
+
+要开始使用,请在 [Dashboard](https://dashboard.buildwithfern.com/) 中转到**设置** > **密码**。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/domains.mdx b/fern/translations/zh/products/dashboard/pages/domains.mdx
new file mode 100644
index 000000000..e85db8624
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/domains.mdx
@@ -0,0 +1,55 @@
+---
+title: 设置自定义域名
+description: 使用 Fern Dashboard 配置您的自定义域名,为子域名、子路径或根域名托管配置 DNS 记录。
+sidebar-title: 设置自定义域名
+---
+
+[管理员](/learn/dashboard/configuration/permissions) 可以使用 [Fern Dashboard](https://dashboard.buildwithfern.com/) 配置以下任一自定义域名类型:
+- **子域名**:`docs.mydomain.com`
+- **子路径**:`mydomain.com/docs`
+- **根域名**:`mydomain.com`
+
+Dashboard 会根据您的域名类型自动提供正确的 DNS 记录。
+
+
+ 或者,您可以[通过手动配置 DNS 记录来设置自定义域名](/learn/docs/preview-publish/setting-up-your-domain)。
+
+
+## 设置
+
+
+
+
+导航到 [Fern Dashboard](https://dashboard.buildwithfern.com/) 并选择您的文档站点。
+
+
+
+
+在**概述**选项卡的**域名**部分,选择**添加自定义域名**并输入您的域名。Dashboard 会显示您需要配置的 DNS 记录。
+
+
+
+
+
+将您的 `custom-domain` 添加到 `docs.yml` 配置中:
+
+```yaml docs.yml
+instances:
+ - url: example.docs.buildwithfern.com
+ custom-domain: docs.mydomain.com
+```
+
+
+
+
+
+登录到您的域名注册商并添加 Fern Dashboard 中显示的 DNS 记录。具体记录取决于您的域名类型(子域名、子路径或根域名)。
+
+
+
+
+添加 DNS 记录后,返回 Fern Dashboard 验证您的域名。SSL 会为您的域名自动配置,但可能需要几分钟才能在全球范围内传播。
+
+检查您是否可以从移动设备或无痕浏览器访问您的新文档站点。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/github-repo.mdx b/fern/translations/zh/products/dashboard/pages/github-repo.mdx
new file mode 100644
index 000000000..95ebaa88d
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/github-repo.mdx
@@ -0,0 +1,39 @@
+---
+title: 连接 GitHub 仓库
+description: 将你的 GitHub 仓库链接到 Fern 项目以实现自动部署。
+sidebar-title: 连接 GitHub 仓库
+---
+
+
+将 Fern 仪表板连接到包含你的 Fern 文档的 GitHub 仓库。连接后,当你推送更改时,你的文档会自动部署。
+
+要完成仓库连接,你需要:
+
+- 对存在仓库的 GitHub 组织的**管理员访问权限**
+- 在仓库上安装 [Fern GitHub 应用](https://github.com/apps/fern-api)
+
+## 设置
+
+
+
+
+导航到 [Fern 仪表板](https://dashboard.buildwithfern.com/) 并选择你的文档站点。
+
+
+
+
+在**概述**标签页的**源**部分,选择**连接仓库**并按照提示授权 Fern API GitHub 应用。
+
+
+
+
+
+如果你还没有安装 [Fern GitHub 应用](https://github.com/apps/fern-api),系统会提示你在仓库上安装它。你必须是 GitHub 组织的管理员才能完成此步骤。
+
+
+
+
+
+选择包含你的 Fern 文档的仓库。连接后,当你向配置的分支推送更改时,Fern 会自动部署你的文档。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/overview.mdx b/fern/translations/zh/products/dashboard/pages/overview.mdx
new file mode 100644
index 000000000..5e2e549a6
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/overview.mdx
@@ -0,0 +1,190 @@
+---
+title: 仪表板概述
+description: 从中央仪表板管理您的 Fern 项目、设置和团队。
+sidebar-title: 仪表板概述
+---
+
+
+
+Fern 仪表板提供一个中心位置来管理您的项目、团队成员和设置。
+
+## 设置
+
+访问您团队的[仪表板](https://dashboard.buildwithfern.com/)并完成初始设置步骤:
+
+
+
+ 配置您的自定义域名,自动配置 DNS 记录。
+
+
+ 分配管理员、编辑者或查看者角色来管理仪表板和 CLI 访问权限。
+
+
+ 将您的 GitHub 仓库连接到项目。
+
+
+ 为您的文档设置 AI 驱动的聊天功能。
+
+
+
+## 指标
+
+监控和分析开发者如何与您的文档进行交互:
+
+
+
+ 跟踪开发者和机器人如何与您的文档进行交互。
+
+
+ 监控搜索查询,了解开发者在您的文档中寻找什么。
+
+
+ 扫描您已发布的文档中的内部和外部损坏链接。
+
+
+ 查看和响应页面反馈。
+
+ 了解更多
+
+
+
+
+
+
+
+
+ 查看 AI 聊天对话历史。
+
+ 了解更多
+
+
+
+
+
+
+
+
+
+## 站点管理
+
+管理您的文档站点和团队协作:
+
+
+
+ 查看部署状态、域名、CLI 版本和 GitHub 仓库详细信息。
+
+
+ 创建和管理 Fern Editor 会话。
+
+ 了解更多
+
+
+
+
+
+
+
+
+ 将您的完整文档站点导出为 PDF。
+
+ 了解更多
+
+
+
+
+
+
+
+
+ 使用共享密码限制对您文档站点的访问。
+
+
+ 暂时让站点下线而不删除它。
+
+
+
+
+
+Fern 仪表板提供一个中心位置来管理您的项目、团队成员和设置。
+
+## 设置
+
+访问您团队的[仪表板](https://dashboard.buildwithfern.com/)并完成初始设置步骤:
+
+- [设置自定义域名](/learn/dashboard/configuration/custom-domains):配置您的自定义域名,自动配置 DNS 记录。
+- [成员权限](/learn/dashboard/configuration/permissions):分配管理员、编辑者或查看者角色来管理仪表板和 CLI 访问权限。
+- [集成 GitHub](/learn/dashboard/configuration/github-repo):将您的 GitHub 仓库连接到项目。
+- [启用 Ask Fern](/learn/docs/ai-features/ask-fern/overview):为您的文档设置 AI 驱动的聊天功能。
+
+## 指标
+
+监控和分析开发者如何与您的文档进行交互:
+
+- **网站分析**:跟踪开发者和机器人如何与您的文档进行交互。
+- **搜索分析**:监控搜索查询,了解开发者在您的文档中寻找什么。
+- **损坏链接**:扫描您已发布的文档中的内部和外部损坏链接。
+- [反馈](/learn/docs/user-feedback):查看和响应页面反馈。
+- [Ask Fern 对话](/learn/ask-fern/getting-started/what-is-ask-fern):查看 AI 聊天对话历史。
+
+## 站点管理
+
+管理您的文档站点和团队协作:
+
+- **站点信息**:查看部署状态、域名、CLI 版本和 GitHub 仓库详细信息。
+- [Fern Editor](/learn/docs/writing-content/fern-editor):创建和管理 Fern Editor 会话。
+- [PDF 导出](/learn/dashboard/configuration/pdf-export):将您的完整文档站点导出为 PDF。
+- [密码保护](/learn/dashboard/configuration/password-protection):使用共享密码限制对您文档站点的访问。
+- [取消发布站点](/learn/docs/preview-publish/publishing-your-docs#unpublishing-your-docs):暂时让站点下线而不删除它。
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/password-protection.mdx b/fern/translations/zh/products/dashboard/pages/password-protection.mdx
new file mode 100644
index 000000000..64d16a10d
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/password-protection.mdx
@@ -0,0 +1,62 @@
+---
+title: 密码保护
+description: 从 Fern Dashboard 管理文档站点的密码保护。
+sidebar-title: 密码保护
+---
+
+
+
+
+直接从 [Fern Dashboard](https://dashboard.buildwithfern.com/) 使用共享密码保护您已发布的文档站点。启用后,访问者必须输入密码才能查看任何内容。您还可以设置多个密码与 [RBAC](/learn/docs/authentication/features/rbac) 配合使用。
+
+
+ 受密码保护的站点不会被搜索引擎索引。
+
+
+您也可以使用 SSO、JWT 或 OAuth 对用户进行身份验证。详情请参阅[身份验证概述](/learn/docs/authentication/overview)。
+
+## 启用密码保护
+
+
+
+
+导航至 [Fern Dashboard](https://dashboard.buildwithfern.com/) 并选择您要保护的文档站点。
+
+
+
+
+打开您的文档站点的**设置**页面。您将在页面顶部看到一个**密码**卡片。
+
+
+
+
+为您的整个站点输入一个密码,或选择**添加角色**来添加多个密码,每个密码都映射到您定义的用户角色。您最多可以添加三个用户角色。点击**保存**以激活密码保护。
+
+启用后,卡片将显示当前密码以及最后更新的时间和更新人员。
+
+
+
+
+
+
+
+
+
+如果您设置了具有不同用户角色的多个密码,请在 `docs.yml` 中配置[基于角色的访问控制 (RBAC)](/learn/docs/authentication/features/rbac) 以根据角色限制站点的页面和章节。
+
+
+
+## 管理密码保护
+
+在同一对话框中,您可以**重置**密码或**移除**密码以使您的站点公开访问。
+
+
+ 所有[成员](/learn/dashboard/configuration/permissions)都可以查看当前密码。只有管理员可以设置、重置或移除密码。
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/pdf-export.mdx b/fern/translations/zh/products/dashboard/pages/pdf-export.mdx
new file mode 100644
index 000000000..335ec2113
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/pdf-export.mdx
@@ -0,0 +1,73 @@
+---
+title: PDF 导出
+description: 从 Fern Dashboard 将您的文档站点导出为 PDF。
+sidebar-title: PDF 导出
+---
+
+
+
+
+直接从 [Fern Dashboard](https://dashboard.buildwithfern.com/) 将您的文档导出为 PDF。生成的 PDF 包含封面页、带有可点击链接的目录以及所有带有页眉和页脚的内容页面。
+
+## 导出您的文档
+
+
+
+
+在 [Fern Dashboard](https://dashboard.buildwithfern.com/) 中,导航到 **概述** 选项卡。点击右上角的 **⋮**(垂直省略号)菜单,然后选择 **导出为 PDF**。
+
+
+
+
+
+
+
+
+自定义您的 PDF:
+
+- **产品和/或版本**:如果您的站点有[产品](/learn/docs/configuration/products)或[版本](/learn/docs/configuration/versions),请选择要导出的产品和/或版本。您一次只能导出一个产品的一个版本。
+- **封面标题和副标题**:默认为您的 Fern Docs 站点标题和副标题。您可以自定义或隐藏这些内容。
+- **封面页脚**:切换封面页上的"Generated by Fern"页脚。
+- **页眉和页脚**:使用模板在每个内容页面的顶部或底部添加文本,支持 `{pageIndex}` 和 `{totalPages}` 占位符。自定义位置(右侧或左侧)。
+
+
+
+
+
+选择 **导出为 PDF** 开始导出。大型站点可能需要几分钟时间——您可以安全地关闭页面。导出完成后您将收到邮件通知。
+
+
+
+
+导出完成后,点击 **打开** 下载 PDF。您还可以查看过往的 PDF 导出记录。
+
+
+
+
+## 示例
+
+
+
+该站点使用**版本**但没有产品。导出涵盖单个版本。
+[查看在线站点](https://docs.cohere.com/)
+
+
+
+该站点**没有版本或产品**,因此导出涵盖整个站点。
+[查看在线站点](https://buildwithfern.com/learn/docs/getting-started/overview)
+
+
+
+该站点使用**产品**但没有版本。导出涵盖单个产品。
+[查看在线站点](https://buildwithfern.com/learn/docs/getting-started/overview)
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/permissions.mdx b/fern/translations/zh/products/dashboard/pages/permissions.mdx
new file mode 100644
index 000000000..8382be041
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/permissions.mdx
@@ -0,0 +1,80 @@
+---
+title: 成员权限
+description: 管理您组织的仪表板和 CLI 访问权限。
+sidebar-title: 成员权限
+---
+
+通过在 [Fern Dashboard](https://dashboard.buildwithfern.com/members) 中配置角色来控制每个团队成员在 Fern 中可以执行的操作。
+
+## 添加成员
+
+只有[管理员](#admin)可以添加成员。您的[计划](#team-members-by-plan)决定了可以添加的成员数量。
+
+
+
+
+导航到 [Fern Dashboard](https://dashboard.buildwithfern.com/members) 并从侧边栏选择**成员**。
+
+
+
+
+选择**添加成员**,然后选择以下方式之一邀请成员加入您的组织:
+
+- **一次性链接**:分配一个[角色](#role-types)并为编辑者配置 [CLI 访问权限](#editor)。然后,选择**生成邀请链接**来创建一个可与任何人共享的一次性链接。
+- **电子邮件**:输入电子邮件地址,分配一个[角色](#role-types),并为编辑者配置 [CLI 访问权限](#editor)。然后,选择**发送邀请**。
+
+被邀请者将收到一封包含加入您在 Fern 中的组织链接的电子邮件。
+
+
+
+
+要更改成员的角色或移除成员,请前往[成员](https://dashboard.buildwithfern.com/members)页面并选择成员姓名旁边的选项菜单。
+
+## 角色类型
+
+每个团队成员都有管理员、编辑者或查看者角色。默认情况下,除非您分配不同的角色,否则所有成员都具有管理员权限。
+
+角色控制两种类型的权限:
+
+- **仪表板权限**:管理组织设置和成员、添加或更新自定义域名、查看分析数据以及使用 [Fern Editor](/learn/docs/writing-content/fern-editor)。
+- **CLI 权限**:将 SDK 和文档发布到生产环境。本地开发和部署预览不需要 CLI 访问权限。
+
+### 管理员
+
+管理员对仪表板和 CLI 都有完全访问权限,包括编辑组织设置、管理成员、使用 Fern Editor 以及发布到生产环境。
+
+### 编辑者
+
+编辑者可以查看分析数据和使用 Fern Editor。编辑者无法管理组织设置或成员。CLI 访问权限可为每个编辑者单独配置:
+
+- **有** CLI 访问权限的编辑者可以将 SDK 和文档站点发布到生产环境。
+- **无** CLI 访问权限的编辑者无法发布到生产环境。
+- 所有编辑者都可以通过 CLI 部署预览。
+
+### 查看者
+
+查看者对仪表板(设置、分析数据)具有只读访问权限,并且可以通过 CLI 部署预览。查看者无法访问 Fern Editor。
+
+## 按角色划分的权限
+
+| 权限 | 管理员 | 编辑者 | 查看者 |
+| -------------------- | ----- | --------------- | ----- |
+| 管理组织设置 | 是 | 否 | 否 |
+| 管理成员 | 是 | 否 | 否 |
+| 添加或更新自定义域名 | 是 | 否 | 否 |
+| 管理密码保护 | 是 | 否 | 否 |
+| 查看仪表板和分析数据 | 是 | 是 | 是 |
+| 发布到生产环境 | 是 | 按编辑者配置 | 否 |
+| 部署预览 | 是 | 是 | 是 |
+| 本地生成 | 是 | 是 | 是 |
+| 使用 Fern Editor | 是 | 是 | 否 |
+
+## 按计划划分的团队成员
+
+您的[计划](https://buildwithfern.com/pricing)决定了可以添加到组织的成员数量:
+
+| 计划 | 团队成员 |
+| --------- | ------- |
+| Hobby | 2 |
+| Pro | 5 |
+| Enterprise| 自定义 |
\ No newline at end of file
diff --git a/fern/translations/zh/products/dashboard/pages/sso.mdx b/fern/translations/zh/products/dashboard/pages/sso.mdx
new file mode 100644
index 000000000..2f464d377
--- /dev/null
+++ b/fern/translations/zh/products/dashboard/pages/sso.mdx
@@ -0,0 +1,170 @@
+---
+title: 设置单点登录 (SSO)
+description: 让团队成员使用您的身份提供商 (SAML 或 OIDC) 登录 Fern
+sidebar-title: 设置单点登录 (SSO)
+---
+
+
+
+
+设置单点登录 (SSO) 以使用您现有的身份提供商登录 Fern。
+
+SSO 设置需要与 Fern 合作交换配置值(如回调 URL 和实体 ID)。开始使用前,请在下方选择您的身份提供商(Okta、Google Workspace 或 Microsoft Entra),然后选择 SAML 或 OIDC。
+
+
+ 如果您使用其他身份提供商,Fern 将帮助您配置。请通过 Slack 或 support@buildwithfern.com 联系我们开始设置。
+
+
+
+
+
+
+
+
+
+ Fern 将通过安全渠道向您发送 SSO URL 和 Audience URI。
+
+
+
+ 在 **Applications** 中,使用 **SAML 2.0** 创建新的应用集成。使用以下值进行配置:
+
+ | 字段 | 值 |
+ | ----- | ----- |
+ | Single sign-on URL | [来自 Fern 的值] |
+ | Audience URI | [来自 Fern 的值] |
+ | Name ID format | `EmailAddress` |
+
+ 然后,添加属性声明:
+ | 名称 | 值 |
+ | ------ | -------------------------------------- |
+ | `name` | `user.firstName + " " + user.lastName` |
+ | `email`| `user.email` |
+
+
+
+ 从 **Sign-On** 选项卡中,复制元数据 URL 和 X.509 证书。将它们发送回 Fern。Fern 将启用连接并与您一起运行测试登录。
+
+
+
+ 在 **General** 选项卡的 **App visibility** 下,启用 **Do not display application icon to users**。这可以防止身份提供商发起的登录流程,该流程存在安全风险。
+
+
+
+ 分配应访问 Fern 的人员。
+
+
+
+
+
+
+
+ Fern 将通过安全渠道向您发送重定向 URI。
+
+
+
+ 在 **Applications** 中,使用 OIDC 创建新的 **Web Application**。使用授权码授权并将重定向 URI 设置为 Fern 提供的值。
+
+
+
+ 将客户端 ID、客户端密钥和您的 Okta 域(例如,`.okta.com`)发送回 Fern。Fern 将启用连接并与您一起运行测试登录。
+
+
+
+ 在 **General** 选项卡的 **App visibility** 下,启用 **Do not display application icon to users**。这可以防止身份提供商发起的登录流程,该流程存在安全风险。
+
+
+
+ 分配应访问 Fern 的人员。
+
+
+
+
+
+
+
+
+
+
+
+
+ Fern 将通过安全渠道向您发送 ACS URL 和实体 ID。
+
+
+
+ 在 **Web and mobile apps** 中,选择 **Add app → Add custom SAML app**。在 **Service provider details** 中,输入以下值:
+
+ | 字段 | 值 |
+ | ----- | ----- |
+ | ACS URL | [来自 Fern 的值] |
+ | Entity ID | [来自 Fern 的值] |
+ | Name ID format | `EMAIL` |
+ | Name ID | `Primary email` |
+
+ 然后,添加属性声明:
+ | Google Directory Attribute | App Attribute |
+ | -------------------------- | ------------- |
+ | `First name` | `firstName` |
+ | `Last name` | `lastName` |
+
+
+
+ 从 Google 复制 SSO URL、实体 ID 和 X.509 证书。将它们发送给 Fern。Fern 将启用连接并与您一起运行测试登录。
+
+
+
+ 分配应访问 Fern 的人员。
+
+
+
+
+
+
+
+
+
+
+
+
+ 在 **Enterprise applications** 下,选择 **New application → Create your own application → Non-gallery**。
+
+
+
+ Fern 将通过安全渠道向您发送标识符(实体 ID)和回复 URL (ACS)。
+
+
+
+ 在 **Single Sign-On** 中,选择 **SAML** 并输入以下值:
+
+ | 字段 | 值 |
+ | ----- | ----- |
+ | Identifier (Entity ID) | [来自 Fern 的值] |
+ | Reply URL (ACS) | [来自 Fern 的值] |
+ | Name ID | `user.primaryauthoritativeemail` (email) |
+
+ 然后,添加属性声明:
+
+ | 名称 | 值 |
+ | ------- | ------------------ |
+ | `name` | `user.displayname` |
+ | `email` | `user.mail` |
+
+
+
+ 从 **SAML Certificates** 中,复制 **App Federation Metadata URL**。将其发送给 Fern。Fern 将启用连接并与您一起运行测试登录。
+
+
+
+ 为了防止身份提供商发起的登录流程(存在安全风险),请不要分发用户访问 URL。
+
+ 可选地,创建条件访问策略以阻止非来自服务提供商的登录。
+
+
+
+ 在 **Users and groups** 中,添加应访问 Fern 的人员。
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/accessibility/keyboard-shortcuts.mdx b/fern/translations/zh/products/docs/pages/accessibility/keyboard-shortcuts.mdx
new file mode 100644
index 000000000..6bd2145c0
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/accessibility/keyboard-shortcuts.mdx
@@ -0,0 +1,60 @@
+---
+title: "键盘快捷键"
+description: "了解 Fern 文档中的键盘快捷键,包括导航快捷键、搜索命令、Ask AI 面板控制和 API playground 快捷键。"
+sidebar-title: 键盘快捷键
+---
+
+Fern 文档包含用于导航、搜索和交互功能的内置键盘快捷键。
+
+## 交互元素
+
+| 操作 | 快捷键 |
+|--------|----------|
+| 在交互元素之间移动焦点 | `Tab` |
+| 在交互元素之间向后移动焦点 | `Shift` + `Tab` |
+| 激活[按钮](/learn/docs/writing-content/components/button)和[可展开部分](/learn/docs/writing-content/components/accordions) | `Enter` 或 `Space` |
+| 关闭打开的对话框、面板和 API playground | `Escape` |
+| 切换 Ask AI 面板 | `Command` + `/` (macOS)
`Ctrl` + `/` (Windows/Linux) |
+| 切换 API playground/explorer | `Ctrl` + `` ` `` |
+
+
+`Command`/`Ctrl` + `/` 快捷键不同于单个 `/` 键,后者用于打开常规[搜索对话框](#search)。
+
+
+## 导航
+
+| 操作 | 快捷键 |
+|--------|----------|
+| 导航到上一页或下一页 | `Command` + `← / →` (macOS)
`Alt` + `← / →` (Windows/Linux) |
+| 滚动到页面顶部或底部 | `Command` + `↑ / ↓` (macOS)
`Ctrl` + `↑ / ↓` (Windows/Linux) |
+
+
+某些浏览器可能会拦截这些快捷键用于前进/后退历史记录导航。
+
+
+## 搜索
+
+| 操作 | 快捷键 |
+|--------|----------|
+| 打开搜索对话框 | `Command` + `K` (macOS)
`Ctrl` + `K` (Windows/Linux) |
+| 当焦点不在文本输入框中时打开搜索对话框 | `/`(正斜杠) |
+
+
+当在输入框、`textarea` 或 `contenteditable` 元素中输入时,`/` 快捷键不会生效。
+
+
+在搜索对话框中:
+
+| 操作 | 快捷键 |
+|--------|----------|
+| 在搜索结果之间导航 | `方向键` |
+| 选择搜索结果 | `Enter` |
+
+## 故障排除
+
+如果键盘快捷键不起作用:
+
+- **浏览器冲突**:某些浏览器对自己的功能使用相同的快捷键(例如,`Command` + `← / →` 用于历史记录导航)。
+- **操作系统冲突**:您的操作系统可能会拦截某些键盘组合。请检查您的系统键盘设置。
+- **输入框中的焦点**:当在文本框中输入时,`/` 快捷键不会生效。请使用 `Command`/`Ctrl` + `K` 代替。
+- **扩展程序冲突**:浏览器扩展程序可能会覆盖键盘快捷键。请尝试禁用扩展程序。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/accessibility/overview.mdx b/fern/translations/zh/products/docs/pages/accessibility/overview.mdx
new file mode 100644
index 000000000..6127ff449
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/accessibility/overview.mdx
@@ -0,0 +1,34 @@
+---
+title: "概述"
+description: "了解 Fern 文档中的无障碍功能,包括键盘导航、网页内容无障碍指南 (WCAG) 2.1 AA 颜色对比度执行和屏幕阅读器支持。"
+sidebar-title: 概览
+---
+
+
+Fern 文档使用语义化 HTML 和 [ARIA 属性](https://www.w3.org/WAI/standards-guidelines/aria/)来支持屏幕阅读器和键盘导航。
+
+
+ 如需报告无障碍问题或建议改进,请联系 support@buildwithfern.com。
+
+
+## 键盘导航
+
+所有交互元素都支持使用 `Tab`、`Enter` 和 `Space` 键进行键盘导航。请查看[键盘快捷键](/learn/docs/accessibility/keyboard-shortcuts#interactive-elements)了解完整列表。
+
+## 对话框和面板
+
+Fern 文档中的对话框和面板专为[键盘无障碍](/learn/docs/accessibility/keyboard-shortcuts#interactive-elements)而设计。焦点会被限制在打开的对话框内,防止导航到对话框外部,搜索对话框支持使用方向键进行完整的键盘导航。
+
+## 颜色对比度
+
+Fern 自动执行 [WCAG 2.1 AA](https://www.w3.org/WAI/WCAG21/quickref/#contrast-minimum) 颜色对比度比率,确保文本和交互元素对所有用户都是可读的:
+
+- **普通文本**: 最低 4.5:1 ([WCAG AA](https://www.w3.org/WAI/WCAG21/quickref/#contrast-minimum))
+- **UI 元素**: 最低 3:1
+- **增强**: 在可行时达到 7:1 ([WCAG AAA](https://www.w3.org/WAI/WCAG21/quickref/#contrast-enhanced))
+
+当您[在 `docs.yml` 文件中配置颜色](/learn/docs/configuration/site-level-settings#colors-configuration)时,Fern 会验证主色调颜色。如果您的主色调颜色相对于背景颜色不满足最低对比度比率,Fern 将:
+
+1. 在 `fern check` 验证期间显示警告
+2. 在运行时自动调整主色调颜色以满足 WCAG AA 标准
+3. 在可能的情况下尝试进一步调整到 WCAG AAA (7:1)
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/ai-examples.mdx b/fern/translations/zh/products/docs/pages/ai/ai-examples.mdx
new file mode 100644
index 000000000..258e0e99a
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/ai-examples.mdx
@@ -0,0 +1,54 @@
+---
+title: AI 生成的示例
+description: 使用 Fern 的 AI 功能自动创建真实的 API 示例。根据需要自定义示例样式或禁用 AI 生成。
+sidebar-title: AI 生成的示例
+---
+
+Fern 使用 AI 为您的 [API Reference](/learn/docs/api-references/overview) 文档自动生成真实的请求和响应示例。此功能默认为所有 API Reference 页面启用。您将获得反映端点属性和描述的可信数据,而不是像 `username: "string"` 这样的占位符值。示例会随着您的规范变化自动更新。
+
+AI 示例与在 [`x-fern-examples`](/learn/api-definitions/openapi/extensions/request-response-examples) 中定义的手动示例一起工作,手动示例具有优先级。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## 配置
+
+自定义生成示例的样式:
+
+```yaml docs.yml
+ai-examples:
+ style: "Use names and emails that are inspired by plants."
+```
+
+或完全禁用此功能:
+
+```yaml docs.yml
+ai-examples:
+ enabled: false
+```
+
+AI 生成的示例将写入 `ai_examples_override.yml`。编辑此文件以自定义特定示例。要在每次构建时重新生成示例,请将该文件添加到 `.gitignore`:
+
+```txt .gitignore
+**/ai_examples_override.yml
+```
+
+
+要使 AI 生成的示例可移植到非 Fern OpenAPI 工具,请使用 [`fern api enrich`](/learn/cli-api-reference/cli-reference/commands#fern-api-enrich) 将它们合并到原生 OpenAPI 示例字段中。
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/llms-txt/analytics-integration.mdx b/fern/translations/zh/products/docs/pages/ai/llms-txt/analytics-integration.mdx
new file mode 100644
index 000000000..50cee5f30
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/llms-txt/analytics-integration.mdx
@@ -0,0 +1,51 @@
+---
+title: 分析和集成
+description: 在 Fern Dashboard 中跟踪对您文档的 LLM 流量,并通过按钮和导航栏链接向读者展示 llms.txt 端点。
+sidebar-title: 分析和集成
+---
+
+`llms.txt` 和 `llms-full.txt` 会自动为您的站点生成,但读者和 AI 工具如何发现它们取决于您。在 Fern Dashboard 中跟踪使用情况,并在您的文档中直接展示端点。
+
+## 跟踪 LLM 流量
+
+[Fern Dashboard](https://dashboard.buildwithfern.com/) 提供 `llms.txt` 使用分析,包括:
+- 按 LLM 提供商(Claude、ChatGPT、Cursor 等)分类的流量
+- Markdown 和 `llms.txt` 文件的机器人与人工访问者的页面级明细
+
+## 向读者展示端点
+
+要让人类读者能够发现端点,请添加按钮或导航链接:
+
+
+
+为您的 SDK 文档添加一个按钮,链接到您 API Reference 的 `llms-full.txt`。使用 `lang` 将代码示例过滤为一种语言,使用 `excludeSpec=true` 排除原始 OpenAPI 规范。
+
+```jsx Markdown
+
+```
+
+这为用户提供了一个干净的、特定语言的输出,他们可以在编写代码时将其提供给 AI 工具。
+
+
+
+在导航栏中添加一个下拉菜单,链接到 `llms-full.txt` 的不同过滤版本,让用户轻松访问其偏好语言的 LLM 优化文档。
+
+```yaml docs.yml
+navbar-links:
+ - type: dropdown
+ text: LLMs
+ icon: fa-solid fa-robot
+ links:
+ - text: 完整文档
+ href: /llms-full.txt
+ - text: Python SDK
+ href: /api-reference/llms-full.txt?lang=python&excludeSpec=true
+ - text: TypeScript SDK
+ href: /api-reference/llms-full.txt?lang=typescript&excludeSpec=true
+ - text: Go SDK
+ href: /api-reference/llms-full.txt?lang=go&excludeSpec=true
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/llms-txt/customize-llms-txt.mdx b/fern/translations/zh/products/docs/pages/ai/llms-txt/customize-llms-txt.mdx
new file mode 100644
index 000000000..123253993
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/llms-txt/customize-llms-txt.mdx
@@ -0,0 +1,126 @@
+---
+title: 自定义 LLM 输出
+description: 使用 noindex 排除页面,使用 llms-only 和 llms-ignore 标签过滤内容,使用查询参数过滤端点输出,或提供您自己的自定义文件。
+sidebar-title: 自定义 LLM 输出
+---
+
+通过使用 `` 和 `` 标签在页面内过滤内容、使用查询参数过滤端点输出、使用 `noindex` 排除页面或提供您自己的自定义文件来自定义 LLM 从您的站点接收的内容。
+
+## 页面内过滤
+
+在页面内,使用 `` 和 `` 标签来控制哪些内容暴露给 AI,哪些内容显示给文档站点上的人类读者。
+
+### 仅供 AI 使用的内容
+
+`` 内容仅出现在外部代理(如 Claude、ChatGPT 或 Cursor)直接获取的 LLM 服务端点上:`/llms.txt`、`/llms-full.txt` 和每个页面的 [`.md`/`.mdx` 源文件](/learn/docs/developer-tools/view-markdown)。它在所有面向人类的界面中都被隐藏,包括渲染页面、[复制页面](/learn/docs/configuration/site-level-settings#page-actions-configuration)、搜索组件和 [Ask Fern](/learn/docs/ai-features/ask-fern/overview)。
+
+使用 `` 用于:
+- 对 AI 有帮助但过于冗长的技术上下文,如实现细节或架构说明
+- 会使人类 UI 混乱的代码相关元数据
+- 帮助 AI 理解页面之间关系的交叉引用
+
+### 仅供人类使用的内容
+
+`` 内容出现在所有面向人类的界面上,包括渲染页面、[复制页面](/learn/docs/configuration/site-level-settings#page-actions-configuration)、搜索组件和 [Ask Fern](/learn/docs/ai-features/ask-fern/overview)(它会索引并像引用其他页面内容一样引用此内容)。它会从 LLM 服务端点(`/llms.txt`、`/llms-full.txt` 和每个页面的 `.md`/`.mdx` 源文件)中被移除。
+
+使用 `` 用于:
+- 营销 CTA 或推广内容
+- 仅供人类读者使用的导航提示
+- 应该仅保留在源文件中的内部注释
+
+### 示例
+
+Fern 自己的 [docs 快速开始](https://github.com/fern-api/docs/blob/main/fern/products/docs/pages/getting-started/quickstart.mdx) 将 GitHub UI 点击步骤与其 CLI 等效操作配对:
+
+````jsx quickstart.mdx wordWrap
+使用 `fern-api/docs-starter` 仓库作为您站点的模板:
+
+
+1. 导航到 [fern-api/docs-starter](https://github.com/fern-api/docs-starter) 并点击 **Use this template** 按钮(位于此页面右上角)。您必须登录 GitHub。
+2. 选择 **create a new repository** 选项。将其命名为 `fern-docs`。
+3. 克隆您新创建的仓库并在您喜欢的代码编辑器中打开它(例如,Cursor、VS Code)。
+
+
+
+使用 GitHub CLI 从模板创建新仓库并在本地克隆它:
+
+```bash
+gh repo create my-org/fern-docs --template fern-api/docs-starter --private --clone
+cd fern-docs
+```
+
+将 `my-org/fern-docs` 替换为您期望的所有者和仓库名称。如果您想要公共仓库,请使用 `--public` 而不是 `--private`。
+
+````
+
+
+
+ 使用 `fern-api/docs-starter` 仓库作为您站点的模板:
+
+
+ 1. 导航到 [fern-api/docs-starter](https://github.com/fern-api/docs-starter) 并点击 **Use this template** 按钮(位于此页面右上角)。您必须登录 GitHub。
+ 2. 选择 **create a new repository** 选项。将其命名为 `fern-docs`。
+ 3. 克隆您新创建的仓库并在您喜欢的代码编辑器中打开它(例如,Cursor、VS Code)。
+
+
+
+ 使用 GitHub CLI 从模板创建新仓库并在本地克隆它:
+
+ ```bash
+ gh repo create my-org/fern-docs --template fern-api/docs-starter --private --clone
+ cd fern-docs
+ ```
+
+ 将 `my-org/fern-docs` 替换为您期望的所有者和仓库名称。如果您想要公共仓库,请使用 `--public` 而不是 `--private`。
+
+
+
+
+在文档站点上,人类读者只能看到编号的 UI 步骤 —— `` 块被隐藏。读取此页面 Markdown 输出的 LLM 看到的相反:没有 UI 步骤,只有它们可以实际运行的 `gh repo create` 命令。每个受众都得到他们可以执行的路径。
+
+指导原则:**仅 UI 元素属于人类读者,而它们的程序化等效操作属于 AI 代理。** 将可点击的卡片和 UI 演练包装在 `` 中,这样代理会跳过它们,并为每个 UI 步骤配对一个 `` 块,提供 CLI 或 API 等效操作。
+
+要预览和调试 AI 在任何页面上看到的内容,您可以在页面 URL 后添加 `.md` 或 `.mdx` 来[查看其 Markdown 源文件](/learn/docs/developer-tools/view-markdown)。
+
+## 过滤端点输出
+
+使用 `lang` 和 `excludeSpec` 查询参数过滤 `llms.txt` 和 `llms-full.txt` 输出以减少令牌使用量。参数也可以组合使用。
+
+```txt Example
+/llms.txt?lang=python
+/llms-full.txt?excludeSpec=true
+/llms-full.txt?lang=python&excludeSpec=true
+```
+
+
+ 将 SDK 代码示例过滤到特定语言。也接受常见别名:`javascript`、`typescript`、`js`、`ts`、`py` 和 `golang`。不区分大小写。
+
+
+
+ 排除 OpenAPI 和 AsyncAPI 规范部分。
+
+
+## 排除整个页面
+
+您可以通过[在页面的 frontmatter 中添加 `noindex: true`](/learn/docs/seo/setting-seo-metadata#noindex) 来从 LLM 端点(`llms.txt` 和 `llms-full.txt`)中排除整个页面。标记为 `noindex` 的页面不会被搜索引擎索引,但在您的侧边栏导航中保持可见,仍然可以通过 URL 直接访问。要同时从导航中隐藏页面,请参阅[隐藏内容](/learn/docs/customization/hiding-content)。
+
+```mdx docs/pages/internal-notes.mdx
+---
+title: 内部说明
+noindex: true
+---
+```
+
+## 提供自定义文件
+
+要提供您自己的 `llms.txt` 或 `llms-full.txt` 而不是自动生成的版本,请在 [`docs.yml` 中的 `agents` 键](/learn/docs/configuration/site-level-settings#agents-configuration)下指向您的文件:
+
+```yaml docs.yml
+agents:
+ llms-txt: ./path/to/llms.txt
+ llms-full-txt: ./path/to/llms-full.txt
+```
+
+路径相对于 `docs.yml` 文件。CLI 会验证每个文件是否存在,并将其作为文档部署的一部分上传。您的自定义文件在根级别的 `/llms.txt` 和 `/llms-full.txt` 端点提供服务。嵌套路径(例如,`/api-reference/llms.txt`)继续使用自动生成的输出。
+
+您可以提供一个或两个文件。任何您未指定的文件都会回退到自动生成的版本。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/llms-txt/directives.mdx b/fern/translations/zh/products/docs/pages/ai/llms-txt/directives.mdx
new file mode 100644
index 000000000..855c52ad1
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/llms-txt/directives.mdx
@@ -0,0 +1,29 @@
+---
+title: Agent 指令
+description: 配置提供给 AI agents 的每个页面默认预置指令,或使用自定义指令覆盖它。
+sidebar-title: 智能体指令
+---
+
+提供给 AI agents 的每个页面都会自动预置一个默认指令,告诉 agents 如何以编程方式导航您的文档:
+
+```text title="默认页面指令" wordWrap
+For clean Markdown of any page, append .md to the page URL. For a complete documentation index, see https://docs.example.com/llms.txt. For full documentation content, see https://docs.example.com/llms-full.txt.
+```
+
+指令中的 URL 是根据您网站的域名和基础路径生成的。指令在前言元数据部分之后但页面正文之前注入,因此即使 agents 截断页面的其余部分,它们也会首先看到指令。它适用于单个页面 Markdown(`.md`/`.mdx` URLs)和 `llms-full.txt` 中的每个页面部分,面向人类的文档不受影响。
+
+## 自定义 agent 指令
+
+要覆盖默认指令,请使用 [`docs.yml` 中的 `agents` 键](/learn/docs/configuration/site-level-settings#agents-configuration)设置自定义指令:
+
+```yaml docs.yml
+agents:
+ page-directive: "For a complete page index, fetch https://docs.example.com/llms.txt"
+```
+
+要完全禁用指令,请将 `page-directive` 设置为空字符串:
+
+```yaml docs.yml
+agents:
+ page-directive: ""
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/llms-txt/overview.mdx b/fern/translations/zh/products/docs/pages/ai/llms-txt/overview.mdx
new file mode 100644
index 000000000..7c3d639b5
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/llms-txt/overview.mdx
@@ -0,0 +1,86 @@
+---
+title: "`llms.txt` 和 `llms-full.txt`"
+description: Fern 自动生成 llms.txt 和 llms-full.txt Markdown 文件,以便 AI 工具可以发现和索引您的文档。
+sidebar-title: '`llms.txt` 和 `llms-full.txt`'
+---
+
+[`llms.txt`](https://llmstxt.org/) 是一个向 AI 开发工具暴露网站内容的标准。Fern 实现了这个标准,自动生成和维护 `llms.txt` 和 `llms-full.txt` Markdown 文件,以便 AI 工具可以发现和索引您的文档。
+
+Fern 还在任何页面 URL 上提供[干净的 Markdown 而不是 HTML](https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation),当请求包含 `Accept: text/markdown` 头时,确保代理只接收它们需要的内容。这些功能结合在一起可以减少 90% 以上的 token 消耗。
+
+
+
+
+
+## 生成的文件
+
+Fern 为 LLM 生成两个文件:
+
+- **`llms.txt`** 包含您的文档站点的轻量级摘要,每个页面都提炼为一句话描述和 URL。对于有 API 端点的站点,它还链接到您的 [OpenAPI 规范](/learn/docs/developer-tools/openapi-spec) 作为独立的、机器可读的文件,以便 AI 工具可以直接解析您的完整 API 模式。对于有 WebSocket 通道的站点,它还链接到您的 [AsyncAPI 规范](/learn/docs/developer-tools/asyncapi-spec)。
+
+- **`llms-full.txt`** 包含完整的文档内容,包括所有页面的全文。对于 API 文档,这包括您的完整 API 参考,带有已解析的 OpenAPI 规范和启用语言的 SDK 代码示例。
+
+这两个文件都可以在您的文档层次结构的任何级别获得(`/llms.txt`、`/llms-full.txt`、`/docs/llms.txt`、`/docs/ai-features/llms-full.txt` 等)。
+
+示例:[Eleven Labs llms.txt](https://elevenlabs.io/docs/llms.txt),[Cash App llms-full.txt](https://developers.cash.app/llms-full.txt)。
+
+## 页面描述
+
+这两个文件都包含从 [frontmatter](/learn/docs/configuration/page-level-settings) 提取的页面描述。Fern 使用 `description` 字段(如果存在),否则回退到 `subtitle`。
+
+```mdx title="Frontmatter"
+---
+title: Fern Docs
+subtitle: Build beautiful documentation websites with Fern.
+---
+```
+
+输出格式取决于您是否请求单个页面或部分:
+
+
+
+`llms.txt` 和 `llms-full.txt` 返回相同的格式:
+
+```txt title=".../page/llms.txt and .../page/llms-full.txt"
+# Fern Docs
+
+> Build beautiful documentation websites with Fern.
+```
+
+
+
+这两个文件不同:
+
+
+```txt title=".../section/llms.txt"
+- [Fern Docs](https://example.com/docs): Build beautiful documentation websites with Fern.
+```
+
+```txt title=".../section/llms-full.txt"
+# Fern Docs
+
+> Build beautiful documentation websites with Fern.
+```
+
+
+
+
+## 了解更多
+
+
+
+
+ 排除页面、使用标签过滤内容或提供您自己的自定义文件。
+
+
+
+ 配置默认指令,该指令会添加到每个提供给 AI 代理的页面前面。
+
+
+ 跟踪 LLM 流量并向读者暴露 `llms.txt` 端点。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/mcp-server.mdx b/fern/translations/zh/products/docs/pages/ai/mcp-server.mdx
new file mode 100644
index 000000000..fb7af145a
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/mcp-server.mdx
@@ -0,0 +1,31 @@
+---
+title: MCP 服务器
+description: 连接 AI 客户端如 Claude Code 和 Cursor 到您的文档站点的 MCP 服务器,获取即时答案。
+sidebar-title: MCP 服务器
+---
+
+Fern 会自动为每个启用了 [Ask Fern](/learn/docs/ai-features/ask-fern/overview) 的文档站点生成并托管一个生产就绪的 [Model Context Protocol (MCP)](https://modelcontextprotocol.io) 服务器。该服务器将 AI 客户端(如 Claude Code、Cursor 和 Windsurf)连接到您的文档作为外部数据源,这样开发者就可以直接在开发环境中获得关于您产品的即时答案。
+
+您的 MCP 服务器位于 `your-documentation-site.com/_mcp/server`。例如,本站的 MCP 服务器位于 [https://buildwithfern.com/learn/_mcp/server](https://buildwithfern.com/learn/_mcp/server)。
+
+## 从您的文档站点连接
+
+[页面操作](/learn/docs/configuration/site-level-settings#page-actions-configuration)按钮让用户可以一键连接到您的 MCP 服务器:
+
+- **连接到 Claude Code** 会复制一个 `claude mcp add` 命令到剪贴板,用于注册服务器。
+- **连接到 Cursor** 会打开 Cursor 并预填服务器 URL,实现一键安装。
+
+启用了 Ask Fern 的站点默认启用这两个按钮。对于其他客户端(Claude Desktop、Windsurf 等),用户可以将 `your-documentation-site.com/_mcp/server` 添加到他们的 MCP 配置中。
+
+## AI 代理的直接 API 访问
+
+AI 代理可以通过 HTTP 直接访问您的文档。Fern 以清洁的 Markdown 格式提供内容,以提高令牌效率。
+
+对于需要身份验证的站点,代理可以通过 Fern API 密钥使用 [`/api/fern-docs/get-jwt`](/learn/docs/fern-api-reference/get-jwt) 获取 JWT,以访问受保护的文档内容和搜索功能。
+
+```bash Access protected content
+curl https://docs.example.com/platform/overview \
+ -H 'Accept: text/plain' \
+ -H 'x-fern-host: docs.example.com' \
+ -H 'FERN_TOKEN: your-jwt-here'
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/ai/overview.mdx b/fern/translations/zh/products/docs/pages/ai/overview.mdx
new file mode 100644
index 000000000..97c27193e
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/overview.mdx
@@ -0,0 +1,49 @@
+---
+title: AI 功能
+sidebar-title: AI 功能
+description: Fern AI 功能帮助用户即时找到答案,自动更新内容,并通过 llms.txt 支持为 AI 工具优化文档。
+---
+
+
+您的文档站点自带针对 AI 工具的自动优化,以及可供安装的功能,帮助用户找到答案并保持内容的及时更新。
+
+
+
+ AI 功能按使用量计费并消耗额度。每个 [套餐](https://buildwithfern.com/pricing) 都包含每月额度配额:Hobby 套餐获得 250 额度,Pro 套餐获得 1,000 额度,Enterprise 套餐获得自定义额度。
+
+ | 功能 | 额度 |
+ | --- | --- |
+ | Ask Fern | 每条消息消耗 2 额度 |
+ | AI 生成示例 | 1 额度 |
+ | Fern Writer 会话 | 50 额度 |
+
+
+
+## 查找答案
+
+无论用户在何处工作,都能即时获取来自您文档的带引用答案。Ask Fern 提供以下形式:嵌入式聊天小部件、用于自定义集成的 [API](/learn/docs/ai-features/ask-fern/api-reference/overview),以及面向社区的 [Slack 应用](/learn/docs/ai-features/ask-fern/slack-app)。对于使用 Claude Code、Cursor、Windsurf 等 AI 客户端的开发者,Fern 还托管了 MCP 服务器,便于他们直接从开发环境中查询文档。
+
+
+
+
+
+
+
+
+## 创建和更新内容
+
+AI 帮助保持您的文档实时更新。Fern Writer 是一个基于 Slack 的技术写作代理,当您标记 `@Fern Writer` 请求更新时,它会创建带有针对性编辑的 pull request。对于 API 参考文档,Fern 会根据您的 OpenAPI 规范自动生成贴近实际的示例,并随规范变更同步更新,将 `"string"` 等占位值替换为可信的数据。
+
+
+
+
+
+
+## 为 AI 优化
+
+您的站点会针对 AI 工具和搜索引擎进行自动优化。Fern 托管 `llms.txt` 和 `llms-full.txt` 文件,便于 LLM 高效索引您的文档,并向 AI 代理返回 Markdown 而非 HTML。这些功能可减少 token 消耗,帮助代理更快处理您的内容。
+
+
+
+
+
diff --git a/fern/translations/zh/products/docs/pages/ai/writer.mdx b/fern/translations/zh/products/docs/pages/ai/writer.mdx
new file mode 100644
index 000000000..990c96946
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/ai/writer.mdx
@@ -0,0 +1,105 @@
+---
+title: Fern Writer
+description: 基于 Slack 的技术写作代理,通过 GitHub 拉取请求更新您的文档
+sidebar-title: Fern Writer
+---
+
+Fern Writer 是一个基于 Slack 的技术写作代理,可在您的产品发展过程中保持文档同步。它由 [Cognition 的 Devin](https://cognition.ai/blog/introducing-devin) 驱动。Fern Writer 理解 Fern 组件和您的写作风格,并可通过文档仓库中的 `AGENTS.md` 文件进行自定义。
+
+
+
+
+
+## 工作原理
+
+### 发起请求
+
+在您已添加 Fern Writer 的 Slack 频道中,标记 `@Fern Writer` 并描述您需要的更改。Fern Writer [仅在被直接标记时响应](#隐私和数据处理)。它会对您的消息进行表情反应以确认收到,然后创建拉取请求并回复链接。
+
+
+
+
+
+Fern Writer 支持图片和文件附件以提供额外的上下文。当在现有对话串中被标记时,它会读取完整对话以理解上下文后再响应。
+
+| 用例 | 示例请求 |
+|----------|----------------|
+| 为新功能编写文档(基于拉取请求) | `@Fern Writer 为 PR #123 中添加的新速率限制功能编写文档` |
+| 向现有页面添加新内容 | `@Fern Writer 在 webhook 指南中添加关于 webhook 重试行为的章节` |
+| 重新组织和整合内容 | `@Fern Writer 合并身份验证和授权页面,并从旧的认证页面添加重定向` |
+| 修复错误并提高清晰度 | `@Fern Writer 修复快速开始中损坏的代码示例,并将包版本更新到 v2.1.0` |
+
+
+
+
+
+### 审查和合并
+
+通过在 Slack 对话串中评论来请求更改。一旦 PR 满足您的要求,就像合并其他任何拉取请求一样合并它。
+
+### 拉取请求归属
+
+
+
+
+
+每个拉取请求在描述中都包含一个 **请求者** 字段,将更改归属于发起请求的人员或团队。提交已签名并归属于 `fern-support`,确保自动更改与您仓库历史记录中的手动贡献明确区分。
+
+## 设置
+
+
+ Fern Writer 仅支持 GitHub。不支持 GitLab 和其他 Git 提供商。
+
+
+要开始使用 Fern Writer,请将其添加到您的 Slack 工作区(您必须是 Slack 管理员)并将其邀请到您的团队讨论文档的频道中。
+
+
+
+
+[获取您组织的专属 Slack 安装链接](/learn/docs/scribe-api/fern-writer-api/get-fern-writer-install-link)。提供:
+- 您的 [Fern 令牌](/learn/cli-api-reference/cli-reference/commands#fern-token)
+- 包含您文档的 GitHub 仓库,格式为 `owner/repo`(例如 `acme/docs`)。[Fern GitHub App](https://github.com/apps/fern-api) 必须安装在该仓库中。
+
+您也可以使用此 cURL 请求:
+```bash
+curl -G https://fai.buildwithfern.com/scribe/slack/get-install \
+ -H "Authorization: Bearer " \
+ --data-urlencode github_repo=
+```
+
+访问响应中返回的 URL。
+
+
+
+您将被重定向到 Slack 以授权 Fern Writer。选择您想添加 Fern Writer 的工作区并点击 **允许**。
+
+
+
+
+安装完成后,将 Fern Writer 添加到您团队讨论文档的 Slack 频道中。
+
+
+
+
+## 隐私和数据处理
+
+Fern Writer 不会直接存储您的 Slack 消息。当您标记 `@Fern Writer` 或引用消息或对话串时,内容会存储在会话中以生成文档拉取请求。任务完成后不会保留会话数据。
+
+无论是 Fern 还是 [Devin](https://docs.devin.ai/admin/security#how-is-your-data-used-to-improve-devin) 都不会使用您的数据来训练 AI 模型。Fern 明确配置其 Devin 集成以选择退出任何用于模型训练的数据收集。您的频道消息、代码和文档内容永远不会用于训练目的。有关其他详细信息,请参阅 Devin 关于 [Slack 集成安全性](https://docs.devin.ai/admin/security#integrating-with-slack) 的文档。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/api-references/api-explorer.mdx b/fern/translations/zh/products/docs/pages/api-references/api-explorer.mdx
new file mode 100644
index 000000000..0d70d4ffb
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/api-references/api-explorer.mdx
@@ -0,0 +1,70 @@
+---
+title: API 探索器
+subtitle: 通过允许用户直接在 API 参考文档中对您的 API 进行真实调用,来减少"获得 200 响应的时间"。
+sidebar-title: API 资源管理器
+---
+
+Fern 的 API 探索器允许用户在不离开文档的情况下对您的 API 发起经过身份验证的请求。
+
+## 使用示例自动填充
+Fern 将自动使用 API 规范中设置的值填充端点的字段。
+
+
+
+## 身份验证
+
+API 探索器支持在您的 OpenAPI 规范或 `generators.yml` 中配置的[所有身份验证方案](/learn/api-definitions/openapi/authentication),包括多种身份验证方案。当有多种方案可用时,API 探索器会自动在下拉菜单中显示它们,允许用户在发送请求之前选择并配置其首选的身份验证方法。
+
+一旦用户设置了身份验证凭据,他们的凭据将在整个探索会话期间保持不变。
+
+
+
+
+身份验证凭据仅使用 cookie 存储在客户端。不会收集或存储任何敏感的用户信息。
+
+
+要为已登录用户自动填充 API 密钥,请参阅 [API 密钥注入](/learn/docs/authentication/features/api-key-injection)。
+
+## 多环境
+
+当在 [OpenAPI](/learn/api-definitions/openapi/extensions/server-names-and-url-templating) 或 [Fern Definition](/learn/api-definitions/ferndef/api-yml/environments) 中配置了多个服务器 URL 时,用户可以从 API 探索器的下拉菜单中在不同环境(例如,生产环境和沙盒环境)之间切换。所选环境在他们在页面之间导航时保持不变。
+
+
+
+用户还可以双击服务器 URL 手动编辑它,允许快速测试自定义环境或端点。
+
+这是配置了多个服务器名称的 [Flagright 文档网站](https://docs.flagright.com/framl-api/api-reference/api-reference/transactions/get) 示例。
+
+
+
+
+ ```yaml
+ openapi: 3.0.0
+ servers:
+ - url: https://sandbox.api.flagright.com
+ x-fern-server-name: Sandbox API server (eu-1)
+ - url: https://sandbox-asia-1.api.flagright.com
+ x-fern-server-name: Sandbox API server (asia-1)
+ ```
+
+
+
+
+ ```yaml
+ environments:
+ Sandbox API server (eu-1): https://sandbox.api.flagright.com
+ Sandbox API server (asia-1): https://sandbox-asia-1.api.flagright.com
+ ```
+
+
+
+
+## WebSocket Playground
+
+对于支持 WebSocket 连接的 API,API 探索器包含一个 **WebSocket** 特定的 Playground。WebSocket Playground 还允许用户与 API 建立连接,并实时发送/接收消息。
+
+
+
+## 控制 API 探索器可用性
+
+对于 OpenAPI 规范,API 探索器默认为所有端点启用。您可以使用 [`x-fern-explorer`](/learn/api-definitions/openapi/extensions/api-explorer-control) 扩展全局或按端点禁用它。这通常用于禁用破坏性操作、支付处理或仅限管理员端点的探索器。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/api-references/api-ref-content.mdx b/fern/translations/zh/products/docs/pages/api-references/api-ref-content.mdx
new file mode 100644
index 000000000..dc7502a48
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/api-references/api-ref-content.mdx
@@ -0,0 +1,127 @@
+---
+title: 在 API Reference 中编写 Markdown 内容
+description: 在 API 文档中编写丰富的 Markdown 内容。为端点添加描述,创建摘要页面,并自定义您的 API Reference 布局。
+sidebar-title: 在 API 参考中编写 Markdown 内容
+---
+
+
+Fern Docs 允许您在 API Reference 文档中编写 Markdown 内容。此功能对于为 API 端点提供额外的上下文、示例或说明非常有用。
+
+## 为端点添加 Markdown 内容
+
+您可以使用 `description` 字段(OpenAPI)或 `docs` 字段(Fern Definition)在 API 定义中包含 Markdown 内容。这包括标注、代码块和[其他组件](/learn/docs/writing-content/components/overview)。
+
+您还可以使用 `
),
+ SEARCH_TYPE: (设置为 ai 以打开 Ask AI 面板。
),
+ QUERY1: (发送给 Ask AI 的提示,URL 编码。
),
+ QUERY2: (搜索词,URL 编码。
)
+ }}
+>
+
+```bash showLineNumbers={false}
+# 使用提示打开 Ask Fern 侧面板
+https://{{PAGE_URL}}?searchType={{SEARCH_TYPE}}&query={{QUERY1}}
+
+# 使用查询打开搜索
+https://{{PAGE_URL}}?query={{QUERY2}}
+```
+
+
+
+| 参数 | 描述 |
+| --- | --- |
+| `query` | 搜索查询或提示,URL 编码。 |
+| `searchType` | 可选。设置为 `ai` 以打开 Ask AI 面板,或省略以打开常规搜索。 |
+
+
+Ask Fern 自动遵守[在您的文档中配置的基于角色的访问控制 (RBAC) 设置](/learn/docs/authentication/features/rbac)。当用户查询 Ask Fern 时,他们只会从根据其分配角色有权访问的文档中获得答案。
+
+这适用于所有级别,从整个部分到单个页面以及页面内的条件内容。
+
+
+
+
+## 内部原理
+
+Ask Fern 使用检索增强生成 (RAG) 来回答用户问题:
+
+1. **内容和代码索引** — Fern 处理您的文档页面和 Fern 生成的 SDK 代码,将它们分解为语义块,并将每个块转换为存储在搜索索引中的向量嵌入。
+2. **查询处理** — 当用户提问时,Ask Fern 将查询向量化并检索最相关的块。如果配置了 RBAC,结果会按用户权限进行过滤。
+3. **响应生成** — Ask Fern 将检索到的块作为上下文发送给 Claude 4.6 Sonnet 以生成带引用的答案。如果初始上下文不足,它会执行额外的关键词搜索。
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant U as User
+ participant C as /chat Endpoint
+ participant V as Documentation Database
+ participant A as Ask Fern
+
+ U->>C: Submit question via Ask Fern searchbox
+ C->>C: Convert query to vector
+ C->>C: Check user roles (if RBAC enabled)
+ C->>V: Search for relevant chunks
+ V->>C: Return matching documents user can access
+ C->>A: Send query + context
+ A->>V: Perform additional keyword search if needed
+ V->>A: Return additional chunks user can access
+ A->>A: Generate response
+ A->>U: Return answer with citations
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/api-key-injection.mdx b/fern/translations/zh/products/docs/pages/authentication/api-key-injection.mdx
new file mode 100644
index 000000000..32b53e0de
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/api-key-injection.mdx
@@ -0,0 +1,105 @@
+---
+title: API key injection
+subtitle: 为登录用户在 API Explorer 中自动填充 API keys。
+sidebar-title: API 密钥注入
+---
+
+
+
+
+API key injection 是 [JWT](/learn/docs/authentication/setup/jwt) 和 [OAuth](/learn/docs/authentication/setup/oauth) 身份验证的一个功能。当用户登录时,会在其浏览器中设置一个 [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie,其中包含 `fern.playground` 声明,告诉 [API Explorer](/learn/docs/api-references/api-explorer) 要预填充什么值——API keys、headers 或其他凭据。您可以将其与 [RBAC](/learn/docs/authentication/features/rbac) 在单个令牌中结合使用。
+
+
+
+
+用户凭据仅存储在浏览器 cookies 中,永远不会传输到 Fern 的服务器。了解更多信息请参阅[安全概述](/learn/docs/security/overview)。
+
+
+## 设置
+
+要启用 API key injection,请按照 [JWT](/learn/docs/authentication/setup/jwt) 或 [OAuth](/learn/docs/authentication/setup/oauth) 设置指南进行操作。
+
+### 高级载荷配置
+
+通过 [JWT 设置](/learn/docs/authentication/setup/jwt),您可以完全控制 `fern.playground` 载荷。这些选项让您超越单个 bearer token——预填充自定义 headers、支持多个 API keys,或根据环境变化凭据。这些选项在 OAuth 中不可用,因为 Fern 管理令牌。
+
+
+
+您可以在身份验证凭据旁预填充 headers、路径参数和查询参数:
+
+```json maxLines=10 startLine=5
+{
+ "fern": {
+ "playground": {
+ "initial_state": {
+ "auth": {
+ "bearer_token": "eyJhbGciOiJIUzI1c"
+ },
+ "headers": {
+ "API-Version": "2024-02-02"
+ },
+ "path_parameters": {
+ "plantId": "plant_1234"
+ },
+ "query_parameters": {
+ "sort": "DESCENDING"
+ }
+ }
+ }
+ }
+}
+```
+
+
+
+要提供多个 API keys(例如,每个应用程序一个),请将 `bearer_token` 设置为 JSON 编码的键值对象数组。每个对象将应用程序名称映射到其密钥。
+
+```json maxLines=5 startLine=2
+{
+ "fern": {
+ "playground": {
+ "initial_state": {
+ "auth": {
+ "bearer_token": "[{\"Greenhouse app\": \"sk-greenhouse-abc123\"}, {\"Garden app\": \"sk-garden-def456\"}]"
+ }
+ }
+ }
+ }
+}
+```
+
+API Explorer 显示一个下拉菜单,用户可以选择使用哪个应用程序密钥进行请求。
+
+
+
+使用 `env_state` 为每个环境提供不同的凭据(例如,生产环境与预发环境)。`env_state` 中的每个键都使用子字符串匹配与选定的环境 URL 进行匹配。
+
+```json maxLines=10 startLine=2
+{
+ "fern": {
+ "playground": {
+ "initial_state": {
+ "auth": {
+ "bearer_token": "default-token"
+ }
+ },
+ "env_state": {
+ "prod": {
+ "auth": {
+ "bearer_token": "prod-token-abc123"
+ }
+ },
+ "staging": {
+ "auth": {
+ "bearer_token": "staging-token-def456"
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+当用户选择包含 `prod` 的环境(如 `https://api.prod.example.com`)时,API Explorer 使用 `prod-token-abc123`。`env_state` 值会合并到 `initial_state` 之上:auth 完全替换,而 headers、路径参数和查询参数进行浅合并。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/jwt-setup.mdx b/fern/translations/zh/products/docs/pages/authentication/jwt-setup.mdx
new file mode 100644
index 000000000..1942577ee
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/jwt-setup.mdx
@@ -0,0 +1,205 @@
+---
+title: 设置 JWT
+subtitle: 与您的登录系统集成的自管理身份验证
+sidebar-title: 设置 JWT
+---
+
+
+
+
+使用 JWT,您可以管理整个身份验证流程。这涉及构建和签署一个 [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie,将您的文档与现有登录系统集成。与 [OAuth](/learn/docs/authentication/setup/oauth) 类似,JWT 支持:
+
+- **仅登录** — 通过身份验证来保护文档
+- **[RBAC](/learn/docs/authentication/features/rbac)** — 按用户角色限制内容
+- **[API 密钥注入](/learn/docs/authentication/features/api-key-injection)** — 在 [API Explorer](/learn/docs/api-references/api-explorer) 中预填充 API 密钥
+
+## 工作原理
+
+1. 用户在您的文档站点上点击 **登录**,然后被重定向到您的身份验证页面。
+2. 身份验证后,您的系统使用来自 Fern 的密钥签署一个 [JWT](https://jwt.io),并将其设置为 `fern_token` cookie。
+3. Fern 读取令牌以确定用户的访问权限和凭据。
+
+
+```mermaid
+sequenceDiagram
+ participant U as User
+ participant F as Fern Docs
+ participant R as Redirect URL
+ participant A as Auth System
+
+ U->>F: Visit restricted page
+ F->>F: Check fern_token cookie
+
+ alt Cookie exists
+ F->>F: Decode JWT with secret key
+ F->>F: Extract roles from JWT
+ F->>F: Check if user has required role
+
+ alt User has required role
+ F->>U: Show restricted content
+ else User lacks required role
+ F->>U: User is shown a 404 page
+ end
+ else No cookie
+ F->>R: Redirect to login page
+ R->>A: Authenticate user
+ end
+
+ Note over A: User logs in
+
+ A->>A: Generate JWT with roles
+ A->>F: Set fern_token cookie
+ F->>F: Validate JWT and roles
+ F->>U: Show restricted content
+```
+
+
+## 配置
+
+
+
+联系 Fern 获取您的密钥,并向他们发送您的身份验证页面 URL。这是用户点击 **登录** 后被重定向的地方。
+
+
+
+JWT 负载必须包含一个 `fern` 声明。您在令牌的 `fern` 声明中包含的内容控制启用的功能:仅登录、RBAC 或 API 密钥注入。
+
+
+```json 仅登录
+{
+ "fern": {}
+}
+```
+
+```json RBAC
+{
+ "fern": {
+ "roles": ["partners"]
+ }
+}
+```
+
+```json API 密钥注入
+{
+ "fern": {
+ "playground": {
+ "initial_state": {
+ "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" }
+ }
+ }
+ }
+}
+```
+
+```json API 密钥注入 + RBAC
+{
+ "fern": {
+ "roles": ["partners"],
+ "playground": {
+ "initial_state": {
+ "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" }
+ }
+ }
+ }
+}
+```
+
+
+
+
+在您的服务中添加逻辑,在用户登录时签署 JWT 并将其设置为 `fern_token` cookie。
+
+
+这个 Next.js 端点处理来自您的身份验证页面的回调。它读取 `state` 参数来确定将用户重定向到何处,使用 [jose](https://github.com/panva/jose) 生成 `fern_token` JWT,将其设置为 cookie,并将用户重定向回文档。
+
+```typescript title="app/api/fern-token/route.ts"
+import { SignJWT } from "jose";
+import { cookies } from "next/headers";
+import { type NextRequest, NextResponse } from "next/server";
+
+export async function GET(req: NextRequest): Promise {
+ const domain = getDomain(req); // your logic to determine the docs domain
+
+ // use the state param to determine redirect location
+ const returnTo = req.nextUrl.searchParams.get("state");
+ const redirectLocation = returnTo ?? `https://${domain}`;
+
+ // fetch the user's API key, roles, and secret (from your config or database)
+ const apiKey = await getApiKeyForUser();
+ const roles = await getRolesForUser();
+ const secret = await getSecretForDomain(domain);
+
+ if (!secret) {
+ // redirect with an error if credentials are missing
+ const url = new URL(redirectLocation);
+ url.searchParams.set("error", "missing_credentials");
+ return NextResponse.redirect(url);
+ }
+
+ // mint the JWT using the secret key
+ const fernToken = await mintFernToken({ secret, apiKey, roles });
+
+ if (!fernToken) {
+ const url = new URL(redirectLocation);
+ url.searchParams.set("error", "token_creation_failed");
+ return NextResponse.redirect(url);
+ }
+
+ // set the fern_token as a cookie on the docs domain
+ const cookieJar = await cookies();
+ cookieJar.set("fern_token", fernToken, {
+ httpOnly: true,
+ secure: true,
+ sameSite: "lax",
+ domain,
+ });
+
+ // redirect the user back to the docs
+ return NextResponse.redirect(redirectLocation);
+}
+
+const encoder = new TextEncoder();
+
+async function mintFernToken({
+ secret,
+ apiKey,
+ roles,
+}: {
+ secret: string;
+ apiKey?: string;
+ roles?: string[];
+}): Promise {
+ const fern: Record = {};
+
+ if (roles) {
+ fern.roles = roles;
+ }
+
+ if (apiKey) {
+ fern.playground = {
+ initial_state: {
+ auth: {
+ bearer_token: apiKey,
+ },
+ },
+ };
+ }
+
+ return await new SignJWT({ fern })
+ .setProtectedHeader({ alg: "HS256", typ: "JWT" })
+ .setIssuedAt()
+ .setExpirationTime("1d") // set to any value
+ .setIssuer("https://buildwithfern.com")
+ .sign(encoder.encode(secret)); // sign using the secret provided by Fern
+}
+```
+
+
+
+
+一旦您的 `fern_token` 工作正常,配置您需要的功能:
+
+- **[基于角色的访问控制](/learn/docs/authentication/features/rbac)** — 在 `docs.yml` 中定义角色,并按角色限制导航项或页面内容。
+- **[API 密钥注入](/learn/docs/authentication/features/api-key-injection)** — 配置 `playground` 负载,包括自定义标头、多个 API 密钥和按环境凭据。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/oauth-setup.mdx b/fern/translations/zh/products/docs/pages/authentication/oauth-setup.mdx
new file mode 100644
index 000000000..5946a7e12
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/oauth-setup.mdx
@@ -0,0 +1,158 @@
+---
+title: 设置 OAuth
+subtitle: 与您的登录系统集成的 Fern 托管身份验证
+sidebar-title: 设置 OAuth
+---
+
+
+
+
+使用 OAuth,Fern 为您管理身份验证流程。您为 Fern 提供访问您的 OAuth 提供商的权限,Fern 处理 [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie,将您的文档与现有登录系统集成。与 [JWT](/learn/docs/authentication/setup/jwt) 一样,OAuth 支持:
+
+- **[RBAC](/learn/docs/authentication/features/rbac)** — 按用户角色限制内容
+- **[API 密钥注入](/learn/docs/authentication/features/api-key-injection)** — 在 [API 探索器](/learn/docs/api-references/api-explorer)中预填充 API 密钥
+
+## 工作原理
+
+1. 用户在您的文档站点上点击**登录**,Fern 启动与您提供商的 OAuth 流程。
+1. 用户在您的 OAuth 提供商登录页面进行身份验证。
+1. 您的提供商使用授权码重定向回 Fern,Fern 将其交换为访问令牌。
+1. Fern 设置包含用户访问权限和凭据的 `fern_token` cookie。
+1. 当用户点击**登出**时,Fern 清除会话 cookie。如果配置了登出 URL,用户将被重定向到您的 OAuth 提供商的登出端点以结束那里的会话。
+
+
+```mermaid
+sequenceDiagram
+ participant U as User
+ participant F as Fern Docs
+ participant A as OAuth2 Provider
+ U->>F: Visit restricted page
+ F->>F: Check fern_token cookie
+
+ alt Cookie exists
+ F->>F: Decode cookie
+ F->>F: Verify authentication credentials
+ Note over F: Attempt to refresh the token, if expired
+
+ alt User is properly authenticated
+ F->>U: Show restricted content
+ else User is not properly authenticated
+ F->>U: User is shown a 404 page
+ end
+ else No cookie
+ F->>A: Redirect to `/authenticate` endpoint
+ A->>U: User authenticates
+ U->>F: Authorization code is returned
+ F->>A: Redirect to `/token` endpoint
+ A->>A: Validate token request
+ A->>F: Send authenticated access token
+ F->>F: Set fern_token cookie
+ F->>F: Verify authentication credentials
+ F->>U: Show restricted content
+ end
+```
+
+
+## 配置
+
+
+
+转到您的 OAuth 提供商的控制面板,创建一个新的**Web 应用程序**客户端。
+
+
+
+在您的 OAuth 提供商中将以下回调添加到允许列表:
+`https:///api/fern-docs/oauth2/callback`。
+
+将 `` 替换为您的 Fern 文档域名。如果您同时使用 `.docs.buildwithfern.com` 和自定义域名,请将两者都添加到允许列表。
+
+
+
+将以下信息发送到 support@buildwithfern.com 或您专用的 Slack 频道:
+
+- [ ] 文档域名
+- [ ] 客户端 ID
+- [ ] 客户端密钥
+- [ ] 授权 URL(例如 `https:///oauth2/authorize`)
+- [ ] 令牌 URL(例如 `https:///oauth2/token`)
+- [ ] 作用域(例如 `openid`、`profile`、`email`)
+- [ ] 发行者 URL(例如 `https://`)
+- [ ] 登出 URL(可选,例如 `https:///oauth2/logout`)
+
+
+如果您的客户端连接到 API,您可能需要在身份验证请求中指定受众。
+
+更新后的授权 URL 可能如下所示:`https:///oauth2/authorize?audience=`
+
+
+
+
+Fern 将在您的站点上配置 OAuth。身份验证准备就绪时,您将收到通知。
+
+
+
+OAuth 工作后,配置您需要的功能:
+
+
+
+
+
+将自定义声明添加到您的 OAuth 提供商的令牌响应中,以便 Fern 可以确定每个用户的角色。生成的令牌响应应该如下所示:
+
+```json {12-15} maxLines=7 startLine=10
+{
+ "iss": "https://your-tenant.us.auth0.com/",
+ "sub": "auth0|507f1f77bcf86cd799439011",
+ "aud": "your_client_id_here",
+ "iat": 1728388800,
+ "exp": 1728475200,
+ "email": "user@example.com",
+ "email_verified": true,
+ "name": "John Doe",
+ "nickname": "johndoe",
+ "picture": "https://s.gravatar.com/avatar/...",
+ "roles": [
+ "custom-role",
+ "user-specific-role"
+ ]
+}
+```
+
+
+一些 OAuth 提供商对自定义声明有严格要求。如果您需要使用 `roles` 以外的声明,请联系 Fern 并指定应该解析哪个声明来获取用户角色。
+
+
+
+要向 Auth0 添加自定义声明,您需要创建一个**自定义操作**。此操作将用于向令牌响应添加自定义声明。
+
+1. 转到 Auth0 控制面板中的**操作**标签。
+2. 创建一个**自定义操作**。
+3. 选择**登录/登录后**。
+4. 添加设置角色的逻辑。
+ ```js Example Action
+ exports.onExecutePostLogin = async (event, api) => {
+ const roles = event.user.app_metadata?.roles; // or however you store user roles
+
+ if (roles) {
+ const namespace: "https://.com"; // important: custom claims must be namespaced
+ api.accessToken.setCustomClaim(`${namespace}/roles`, roles);
+ }
+ };
+ ```
+5. 点击**创建**。
+6. 将操作添加到您的**登录后流程**。
+
+
+
+一旦您的令牌响应包含角色,在 `docs.yml` 中定义这些角色并将其分配给导航项和页面内容。完整设置请参阅[基于角色的访问控制](/learn/docs/authentication/features/rbac)。
+
+
+
+
+
+为 Fern 设置一个经过身份验证的账户,以便 Fern 可以代表您对用户进行授权,并配置您的 OAuth 应用程序在 Fern 请求令牌时返回用户 API 密钥。联系 support@buildwithfern.com 协调此设置。
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/overview.mdx b/fern/translations/zh/products/docs/pages/authentication/overview.mdx
new file mode 100644
index 000000000..9c8ba2c81
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/overview.mdx
@@ -0,0 +1,37 @@
+---
+title: 身份验证选项概述
+description: 了解 Fern 提供的不同身份验证选项
+sidebar-title: 认证选项概览
+---
+
+Fern 提供四种方式来对文档站点上的用户进行身份验证。
+
+
+
+ 整个站点的共享密码或映射到角色的多个密码
+
+
+ 内部文档的企业凭据
+
+
+ 与您的登录系统集成的自管理身份验证
+
+
+ 通过您的 OAuth 提供商的 Fern 托管身份验证
+
+
+
+## 我应该使用哪种选项?
+
+- **[密码保护](/learn/docs/authentication/setup/password-protection)** — 您需要通过共享密码进行快速访问控制(无需每用户账户)。支持映射到角色的多个密码,用于[基于角色的访问控制](/learn/docs/authentication/features/rbac)。
+- **[SSO](/learn/docs/authentication/setup/sso)** — 您的团队应使用企业凭据(Okta、Google Workspace 等)登录内部文档或 wiki。
+- **[JWT](/learn/docs/authentication/setup/jwt)** — 您希望与现有登录系统集成并自己控制整个身份验证流程。支持[基于角色的访问控制](/learn/docs/authentication/features/rbac)和 [API 密钥注入](/learn/docs/authentication/features/api-key-injection)。
+- **[OAuth](/learn/docs/authentication/setup/oauth)** — 您希望与现有登录系统集成,但让 Fern 通过您的 OAuth 提供商管理身份验证流程。支持[基于角色的访问控制](/learn/docs/authentication/features/rbac)和 [API 密钥注入](/learn/docs/authentication/features/api-key-injection)。
+
+JWT 和 OAuth 具有相同的功能——区别在于谁管理身份验证流程。两者都可以用于仅登录控制,或与 [RBAC](/learn/docs/authentication/features/rbac) 和 [API 密钥注入](/learn/docs/authentication/features/api-key-injection)结合使用,实现精细的访问控制和预填充的 API 密钥。
+
+## 身份验证的工作原理
+
+JWT、OAuth 和 SSO 都由名为 `fern_token` 的[浏览器 cookie](/learn/docs/security/overview) 支持,它告诉 Fern 用户是谁以及他们可以访问什么。该令牌可以携带用于 [RBAC](/learn/docs/authentication/features/rbac) 的用户角色、用于 [API 浏览器](/learn/docs/api-references/api-explorer)的 API 密钥,或者只是验证用户已登录。
+
+[密码保护](/learn/docs/authentication/setup/password-protection)的工作方式不同——它使用共享密码而不是每用户令牌。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/password.mdx b/fern/translations/zh/products/docs/pages/authentication/password.mdx
new file mode 100644
index 000000000..6f29781cc
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/password.mdx
@@ -0,0 +1,20 @@
+---
+title: 密码保护
+subtitle: 使用共享密码保护您的文档站点,实现简单的访问控制。
+sidebar-title: 密码保护
+---
+
+
+
+
+密码保护允许您使用单个共享密码或多个密码(最多三个)来限制对文档站点的访问,每个密码都映射到一个角色。这对于预发布文档、内部资源或任何您希望保持私密而无需个人用户账户的内容都非常有用。
+
+在 [Fern Dashboard](https://dashboard.buildwithfern.com/) 中[设置和管理密码保护](/learn/dashboard/configuration/password-protection)。如果您为不同的用户角色设置了多个密码,请配置 [RBAC](/learn/docs/authentication/features/rbac) 来控制不同组能够访问的内容。
+
+## 工作原理
+
+启用密码保护后,文档站点的访问者需要输入密码才能查看任何内容。身份验证成功后,用户可以浏览站点直到会话过期。如果配置了多个密码,输入的密码将决定用户的角色以及他们可以访问的内容。
+
+
+ 启用密码保护时,搜索引擎将不会索引您的站点。
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/rbac.mdx b/fern/translations/zh/products/docs/pages/authentication/rbac.mdx
new file mode 100644
index 000000000..4da4fed07
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/rbac.mdx
@@ -0,0 +1,95 @@
+---
+title: 基于角色的访问控制
+subtitle: 控制谁可以查看您的文档
+description: 了解如何使用基于角色的访问控制 (RBAC) 限制对文档的访问
+sidebar-title: 基于角色的访问控制
+---
+
+
+
+ 基于密码的 RBAC 在[团队版和企业版计划](https://buildwithfern.com/pricing)中可用。基于 JWT 和 OAuth 的 RBAC 需要[企业版计划](https://buildwithfern.com/pricing)。
+
+
+RBAC 根据用户角色控制对页面、部分和其他导航项目的访问。它与[密码保护](/learn/docs/authentication/setup/password-protection)、[JWT](/learn/docs/authentication/setup/jwt) 和 [OAuth](/learn/docs/authentication/setup/oauth) 身份验证配合使用。
+
+RBAC 对于合作伙伴文档、测试版功能、分层访问和内部内容非常有用。在使用 JWT 或 OAuth 身份验证时,您可以将其与 [API 密钥注入](/learn/docs/authentication/features/api-key-injection)结合使用。配置 RBAC 后,[Ask Fern](/learn/docs/ai-features/ask-fern/overview) 会自动遵守这些权限。默认情况下,受限页面对未授权用户完全隐藏——如果您希望它们可见但被锁定,请在设置期间告知 Fern。
+
+## 设置
+
+
+ RBAC 在 `docs.yml` 中配置,并通过 [Fern CLI](/learn/cli-api-reference/cli-reference/overview) 管理。如果您使用[向导界面](https://dashboard.buildwithfern.com/get-started)设置网站,您需要直接使用 Fern 配置文件而不是通过 Fern Dashboard。
+
+
+要启用 RBAC,首先设置身份验证方法——[密码保护](/learn/docs/authentication/setup/password-protection)、[JWT](/learn/docs/authentication/setup/jwt) 或 [OAuth](/learn/docs/authentication/setup/oauth)——然后在 `docs.yml` 中定义您的角色:
+
+```yml docs.yml
+roles:
+ - everyone # 每个用户都会被赋予这个角色
+ - partners
+ - beta-users
+ - admins
+```
+
+每个用户都会自动获得 `everyone` 角色,包括未经身份验证的访问者。如果用户缺乏所需角色或未经身份验证,Fern 会将他们重定向到您的登录页面。您可以定义的角色数量没有限制,除非您使用[密码保护](/learn/docs/authentication/setup/password-protection),它最多支持三个角色。
+
+## 限制内容
+
+配置 RBAC 后,在导航中使用 `viewers`,在页面中使用 `` 组件来控制每个角色可以看到的内容。
+
+### 在导航中
+
+您可以为以下导航项目分配 `viewers`:`products`、`versions`、`tabs`、`sections`、`pages`、`api references` 和 `changelogs`。
+
+如果您不指定查看者,内容将对任何*经过身份验证*的用户可见。要使内容公开访问,请明确将查看者设置为 `everyone`。
+
+```yml docs.yml {6-7, 13-15}
+navigation:
+ - tab: Home
+ layout:
+ - page: Welcome # 此页面是公开的
+ path: pages/welcome.mdx
+ viewers:
+ - everyone
+ - tab: Documentation
+ layout:
+ - page: Overview # 此页面对所有已登录用户可见
+ path: pages/overview.mdx
+ - section: Beta Release # 此部分对 beta-users 和 admins 可见
+ viewers:
+ - beta-users
+ - admins
+ contents:
+ ...
+```
+
+查看权限是继承的。例如,如果某个部分只能由 `admins` 查看,那么它的所有页面和嵌套部分也只能由管理员查看。
+
+### 在 MDX 页面中
+
+使用 `` 组件根据用户角色[有条件地渲染内容](/learn/docs/writing-content/components/if)。您可以指定一个或多个角色。内容对具有**任何**指定角色的用户可见:
+
+```mdx
+
+
+ 此内容对合作伙伴和管理员都可见。
+
+
+```
+
+您还可以将 `roles` 与 `products` 和 `versions` 属性结合使用。
+
+
+## 常见错误
+
+### 角色 "X" 被使用但未在 docs.yml 文件的顶层声明。
+
+[`viewers:`](#in-navigation) 条目或 [``](/learn/docs/writing-content/components/if) 引用使用了未在 `docs.yml` 顶层 `roles:` 键下列出的角色。将角色添加到 [`roles`](#setup) 列表中:
+
+```yaml title="docs.yml"
+roles:
+ - everyone
+ - partners
+ - beta-users
+ - admins
+```
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/authentication/sso.mdx b/fern/translations/zh/products/docs/pages/authentication/sso.mdx
new file mode 100644
index 000000000..b28286b6a
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/authentication/sso.mdx
@@ -0,0 +1,41 @@
+---
+title: 单点登录
+subtitle: 使用企业凭据安全访问您的文档
+sidebar-title: 单点登录
+---
+
+
+
+
+SSO 让您的团队通过您组织的身份提供商使用 SAML 2.0 或 OIDC 访问您的文档。与[RBAC](/learn/docs/authentication/features/rbac)和[API 密钥注入](/learn/docs/authentication/features/api-key-injection)一样,SSO 使用[`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie 来识别已认证的用户。SSO 解锁了用于浏览器编辑的[Fern Editor](/learn/docs/writing-content/fern-editor)和[认证预览链接](/learn/docs/preview-publish/preview-changes#preview-links)。
+
+SSO 提供基于登录的访问控制,但不支持角色管理或 API 密钥注入。要进行细粒度访问控制,请使用[RBAC](/learn/docs/authentication/features/rbac)。
+
+## 工作原理
+
+当用户点击**登录**时,Fern 会将他们重定向到您的身份提供商。使用企业凭据验证身份后,身份提供商会重定向回 Fern 并提供 `fern_token`,授予访问您文档的权限。
+
+
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant U as User
+ participant F as Fern Docs
+ participant I as Identity Provider
+
+ U->>F: Click "Login"
+ F->>I: Redirect to SSO login
+
+ Note over I: User authenticates with corporate credentials
+
+ I->>I: Validate user credentials
+ I->>F: Redirect back with fern_token
+ F->>F: Grant access to organizational features
+ F->>U: Show docs site
+```
+
+
+## 设置
+
+Fern 支持任何 SAML 2.0 或 OIDC 提供商(Okta、Google Workspace、Auth0、Azure AD、OneLogin 等)。[联系 Fern](https://buildwithfern.com/contact)或通过 Slack 联系我们。Fern 将与您的安全团队合作连接到您的身份提供商。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-01-24.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-01-24.mdx
new file mode 100644
index 000000000..b6944cbc4
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-01-24.mdx
@@ -0,0 +1,39 @@
+---
+tags: ["api-reference", "customization", "navigation", "search", "performance"]
+---
+
+## API 操作台发布
+在文档中直接启用交互式 API 测试功能。
+- 添加了完整的 API 请求测试功能
+- 改进了错误处理和状态码显示
+- 添加了对递归属性渲染的支持
+
+## 增强的深色模式
+对语法高亮、下拉菜单和搜索结果的深色模式可读性进行了多项改进。
+
+```css
+/* Dark mode improvements */
+[data-theme='dark'] {
+ --syntax-bg: #1a1a1a;
+ --dropdown-bg: #2d2d2d;
+ --search-highlight: #ffd700;
+}
+```
+
+## 移动友好导航
+对移动导航体验进行全面更新,支持折叠和滚动功能。
+
+## 搜索增强
+对搜索体验进行了多项改进。
+- 为搜索添加了默认和可配置的键盘快捷键(`Cmd+A`,`/`)
+- 改进了搜索框尺寸
+- 添加了自动聚焦功能
+
+## 性能优化
+对平台进行了多项性能改进。
+- 将 FontAwesome 移至 CDN
+- 改进了搜索对话框加载
+- 优化了静态属性加载
+- 为服务器端目录渲染添加了 polyfill DOM 解析器
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-02-22.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-02-22.mdx
new file mode 100644
index 000000000..238a8449f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-02-22.mdx
@@ -0,0 +1,38 @@
+---
+tags: ["api-reference", "configuration", "customization", "docs.yml"]
+---
+
+## API 操作台中的 WebSocket 支持
+在 API 操作台中添加了实时 WebSocket 测试功能,使开发者能够直接在文档中测试流式和实时端点。现在可以建立、测试和调试 WebSocket 连接,无需离开文档。
+
+## 增强的代码高亮
+使用 Shiki 实现了新的代码高亮系统,提高了语法高亮准确性和性能。该系统现在支持更多语言,并提供更好的深色模式兼容性。
+
+## 反馈系统
+引入了使用 Radix UI 组件的新反馈收集系统,以提高无障碍性。用户现在可以直接在界面中提供有关文档质量和实用性的结构化反馈。
+
+## 布局配置系统
+实现了灵活的布局配置系统,允许自定义页眉、页脚和侧边栏布置。现在可以自定义文档以匹配您的品牌和偏好。
+
+```yaml
+layout:
+ page-width: full
+ tabs-placement: header
+ searchbar-placement: header
+```
+
+## 自定义样式支持
+添加了对自定义 CSS 和脚本的支持,实现文档外观和行为的深度自定义。组织现在可以在其文档中一致地应用其品牌。
+
+```yaml docs.yml
+ css: ./assets/styles.css
+```
+
+```css styles.css
+/* Custom styles */
+.custom-class {
+ background-color: #f0f0f0;
+}
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-03-24.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-03-24.mdx
new file mode 100644
index 000000000..21823ba7e
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-03-24.mdx
@@ -0,0 +1,14 @@
+---
+tags: ["components", "search", "performance"]
+---
+
+# 2024年3月
+
+## 虚拟化语法高亮
+实现了性能优化的代码渲染,能够高效处理大型代码块而不影响页面性能。长代码示例现在可以立即加载并流畅滚动。
+
+## 移动搜索体验
+重新设计了移动搜索界面,采用了粘性搜索栏和改进的结果显示。用户现在可以在移动设备上轻松搜索文档,体验类似原生的界面。
+
+## 滚动条优化
+增强了所有文档部分的滚动条设计和行为,提供更加精致的外观和感觉。滚动条现在适应浅色和深色主题,同时保持可用性。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-04-20.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-04-20.mdx
new file mode 100644
index 000000000..28414471f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-04-20.mdx
@@ -0,0 +1,17 @@
+---
+tags: ["navigation", "configuration", "docs.yml"]
+---
+
+## 侧边栏导航增强
+通过优化间距和排版,改进了侧边栏填充和视觉层次。文档导航现在提供更清晰的视觉结构和更好的可读性。
+
+## 基础路径配置
+为文档路由添加了灵活的基础路径配置。组织现在可以在自定义路径下托管文档,同时保持正确的导航。
+
+```yaml docs.yml
+instances:
+ - url: your-site.docs.buildwithfern.com
+ custom-domain: your-site.com/docs
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-05-22.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-05-22.mdx
new file mode 100644
index 000000000..8f0acd18f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-05-22.mdx
@@ -0,0 +1,22 @@
+---
+tags: ["configuration", "api-reference", "docs.yml"]
+---
+
+## 高级重定向
+实现了支持模式匹配和参数保留的强大重定向系统。团队现在可以管理文档 URL 结构,同时保持向后兼容性。
+
+```yaml
+redirects:
+ - source: /v1/api/*
+ destination: /v2/api/:splat
+ permanent: true
+ - source: /guides/:name
+ destination: /tutorials/:name
+```
+
+
+
+## API 授权处理
+增强了文档平台中的 API 授权处理。开发者现在可以通过改进的令牌管理更轻松地测试经过身份验证的端点。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-06-25.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-06-25.mdx
new file mode 100644
index 000000000..d6b31957f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-06-25.mdx
@@ -0,0 +1,59 @@
+---
+tags: ["seo", "writing-content", "components"]
+---
+
+# 2024年6月
+
+## RSS 订阅集成
+新增了RSS订阅支持,让用户及时了解文档更改。团队现在可以为其文档提供自动化通知。
+
+## JSON-LD 增强
+通过JSON-LD实现了结构化数据支持,改善SEO效果。文档页面现在可以向搜索引擎和社交平台提供更丰富的信息。
+
+```json
+{
+ "@context": "https://schema.org",
+ "@type": "TechArticle",
+ "headline": "API Authentication Guide",
+ "datePublished": "2024-06-15",
+ "technicalAudience": "Software Developers"
+}
+```
+
+## 图片缩放控制
+新增了可配置的图片缩放功能,支持自定义触发器和行为。用户现在可以更好地检查文档中的图表和技术插图。
+
+```mdx page.mdx
+---
+no-image-zoom: true
+---
+```
+
+
+
+## 语法扩展支持
+新增对BAML和Jinja等编程语言的语法高亮支持。文档现在可以正确显示更广泛的代码示例。
+
+```html
+
+ Available Products
+ {% if products %}
+
+ {% else %}
+ No products are available at the moment.
+ {% endif %}
+
+```
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-07-30.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-07-30.mdx
new file mode 100644
index 000000000..79225adaf
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-07-30.mdx
@@ -0,0 +1,17 @@
+---
+tags: ["seo"]
+---
+
+# 2024年7月
+
+## Meta图片系统
+实现了全面的meta图片支持,改善社交分享效果。文档页面在社交媒体平台上分享时现在可以正确显示。
+
+```yaml
+og:image: /assets/og-image.png
+og:type: documentation
+twitter:card: summary_large_image
+twitter:image: /assets/twitter-card.png
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-08-20.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-08-20.mdx
new file mode 100644
index 000000000..10f9cd539
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-08-20.mdx
@@ -0,0 +1,19 @@
+---
+tags: ["accessibility", "api-reference"]
+---
+
+# 2024年8月
+
+## 锚链接系统
+重新设计了锚链接处理机制,改善了文档页面内的导航体验。链接现在会考虑固定标题并在打开时保持正确的滚动位置。
+
+## WCAG对比度改进
+增强了整个文档平台的颜色对比度,提供更好的可访问性。所有文本和交互元素现在默认满足WCAG AA标准,并对不符合WCAG AA标准的元素显示警告。
+
+## API页面中心更新
+改进了API文档页面的中心元素定位和更新机制。内容现在流畅性更好,在导航期间保持位置稳定。
+
+## 流式切换增强
+改进了API playground中流式响应切换的可见性和行为。用户现在可以更好地控制和监控流式响应。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-09-24.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-09-24.mdx
new file mode 100644
index 000000000..9b0a8e1b0
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-09-24.mdx
@@ -0,0 +1,18 @@
+---
+tags: ["api-reference"]
+---
+
+# 2024年9月
+
+## 环境测试界面
+创建了可编辑的playground环境系统,用于测试API端点。用户现在可以在文档内无缝切换不同的API环境。
+
+```yaml openapi.yml
+servers:
+ - url: https://api.example.com
+ x-fern-server-name: Production
+ - url: https://sandbox.example.com
+ x-fern-server-name: Sandbox
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-10-31.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-10-31.mdx
new file mode 100644
index 000000000..c2c5f9ef8
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-10-31.mdx
@@ -0,0 +1,17 @@
+---
+tags: ["api-reference"]
+---
+
+## JWT API密钥集成
+在文档playground中实现了从JWT令牌自动提取API密钥的功能。用户现在可以通过自动凭据处理更轻松地测试认证端点。
+
+
+
+## 查询参数增强
+改进了文档中间件对查询参数的处理。复杂的查询参数现在可以正确处理并在文档中显示。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-11-27.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-11-27.mdx
new file mode 100644
index 000000000..12520b556
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-11-27.mdx
@@ -0,0 +1,34 @@
+---
+tags: ["api-reference", "components"]
+---
+
+## API Explorer中的凭据自动填充
+
+让开发者免去查找和复制API密钥的麻烦。当用户通过认证后,他们的API凭据将自动填入API Playground。这样,他们可以更快地进行第一次API调用。
+
+
+
+在[Webflow的API Explorer](https://developers.webflow.com/data/reference/sites/list?playground=/data/reference/sites/list)中查看实时效果。
+
+
+
+## 卡片组件系统
+增强了文档卡片组件,改善视觉组织效果。信息现在可以以更结构化和吸引人的方式呈现。
+
+```typescript
+interface CardProps {
+ title: string;
+ description: string;
+ icon?: IconName;
+ variant?: 'default' | 'bordered' | 'filled';
+ actions?: CardAction[];
+}
+
+interface CardAction {
+ label: string;
+ href?: string;
+ onClick?: () => void;
+}
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2024-12-30.mdx b/fern/translations/zh/products/docs/pages/changelog/2024-12-30.mdx
new file mode 100644
index 000000000..36405119d
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2024-12-30.mdx
@@ -0,0 +1,25 @@
+---
+tags: ["api-reference"]
+---
+
+## API Explorer 中的音频流功能
+在 API Explorer 中添加了直接播放音频流的支持。此功能使您能够在不离开文档的情况下测试音频端点。
+
+在 ElevenLabs 的 [API Explorer](https://elevenlabs.io/docs/api-reference/text-to-speech/convert?playground=/docs/api-reference/text-to-speech/convert-as-stream) 中实时查看,让用户测试文本转语音端点并即时听到结果。
+
+
+
+## 表单数据优化
+增强了边缘函数中 URL 参数和表单数据的处理。文档 playground 现在更高效地处理复杂数据结构。
+
+```typescript
+const formConfig = {
+ encoding: 'application/x-www-form-urlencoded',
+ arrayFormat: 'brackets',
+ allowNullables: true,
+ sanitize: true,
+ maxDepth: 5
+}
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-01-14.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-01-14.mdx
new file mode 100644
index 000000000..c67f68d80
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-01-14.mdx
@@ -0,0 +1,37 @@
+---
+tags: ["ai"]
+---
+
+## 支持 /llms.txt
+
+API 文档应该也面向 LLM 和 Agent,而不仅仅是人类!
+
+我们很高兴宣布兼容 `/llms.txt` [新兴标准](https://llmstxt.org/),使您的文档对 AI 开发者工具(如 Cursor、Github Copilot、ChatGPT、Perplexity 和 Anthropic 的 Claude)具有可访问性和优化性。
+
+`/llms.txt` 和 `/llms-full.txt` 都设计为令牌高效,确保更快的处理速度和经济高效的 LLM 交互,同时不会牺牲有价值的信息。
+
+如果您使用 Fern Docs,此功能会像 /robots.txt 和 /sitemap.xml 一样自动启用。
+
+
+
+
+
+查看 ElevenLabs:
+
+
+
+ *加载时间 < 1 秒*
+
+
+
+ *加载时间 5+ 秒*
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-01-21.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-01-21.mdx
new file mode 100644
index 000000000..71cfa29ce
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-01-21.mdx
@@ -0,0 +1,29 @@
+---
+tags: ["components", "writing-content"]
+---
+
+## Accordion 组件的改进
+
+Accordion 组件已升级,现在您可以使用浏览器内的 `cmd+f` 搜索来查找原本隐藏的文本。
+
+- 为所有使用 `` 组件的客户改善了可访问性
+- 改善了内容的 SEO 索引(现在更多 HTML 在服务器端生成,而不是客户端)
+
+在此页面尝试搜索 **burst**:https://dev.hume.ai/docs/expression-measurement/faq
+
+
+
+
+## 支持嵌入本地资源
+
+我们添加了在文档中嵌入本地资源的支持。这对于在文档中显示 PDF、图像、视频和其他资源很有用。
+
+要嵌入资源,您可以使用 `embed` 标签。
+
+```mdx
+
+
+
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-02-04.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-02-04.mdx
new file mode 100644
index 000000000..b6a530517
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-02-04.mdx
@@ -0,0 +1,91 @@
+---
+tags: ["components"]
+---
+
+## 引入全局语言同步:跟随您的代码语言偏好
+
+从今天开始,当您在任何 `` 或 `` 中选择编程语言时,该偏好将自动在所有文档页面间同步。这意味着您在浏览文档的不同部分时,无需再手动切换语言。无论您是在查看实现示例、调试指南还是 API 参考,您的首选语言都会跟随您。语言偏好保存在客户端本地存储中。
+
+此行为对所有 `` 自动启用。要为 `` 添加语言偏好,您可以添加 `language` 属性。在下面的示例中查看语言同步效果:
+
+
+
+
+
+这是 TypeScript 专用内容。
+
+
+这是 Python 专用内容。
+
+
+这是 Java 专用内容。
+
+
+
+
+```typescript
+console.log("Hello, world!");
+```
+```python
+print("Hello, world!")
+```
+```java
+System.out.println("Hello, world!");
+```
+
+
+
+```typescript
+console.log("This content is synced!");
+```
+```python
+print("This content is synced!");
+```
+```java
+System.out.println("This content is synced!");
+```
+
+
+
+
+````md
+
+
+This is content specific to TypeScript.
+
+
+This is content specific to Python.
+
+
+This is content specific to Java.
+
+
+
+
+```typescript
+console.log("Hello, world!");
+```
+```python
+print("Hello, world!")
+```
+```java
+System.out.println("Hello, world!");
+```
+
+
+
+```typescript
+console.log("This content is synced!");
+```
+```python
+print("This content is synced!");
+```
+```java
+System.out.println("This content is synced!");
+```
+
+````
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-04-27.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-04-27.mdx
new file mode 100644
index 000000000..c317a6b0d
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-04-27.mdx
@@ -0,0 +1,6 @@
+---
+tags: ["api-reference", "local-development", "bug-fix"]
+---
+
+- **`(fix):`** openrpc playground 参数现在是数组
+- **`(chore):`** beta 本地开发包大小减少了 75%,现在允许任何机型的用户在本地运行。此外,现在排除了自定义 JavaScript 以解决错误报告。
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-04-28.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-04-28.mdx
new file mode 100644
index 000000000..bbfd324aa
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-04-28.mdx
@@ -0,0 +1,5 @@
+---
+tags: ["local-development"]
+---
+
+- **`(chore):`** beta 本地开发模式现在会在文件更改时刷新
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-04-29.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-04-29.mdx
new file mode 100644
index 000000000..5b235c75e
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-04-29.mdx
@@ -0,0 +1,8 @@
+---
+tags: ["seo", "configuration", "search", "bug-fix", "docs.yml"]
+---
+
+- **`(fix):`** 现在遵守在 `docs.yml` 配置中定义的 `og` 和 `twitter`
+- **`(fix):`** 已恢复经过身份验证的预览
+- **`(fix):`** frontmatter 标题现在优先于 MDX 文件中的 `` 标签
+- **`(fix):`** 规范 URL 现在区分共享相同方法和端点名称但定义在不同 API 中的端点
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-05-02.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-05-02.mdx
new file mode 100644
index 000000000..86a0ad5ba
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-05-02.mdx
@@ -0,0 +1,7 @@
+---
+tags: ["local-development", "search", "ai", "bug-fix"]
+---
+
+- **`(feat):`** 在最新 CLI 上使用 `fern docs dev` 现在能更好地反映生产环境中的文档
+- **`(feat):`** 搜索 UX 现在使用无限滚动,并允许基于面包屑路径进行搜索
+- **`(fix):`** AI 聊天体验的小错误修复
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-05-13.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-05-13.mdx
new file mode 100644
index 000000000..4d5d62ec4
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-05-13.mdx
@@ -0,0 +1,5 @@
+---
+tags: ["api-reference"]
+---
+
+- **`(feat):`** 允许在 playground 中选择响应和请求
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-05-20.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-05-20.mdx
new file mode 100644
index 000000000..84045cd90
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-05-20.mdx
@@ -0,0 +1,6 @@
+---
+tags: ["local-development", "ai", "bug-fix"]
+---
+
+- **`(feat):`** 对本地预览模式的改进,包括对自定义 JavaScript 的支持和重新加载性能问题的错误修复。
+- 对 Ask Fern 的小错误修复和改进
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-05-22.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-05-22.mdx
new file mode 100644
index 000000000..6186258d0
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-05-22.mdx
@@ -0,0 +1,10 @@
+---
+tags: ["customization"]
+---
+
+## 404 页面的改进
+我们现在为您的文档提供主题化的 404 页面,使用您的主题颜色、字体和按钮。我们还使用 404 页面 URL 在此页面上尽力维护导航状态,以便用户能够轻松导航回您的文档。
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-05-23.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-05-23.mdx
new file mode 100644
index 000000000..1a2dd92ee
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-05-23.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["configuration"]
+---
+
+## 目录自定义
+
+我们添加了 `max-toc-depth` frontmatter 选项来控制目录的深度。使用此选项来限制目录中包含的标题级别。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-06-05.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-06-05.mdx
new file mode 100644
index 000000000..b2f483c27
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-06-05.mdx
@@ -0,0 +1,19 @@
+---
+tags: ["navigation"]
+---
+
+## 推出产品切换器
+
+按产品组织您的文档,让开发者能快速找到所需内容。非常适合拥有多个 API 的公司,每个 API 都有自己的参考文档、指南、版本和变更日志。
+
+功能特性:
+
+- **搜索优化** 具有 SEO 友好的结构。
+- **关键词搜索和 Ask Fern** 可在产品内和跨产品工作。
+- **可定制** 支持版本和独特图标来体现您的品牌标识。
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-10-17.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-10-17.mdx
new file mode 100644
index 000000000..e9f213e1f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-10-17.mdx
@@ -0,0 +1,43 @@
+---
+tags: ["api-reference", "components", "docs.yml"]
+---
+
+## HTTP 代码片段现在默认启用
+
+HTTP 代码片段现在默认为所有文档站点启用,使开发者更容易在您的 API 参考中直接查看 cURL、Python、Ruby 和其他 HTTP 客户端示例。以前,此功能需要内部配置才能激活。
+
+您现在可以直接在 `docs.yml` 文件中控制 HTTP 代码片段:
+
+```yaml title="docs.yml"
+# 关闭 HTTP 代码片段
+settings:
+ http-snippets: false
+
+# 或仅指定特定语言
+settings:
+ http-snippets:
+ - python
+ - ruby
+```
+
+
+
+## 引入可运行端点
+
+使用我们全新的交互式组件,直接在您的文档中测试 API 端点。可运行端点允许您的用户在不离开文档的情况下向您的 API 发送真实的 HTTP 请求,使开发者更容易探索和理解您的 API。
+
+
+
+
+
+在您的 MDX 文档中的任何位置嵌入该组件,创建一个交互式请求构建器,为标头、路径参数、查询参数和请求体提供表单输入。用户可以执行请求并查看实时响应,包括状态码和语法高亮。
+
+主要功能包括:
+
+- **交互式表单构建器**,根据您的端点定义自动生成输入
+- **多示例支持**,当您有多个预配置场景时提供下拉选择器
+- **环境选择器**,用于在生产、预发布或开发环境中进行测试
+- **表单持久化**,在本地存储中保存用户输入,跨会话保持
+- **直接导航**,通过"在 API 参考中打开"按钮跳转到完整的 API 参考
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-02.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-02.mdx
new file mode 100644
index 000000000..9b27e7bae
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-02.mdx
@@ -0,0 +1,37 @@
+---
+tags: ["navigation", "api-reference", "configuration", "docs.yml"]
+---
+
+## 导航栏下拉菜单
+
+在导航栏中使用新的下拉菜单来分组相关链接。将资源、工具或外部链接组织在单个按钮下,保持页头简洁。
+
+```yaml title="docs.yml"
+navbar-links:
+ - type: dropdown
+ text: Resources # dropdown button text
+ icon: fa-solid fa-seedling # optional icon
+ links:
+ - text: Plant database # link display text
+ href: https://example.com/plants # destination URL
+ icon: fa-regular fa-leaf # optional icon
+ - text: Growing guides
+ href: https://example.com/guides
+```
+
+
+
+## API Explorer 直接请求
+
+现在您可以直接向您的 API 发送 API Explorer 请求,而不是通过 Fern 的代理。这对于测试跨域资源共享(CORS)配置和调试身份验证流程很有用。
+
+```yaml title="docs.yml"
+settings:
+ disable-explorer-proxy: true
+```
+
+
+您的 API 必须启用 CORS 以允许来自文档域的请求。
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-03.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-03.mdx
new file mode 100644
index 000000000..f20029f4d
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-03.mdx
@@ -0,0 +1,80 @@
+---
+tags: ["navigation", "customization", "configuration", "docs.yml"]
+---
+
+## 标签页变体
+
+使用新的变体功能在单个标签页中创建多种内容变体。这样您可以为同一主题展示不同的视角、用户类型或实现方法,而无需创建单独的标签页。
+
+您现在可以为标签页定义具有不同布局、标题、副标题和图标的变体。每个变体可以有自己的导航结构,您还可以明确设置哪个变体应该是默认的。
+
+```yaml title="docs.yml"
+navigation:
+ - tab: guides
+ variants:
+ - title: For developers
+ layout:
+ - section: Getting started
+ contents:
+ - page: Quick start
+ path: ./pages/dev-quickstart.mdx
+ - title: For product managers
+ default: true
+ layout:
+ - section: Getting started
+ contents:
+ - page: Overview
+ path: ./pages/pm-overview.mdx
+```
+
+
+
+## 在导航中使用自定义图标
+
+您可以在整个 `docs.yml` 导航配置中使用自己的图片文件作为图标,包括[导航栏链接](/learn/docs/configuration/site-level-settings#navbar-links-configuration)、[章节、页面](/learn/docs/configuration/navigation#sidebar-icons)和[产品](/learn/docs/configuration/products#add-your-product-configuration)图标。
+
+图标支持三种格式:
+- **Font Awesome 图标**:使用像 `fa-solid fa-seedling` 或 `fa-regular fa-leaf` 这样的图标名称。支持 Font Awesome 的 Pro 和 Brand 图标。
+- **自定义图片文件**:使用自定义图片文件的相对路径(例如,`./assets/icons/plant-icon.svg`)。路径相对于引用图标的 YAML 文件(例如,`docs.yml`)。
+- **内联 SVG**:提供用引号包装的 SVG 字符串。
+
+```yaml Sidebar icons in docs.yml
+navigation:
+ - section: Home
+ icon: fa-regular fa-home # Font Awesome icon
+ contents:
+ - page: Introduction
+ icon: ./assets/icons/intro-icon.svg # Custom image file
+ path: ./pages/intro.mdx
+ - page: Custom Features
+ icon: "" # Inline SVG
+ path: ./pages/custom.mdx
+ - api: API Reference
+ icon: fa-regular fa-puzzle
+```
+
+
+
+## 外部产品链接
+
+您现在可以配置产品链接到外部 URL(独立应用程序、第三方文档或其他外部资源),而不是站点内的文档。
+
+外部产品会与内部产品一起出现在产品切换器中,但在被选中时会将用户导航到指定的 URL。与内部产品不同,外部产品直接在 `docs.yml` 中使用 `href` 定义,不需要独立的产品 `.yml` 文件。
+
+要定义外部产品,在 `docs.yml` 的 `products` 列表中添加一个带有 `href` 而不是 `path` 的项目:
+
+```yaml title="docs.yml"
+products:
+ - display-name: API Documentation
+ path: ./products/api-docs.yml
+ icon: fa-solid fa-book
+ slug: api-docs
+ subtitle: Complete API reference
+
+ - display-name: Dashboard # External product
+ href: https://dashboard.example.com
+ icon: fa-solid fa-chart-line
+ subtitle: Analytics and insights
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-05.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-05.mdx
new file mode 100644
index 000000000..19504de62
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-05.mdx
@@ -0,0 +1,39 @@
+---
+tags: ["ai", "navigation", "configuration", "docs.yml"]
+---
+
+## AI 代理的 HTTP API 访问
+
+AI 代理现在可以通过 HTTP API 直接访问受认证保护的文档。这使得自定义集成和 AI 工具能够以编程方式检索受保护的内容。
+
+代理通过 `/api/fern-docs/get-jwt` 端点使用 Fern API 密钥获取 JWT,然后使用它来访问受保护的文档:
+
+```bash
+curl https://docs.example.com/platform/overview \
+ -H 'Accept: text/plain' \
+ -H 'x-fern-host: docs.example.com' \
+ -H 'FERN_TOKEN: your-jwt-here'
+```
+
+内容以干净的 Markdown 格式提供,以实现高效的 token 处理。
+
+## 基于文件夹的导航
+
+使用新的 `folder` 配置从 markdown 文件文件夹自动生成导航。无需在 `docs.yml` 中手动列出每个页面,只需指向一个文件夹。Fern 会发现所有 `.md` 和 `.mdx` 文件并将它们添加到导航中。
+
+```yaml docs.yml {6-10}
+navigation:
+ - section: Getting started
+ contents:
+ - page: Introduction
+ path: ./pages/intro.mdx
+ - folder: ./pages/guides
+ title: Guides # Display name for folder section
+ icon: fa-regular fa-book
+ collapsed: true
+ availability: beta # Optional badge to display in navigation
+```
+
+子文件夹会成为嵌套部分。支持的选项:`title`、`slug`、`icon`、`collapsed`、`hidden`、`skip-slug`、`availability`。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-08.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-08.mdx
new file mode 100644
index 000000000..86c85cf51
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-08.mdx
@@ -0,0 +1,38 @@
+---
+tags: ["writing-content", "components"]
+---
+
+## 参数化 markdown 片段
+
+可重用的 Markdown 片段支持任意参数,这些参数可以在片段中用作变量。这使得灵活、可重用的内容模板成为可能。
+
+使用大括号创建带有参数占位符的片段:
+
+```mdx fern/snippets/watering-schedule.mdx
+Remember to water your {plant} every {interval} days.
+```
+
+在引用片段时传递参数:
+
+```mdx page.mdx
+
+```
+
+这将渲染为:
+
+
+
+
+
+## 新的 Copy 组件用于内联可复制文本
+
+`` 组件让文本可以一键复制。在内联使用它可以让读者快速复制版本号、命令、API 密钥或其他文本片段,无需手动选择和复制。
+
+您还可以使用 `clipboard` 属性自定义复制到剪贴板的内容。这在您希望简化命令、版本或 URL 以提高可读性的同时复制完整值时很有用。
+
+```jsx Markdown
+Use the Fern CLI to build and consume REST APIs. The latest version is
+v2.0.
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-09.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-09.mdx
new file mode 100644
index 000000000..c61c4e26c
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-09.mdx
@@ -0,0 +1,45 @@
+---
+tags: ["components"]
+---
+
+## 用于显示文件树结构的 Files 组件
+
+全新的 `` 组件可以创建可视化的文件树结构,支持可展开的文件夹和嵌套文件。使用它来展示项目结构、目录布局或文档中的任何分层文件组织。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+该组件包含三个部分:`` 作为容器,`` 用于可展开或折叠的目录,`` 用于单个文件。文件夹和文件支持可选的 `href` 属性以使其成为可点击链接,文件夹可以使用 `defaultOpen` 在页面加载时默认展开。
+
+```jsx Markdown maxLines=10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-11.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-11.mdx
new file mode 100644
index 000000000..a1447c0bd
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-11.mdx
@@ -0,0 +1,31 @@
+---
+tags: ["api-reference"]
+---
+
+## API Explorer 中的多重身份验证方案
+
+API Explorer 现在支持 OpenAPI 规范的多重身份验证方案和身份验证方案组合。
+
+首先,在您的 OpenAPI 规范中配置多个安全选项:
+
+```yaml openapi.yml {8-11}
+/plant/search/status:
+ get:
+ tags:
+ - plant
+ summary: Search plants by status
+ description: Filter plants based on their current status.
+ operationId: searchPlantsByStatus
+ security:
+ - bearerAuth: [] # Option 1: Bearer token only (OR)
+ - basicAuth: [] # Option 2: Basic auth AND API key (combined)
+ apiKey: []
+```
+
+然后,API Explorer 会自动在下拉菜单中显示所有可用的身份验证选项,允许用户在发送请求前选择和配置他们首选的身份验证方法。
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-14.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-14.mdx
new file mode 100644
index 000000000..f0112cd41
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-14.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["navigation", "configuration", "docs.yml"]
+---
+
+## 链接目标属性
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-18.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-18.mdx
new file mode 100644
index 000000000..c546f56d3
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-18.mdx
@@ -0,0 +1,27 @@
+---
+tags: ["ai", "writing-content"]
+---
+
+## LLM 内容可见性标签
+
+全新的 `` 和 `` 标签让您可以为 AI 助手提供额外的上下文,同时保持文档站点(面向人类读者)简洁且聚焦。
+
+使用 `` 仅向通过 LLM 端点(如 `/llms.txt`)访问的 AI 助手显示内容,同时在文档站点中隐藏:
+
+```jsx docs/getting-started.mdx
+
+ This technical context is only visible to AI assistants via LLM endpoints.
+
+```
+
+使用 `` 仅在文档站点显示内容,同时将其排除在 LLM 端点之外:
+
+```jsx docs/getting-started.mdx
+
+
+ This callout appears on your documentation site but not in LLM endpoints.
+
+
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-24.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-24.mdx
new file mode 100644
index 000000000..f7c613203
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-24.mdx
@@ -0,0 +1,37 @@
+---
+tags: ["customization", "configuration", "docs.yml"]
+---
+
+## 产品和版本特定的公告横幅
+
+公告横幅现在可以在多个层级配置,以针对特定的产品或版本。
+
+覆盖层次结构如下:
+
+1. **版本级** - 最高优先级,为特定版本定义时始终显示
+2. **产品级** - 当产品没有版本级公告时使用
+3. **配置级** - 当没有定义特定覆盖时在所有产品/版本中显示的后备公告
+
+在您的 `docs.yml` 文件中,直接将 `announcement` 属性添加到 `products:` 或 `versions:` 列表中的项目:
+
+```yaml docs.yml
+# 配置级公告(后备)
+announcement:
+ message: "欢迎来到我们的文档!"
+
+products:
+ - display-name: Docs
+ path: ./products/docs/docs.yml
+ # 产品级公告
+ announcement:
+ message: "Docs 产品处于测试版。"
+
+ versions:
+ - display-name: v1
+ path: ./products/docs/v1/docs.yml
+ # 版本级公告(最高优先级)
+ announcement:
+ message: "v1 处于维护模式。请升级到 v2。"
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-11-25.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-11-25.mdx
new file mode 100644
index 000000000..cb1ea33e7
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-11-25.mdx
@@ -0,0 +1,15 @@
+---
+tags: ["api-reference", "configuration", "docs.yml"]
+---
+
+## API 参考文档的标签描述页面
+
+您现在可以使用 OpenAPI 标签描述作为 API 参考文档部分的摘要页面。当您在 API 参考文档配置中设置 `tag-description-pages: true` 时,Fern 会自动为每个标签创建一个摘要页面,使用您 OpenAPI 规范中的描述。
+
+```yaml docs.yml
+navigation:
+ - api: API Reference
+ tag-description-pages: true
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-03.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-03.mdx
new file mode 100644
index 000000000..1cd4cfdd2
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-03.mdx
@@ -0,0 +1,31 @@
+---
+tags: ["security"]
+---
+
+## 安全更新:React Server Components 漏洞已修补
+
+我们已更新平台以解决 React Server Components 中的一个严重安全漏洞(CVE-2025-66478)。该漏洞评级为 CVSS 10.0,可能允许在未修补的环境中处理攻击者控制的请求时执行远程代码。
+
+该漏洞源于上游 React 实现(CVE-2025-55182),影响使用 App Router 和 React Server Components 的 Next.js 应用程序。
+
+### 我们采取的措施
+
+我们将平台依赖项升级到修补版本:
+
+- **Next.js**:从 15.5.4 升级到 15.5.7
+- **React**:从 19.0.0 升级到 19.0.1
+- **React-DOM**:从 19.0.0 升级到 19.0.1
+
+这些版本包含解决漏洞的强化 React Server Components 实现。
+
+### 对 Fern 用户的影响
+
+Fern Docs 用户无需采取任何行动。安全补丁已自动应用于所有 Fern 托管的文档站点。
+
+对于自托管部署,我们建议更新到最新的 Fern 平台版本以确保您拥有安全修复。
+
+### 参考资料
+
+- [Next.js Security Advisory: CVE-2025-66478](https://nextjs.org/blog/CVE-2025-66478)
+- [Next.js 15.5.7 Release](https://github.com/vercel/next.js/releases/tag/v15.5.7)
+- [React 19.0.1 Release](https://github.com/facebook/react/releases/tag/v19.0.1)
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-09.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-09.mdx
new file mode 100644
index 000000000..f8afdfe67
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-09.mdx
@@ -0,0 +1,41 @@
+---
+tags: ["configuration", "api-reference", "components"]
+---
+
+## 最后更新时间前置属性
+
+您现在可以使用新的 `last-updated` 前置属性在页面页脚显示"最后更新"消息。这有助于读者了解内容的最后修改时间。
+
+```mdx
+---
+title: API Reference
+last-updated: December 9, 2025
+---
+```
+
+日期在页面反馈下方以小文本原样显示,因此您可以使用任何您偏好的日期格式。
+
+
+
+
+## API 参考文档描述的页脚组件
+
+您现在可以在 API 端点描述中使用 `` 组件,添加在响应部分下方页面底部渲染的内容。这对于相关链接、附加上下文或在端点文档末尾更有意义的注释很有用。
+
+```yaml api/openapi.yml
+paths:
+ /plants:
+ get:
+ summary: List all plants
+ description: |
+ Get a list of all plants in the system.
+
+
+ ## Related endpoints
+
+ - [Create a plant](/api-reference/plants/create)
+ - [Update a plant](/api-reference/plants/update)
+
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-10.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-10.mdx
new file mode 100644
index 000000000..cb2848407
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-10.mdx
@@ -0,0 +1,19 @@
+---
+tags: ["components", "api-reference"]
+---
+
+## 模式代码片段组件
+
+新的 `` 组件将您 API 参考文档中的类型定义显示为 JSON 代码块。将其与 `` 组件一起使用,可以同时显示数据模型的 JSON 表示和详细字段分解。
+
+
+
+```jsx Markdown
+
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-11.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-11.mdx
new file mode 100644
index 000000000..b83fd0a1d
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-11.mdx
@@ -0,0 +1,29 @@
+---
+tags: ["customization", "configuration", "docs.yml"]
+---
+
+## 徽标右侧文本属性
+
+您现在可以使用新的 `right-text` 属性在徽标配置中在徽标图片右侧显示自定义文本。这对于在徽标旁边添加"Docs"或"API"等标签很有用。
+
+```yaml docs.yml
+logo:
+ dark: assets/images/logo-dark.svg
+ light: assets/images/logo-light.svg
+ right-text: Docs
+```
+
+
+
+## 画布主体主题
+
+新的 `canvas` 主体主题选项将您的主要内容区域包裹在类似卡片的容器中,具有圆角和细微边框。这创造了一种更加集中、专注的阅读体验,在视觉上将您的文档内容与侧边栏和标题分离。
+
+```yaml docs.yml
+theme:
+ body: canvas
+```
+
+画布主题适用于所有页面布局,包括指南、概览和 API 参考文档页面。它使用您配置的 `card-background` 颜色和 `border` 颜色,与您站点的配色方案保持一致的样式。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-14.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-14.mdx
new file mode 100644
index 000000000..fec41d0ce
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-14.mdx
@@ -0,0 +1,11 @@
+---
+tags: ["ai", "api-reference"]
+---
+
+## AI 增强的示例
+
+Fern 使用 AI 自动为您的 API 参考文档生成真实的请求和响应示例。示例中不再是 `"string"` 和 `1.1` 这样的占位符值,而是基于您的 OpenAPI 规范端点属性和描述生成的可信数据。
+
+这些示例与您的规范保持同步 - 当您更改或添加字段时,生成的示例会自动更新。您可以自定义生成示例的样式,直接编辑它们,或者完全禁用此功能。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-15.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-15.mdx
new file mode 100644
index 000000000..e6fd3e033
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-15.mdx
@@ -0,0 +1,22 @@
+---
+tags: ["customization", "configuration", "docs.yml"]
+---
+
+## 自定义页面操作
+
+定义具有自定义标题、图标和 URL 的页面操作按钮。自定义操作与复制页面和以 Markdown 查看等内置页面操作一起显示,并且可以链接到外部工具、编辑器或任何 URL。
+
+```yaml docs.yml
+page-actions:
+ options:
+ custom:
+ - title: 在 Windsurf 中打开
+ subtitle: 使用 AI 辅助编辑
+ url: "windsurf://open?url={url}"
+ icon: fa-solid fa-wind
+ default: true
+```
+
+自定义操作支持 `{slug}`、`{domain}` 和 `{url}` 等 URL 占位符,可以动态地将页面信息插入到链接中。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-16.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-16.mdx
new file mode 100644
index 000000000..43431a18a
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-16.mdx
@@ -0,0 +1,11 @@
+---
+tags: ["customization"]
+---
+
+## 嵌入模式
+
+您现在可以通过在任何 URL 中添加 `?embedded=true` 来隐藏文档页面的头部和尾部。这使得在 iframe、仪表板或其他只想显示内容的上下文中嵌入您的文档变得很容易。
+
+一旦启用,嵌入模式会在同一会话的导航事件中保持启用状态。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2025-12-20.mdx b/fern/translations/zh/products/docs/pages/changelog/2025-12-20.mdx
new file mode 100644
index 000000000..da82bf8e4
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2025-12-20.mdx
@@ -0,0 +1,20 @@
+---
+tags: ["components", "customization"]
+---
+
+## Card 和 Icon 组件中的自定义 SVG 图标
+
+Card 和 Icon 组件支持 SVG 文件的相对路径。使用像 `./images/icon.svg` 这样的相对路径来显示项目中的自定义 SVG 图标。路径相对于使用组件的页面。
+
+```jsx Markdown
+
+ 带有自定义 SVG 图标的卡片。
+
+
+ 自定义 SVG 图标
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-01-05.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-01-05.mdx
new file mode 100644
index 000000000..c891df281
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-01-05.mdx
@@ -0,0 +1,23 @@
+---
+tags: ["components", "api-reference", "docs.yml"]
+---
+
+## Runnable endpoint 组件的折叠状态
+
+`` 组件现在支持 `collapsed` 属性来控制初始显示状态。当设置为 `true` 时,表单部分将被隐藏,直到用户展开它。
+
+```jsx Markdown
+
+```
+
+这对于在页面上嵌入多个端点或减少视觉混乱同时保持交互式 API 测试功能很有用。
+
+
+
+## 默认启用动态 SDK 代码片段
+
+动态 SDK 代码片段现在默认启用。当您配置 SDK 代码片段时,用户可以修改参数并实时查看所有支持语言的代码示例更新。
+
+如果您更喜欢静态代码示例,可以在 `docs.yml` 中[禁用动态代码片段](/learn/docs/configuration/site-level-settings#experimentaldynamic-snippets)。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-01-09.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-01-09.mdx
new file mode 100644
index 000000000..20e955be9
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-01-09.mdx
@@ -0,0 +1,22 @@
+---
+tags: ["components"]
+---
+
+## Versions 组件
+
+新的 `` 组件根据版本选择显示不同的内容。用户可以使用下拉菜单在版本之间切换,所选版本会保存在 URL 查询参数中。
+
+```jsx Markdown
+
+
+ 版本 2.0 的内容。
+
+
+ 版本 1.0 的内容。
+
+
+```
+
+这对于显示特定版本的文档、安装说明或 API 示例非常有用,无需复制页面。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-01-15.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-01-15.mdx
new file mode 100644
index 000000000..609202543
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-01-15.mdx
@@ -0,0 +1,18 @@
+---
+tags: ["components", "api-reference"]
+---
+
+## EndpointRequestSnippet 的 languages 属性
+
+`` 组件现在支持 `languages` 属性来控制下拉菜单中显示哪些语言及其顺序。您还可以包含 `payload` 来显示原始 JSON 请求体或查询参数。
+
+```jsx Markdown
+
+```
+
+当未指定 `languages` 时,将显示所有可用语言,`payload` 显示在最后。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-01-17.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-01-17.mdx
new file mode 100644
index 000000000..23dbded5d
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-01-17.mdx
@@ -0,0 +1,25 @@
+---
+tags: ["components", "navigation"]
+---
+
+## If 组件的产品和版本属性
+
+`` 组件现在支持 `products` 和 `versions` 属性,允许您根据页面在导航结构中的位置有条件地显示内容。
+
+```jsx Markdown
+
+ 此内容仅在 api-reference 产品中显示
+
+
+
+ 此内容仅在 v2 或 v3 中显示
+
+
+
+ 所有条件必须匹配(AND 逻辑)
+
+```
+
+您还可以使用 `not` 属性来反转条件,当当前产品或版本不匹配时显示内容。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-01-22.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-01-22.mdx
new file mode 100644
index 000000000..b6c08e6ae
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-01-22.mdx
@@ -0,0 +1,14 @@
+---
+tags: ["components"]
+---
+
+## 在代码块中隐藏行号
+
+`` 组件现在支持 `showLineNumbers` 属性,允许您隐藏侧边栏中的行号。这对于短代码片段、命令示例或单函数演示很有用,在这些场景中行号会增加不必要的视觉干扰。
+
+```python showLineNumbers={false}
+def get_plant(plant_id):
+ return plants.get(plant_id)
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-01-30.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-01-30.mdx
new file mode 100644
index 000000000..14025c5c8
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-01-30.mdx
@@ -0,0 +1,63 @@
+---
+tags: ["components", "configuration", "docs.yml"]
+---
+
+## 可搜索表格
+
+`` 组件为大型表格提供客户端过滤功能。表格上方会出现一个搜索输入框,使用不区分大小写的子字符串匹配对行进行实时过滤。将任何 markdown 表格用 `` 包装即可添加搜索功能:
+
+```jsx Markdown
+
+| Plant | Light Requirements | Water |
+|-------|-------------------|-------|
+| Fern | Partial shade | Weekly |
+| Snake Plant | Low to bright indirect | Bi-weekly |
+
+```
+
+使用 `` 可以同时结合粘性表头和搜索功能:
+
+```jsx Markdown
+
+| Plant | Light Requirements | Water |
+|-------|-------------------|-------|
+| Fern | Partial shade | Weekly |
+| Snake Plant | Low to bright indirect | Bi-weekly |
+
+```
+
+或者,也可以为 HTML 表格添加 `searchable` 属性:
+
+```jsx Markdown
+
+```
+
+
+
+## 切换器位置配置
+
+使用 `docs.yml` 布局配置中的 `switcher-placement` 选项控制产品和版本切换器在文档站点中的显示位置。可选择 `header`(默认)在顶部导航栏中显示切换器,或选择 `sidebar` 将其放置在侧边栏导航中。
+
+```yaml docs.yml
+layout:
+ switcher-placement: sidebar
+```
+
+
+
+## 代码块中的智能续行
+
+Bash 和终端代码块现在能够智能地显示 `$` 表示新命令,`>` 表示使用 `\` 跨多行的命令续行。这使得在同一个代码块中更容易区分独立命令和多行命令。
+
+```bash
+fern init
+fern generate --group external \
+ --log-level debug \
+ --version 1.0.0
+fern check
+fern docs dev
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-03.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-03.mdx
new file mode 100644
index 000000000..352dcbf30
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-03.mdx
@@ -0,0 +1,43 @@
+---
+tags: ["components", "configuration", "navigation", "docs.yml"]
+---
+
+## EndpointRequestSnippet 中的试用按钮
+
+`` 组件现在包含一个试用按钮,允许用户访问端点浏览器并直接从代码片段测试 API 端点。
+
+
+
+## 前置元数据可用性
+
+使用 `availability` 字段直接在前置元数据中设置页面可用性。这会在页面上显示可用性标识,并覆盖导航(`docs.yml`)中定义的任何可用性设置。
+
+```mdx
+---
+title: 新功能
+availability: beta
+---
+```
+
+有效值为:`stable`、`generally-available`、`in-development`、`pre-release`、`deprecated` 或 `beta`。
+
+
+
+## 使用索引文件的文件夹节概述
+
+使用 `folder` 导航时,向任何文件夹添加 `index.mdx` 或 `index.md` 文件以自动将其用作节概述。索引文件用作概述页面并从节内容中排除。这适用于顶级文件夹和嵌套子目录。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-04.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-04.mdx
new file mode 100644
index 000000000..778bcbb74
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-04.mdx
@@ -0,0 +1,30 @@
+---
+tags: ["customization", "navigation", "configuration", "docs.yml"]
+---
+
+## 使用 @ 前缀的绝对导入
+
+使用 `@/` 前缀从您的 fern 文件夹根目录导入自定义组件的绝对路径。这对于嵌套的 MDX 文件特别有用,在这些文件中像 `../../../components/Banner` 这样的相对路径会很麻烦。
+
+```jsx
+import { CustomCard } from "@/components/CustomCard"
+```
+
+仍然支持相对导入。
+
+
+
+## 文件夹导航的标题源
+
+默认情况下,文件夹导航从文件名派生页面标题。您现在可以设置 `title-source: frontmatter` 来使用每个文件的前置元数据中的 `title` 字段。
+
+```yaml docs.yml
+navigation:
+ - folder: ./pages/guides
+ title: 指南
+ title-source: frontmatter
+```
+
+没有前置元数据 `title` 的文件会回退到从文件名派生的值。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-05.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-05.mdx
new file mode 100644
index 000000000..8d9a6ab94
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-05.mdx
@@ -0,0 +1,16 @@
+---
+tags: ["customization", "configuration", "docs.yml", "components"]
+---
+
+## 服务器端渲染的自定义头部和页脚
+
+使用 `docs.yml` 中新的 `header` 和 `footer` 属性用您自己的 React 组件替换 Fern 的默认头部或页脚。
+
+```yaml docs.yml
+header: ./components/CustomHeader.tsx
+footer: ./components/CustomFooter.tsx
+```
+
+组件是服务器端渲染的,具有更好的 SEO 和性能,在页面加载过程中没有布局偏移。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-06.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-06.mdx
new file mode 100644
index 000000000..e98cbd3b0
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-06.mdx
@@ -0,0 +1,25 @@
+---
+tags: ["ai", "search", "navigation", "configuration", "docs.yml"]
+---
+
+## Ask Fern 深度链接
+
+使用查询参数直接从 URL 打开 Ask Fern 或搜索对话框。添加 `?searchType=ai&query={prompt}` 以使用提示打开 Ask AI,或使用 `?query={search}` 进行常规搜索。搜索打开后,参数将从 URL 中移除。
+
+
+
+## 全局文件夹标题来源设置
+
+使用 `settings` 中的新选项 `folder-title-source` 为所有文件夹导航设置默认的 `title-source`。单个文件夹仍可使用自己的 `title-source` 覆盖此值。
+
+```yaml docs.yml
+settings:
+ folder-title-source: frontmatter
+
+navigation:
+ - folder: ./pages/guides # 使用 frontmatter(来自全局设置)
+ - folder: ./pages/reference
+ title-source: filename # 覆盖全局设置
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-09.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-09.mdx
new file mode 100644
index 000000000..02d0295ae
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-09.mdx
@@ -0,0 +1,15 @@
+---
+tags: ["api-reference", "configuration", "generators.yml"]
+---
+
+## GraphQL API 参考文档
+
+从 GraphQL schema 生成 API 参考文档。将您的 `.graphql` schema 文件添加到 `generators.yml`,Fern 将查询、变更、订阅和类型渲染为交互式参考文档。
+
+```yaml generators.yml
+api:
+ specs:
+ - graphql: schema.graphql
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-10.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-10.mdx
new file mode 100644
index 000000000..a5521c446
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-10.mdx
@@ -0,0 +1,16 @@
+## 自定义 GraphQL API 参考布局
+
+使用 `docs.yml` 布局中的 `operation` 关键字控制 GraphQL 操作在侧边栏中的显示方式。可以排序操作、设置自定义标题和 slug、隐藏操作,并将它们分组到不同的部分。
+
+```yaml docs.yml
+navigation:
+ - api: GraphQL API Reference
+ layout:
+ - section: Plants
+ contents:
+ - operation: QUERY getPlant
+ title: Get plant details
+ - operation: MUTATION createPlant
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-11.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-11.mdx
new file mode 100644
index 000000000..158f4fbf7
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-11.mdx
@@ -0,0 +1,11 @@
+## 自托管文档的 API 密钥注入
+
+自托管部署通过环境变量支持 [API 密钥注入](/learn/docs/authentication/features/api-key-injection)。启用 `FERN_API_KEY_INJECTION_ENABLED` 在 API Explorer 中显示 **登录** 按钮,而无需对整个站点要求登录。使用 `FERN_AUTH_ALLOWLIST` 和 `FERN_AUTH_DENYLIST` 控制页面级别的访问。
+
+
+
+## 多个 API 密钥和每环境密钥
+
+API 密钥注入支持 [多个 API 密钥](/learn/docs/authentication/setup/jwt#build-the-fern-claim) 和 [每环境凭据](/learn/docs/authentication/setup/jwt#build-the-fern-claim)。在 `bearer_token` 中提供多个密钥作为 JSON 编码的数组,并使用 `env_state` 通过子字符串匹配为每个环境设置不同的凭据。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-12.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-12.mdx
new file mode 100644
index 000000000..e1d0214af
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-12.mdx
@@ -0,0 +1,5 @@
+## JWT 回调的 POST 支持
+
+JWT 回调端点(`/api/fern-docs/auth/jwt/callback`)现在除了接受带查询参数的 `GET` 请求外,还接受带 `application/x-www-form-urlencoded` 主体的 `POST` 请求。POST 避免在 URL 和服务器日志中暴露 JWT 令牌。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-17.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-17.mdx
new file mode 100644
index 000000000..23d7828eb
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-17.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["components"]
+---
+
+## 步骤目录深度跟随标题级别
+
+当使用 `` 与 markdown 标题语法时,步骤条目现在在目录中以匹配其标题级别的深度显示——`##` 标题在深度 2,`###` 标题在深度 3。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-23.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-23.mdx
new file mode 100644
index 000000000..8db2bb210
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-23.mdx
@@ -0,0 +1,15 @@
+---
+tags: ["writing-content"]
+---
+
+## 使用 `api:` 语法链接到 API 端点
+
+使用 `api:` 链接语法通过 HTTP 方法和路径链接到 API 端点,而不是硬编码 URL slug。Fern 在构建时将这些链接解析为正确的端点 URL。
+
+```mdx
+[Create a payment](api:POST/v2/payments)
+```
+
+这在 Markdown 页面、OpenAPI `description` 字段和 Fern Definition `docs` 字段中都有效。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-25.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-25.mdx
new file mode 100644
index 000000000..6ea28539a
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-25.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["customization", "configuration", "fern-editor"]
+---
+
+## 在编辑器中编辑站点徽标、图标和标题
+
+您现在可以直接在 Fern Editor 中更新站点的徽标、图标和标题——无需手动编辑配置文件。在编辑器中导航到站点设置以进行可视化更改。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-26.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-26.mdx
new file mode 100644
index 000000000..3efb57e5b
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-26.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["api-reference", "ai"]
+---
+
+## OpenAPI 规范端点
+
+您的 Fern 文档站点现在在 `/openapi.json` 和 `/openapi.yaml` 提供原始的 OpenAPI 3.1 规范。可下载用于 SDK 生成、契约测试或导入到 Postman 等工具中。该规范还链接在您站点的 `llms.txt` 中,因此 AI 编程助手可以自动发现并使用它。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-27.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-27.mdx
new file mode 100644
index 000000000..1e16b5a37
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-27.mdx
@@ -0,0 +1,22 @@
+---
+tags: ["fern-editor", "ai"]
+---
+
+## 协作编辑器会话
+
+您现在可以查看和编辑队友的 Fern Editor 会话。如果队友创建了编辑器会话,您可以从仪表板打开他们的会话并直接将更改提交到他们的 PR 中。这样可以轻松调整文案或修复内容,无需切换到 GitHub。
+
+了解更多关于 [Fern Editor](/learn/docs/writing-content/fern-editor) 的信息。
+
+## Fern Writer 中的拉取请求归属
+
+Fern Writer 现在在每个拉取请求描述中包含 **请求者** 字段,将每个文档更改归属到发起请求的人员或团队。提交已签名并归属到 `fern-support`,使自动化更改在您的代码库历史记录中与手动贡献清楚区分。
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-02-28.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-02-28.mdx
new file mode 100644
index 000000000..833f749d6
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-02-28.mdx
@@ -0,0 +1,20 @@
+---
+tags: ["customization", "configuration", "docs.yml"]
+---
+
+## 使用 Fern Editor 的"编辑此页面"功能
+
+"编辑此页面"按钮现在除了链接到 GitHub 外,还可以打开 Fern Editor。[当您将启动模式设置为 `dashboard`](/learn/docs/configuration/site-level-settings#edit-this-page-configuration) 时,点击按钮会让用户选择在 Fern Editor 中编辑页面或在 GitHub 上查看源代码。这对于内部文档站点特别有用,因为大多数查看者也是编辑者。
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-06.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-06.mdx
new file mode 100644
index 000000000..b2d0e19c7
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-06.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["security"]
+---
+
+## OAuth 登出端点
+
+您现在可以为 OAuth 认证配置登出 URL。当用户点击 **登出** 时,除了清除本地会话 cookie 外,Fern 还会将他们重定向到您的 OAuth 提供商的登出端点以结束他们的会话。要设置这个功能,请将您的登出 URL(例如 `https:///oauth2/logout`)与其他 OAuth 客户端详细信息一起发送给 Fern。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-09.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-09.mdx
new file mode 100644
index 000000000..43e9dda9b
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-09.mdx
@@ -0,0 +1,18 @@
+---
+tags: ["local-development", "configuration"]
+---
+
+## 带有直接页面链接的预览工作流
+
+您现在可以使用更新的 GitHub Actions 预览工作流,它会在您的拉取请求上评论直接链接到每个您更改的页面,这样审查者可以直接跳转到受影响的页面,而无需浏览整个站点。当您推送新提交时,评论会更新新的预览链接和刷新的页面链接。
+
+
+
+
+
+要采用此工作流,请将您的 `.github/workflows/preview-docs.yml` 替换为更新版本。通过[引导式 UI](https://dashboard.buildwithfern.com/get-started) 或 [CLI 快速开始](/learn/docs/getting-started/quickstart) 创建的新站点会自动包含此功能。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-11.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-11.mdx
new file mode 100644
index 000000000..6bb822529
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-11.mdx
@@ -0,0 +1,17 @@
+---
+tags: ["seo", "configuration", "docs.yml"]
+---
+
+## 动态 OG 图片 [#dynamic-og-images]
+
+Fern 现在可以自动为您文档站点的每个页面生成唯一的 Open Graph 图片。在您的 `docs.yml` 元数据中设置 `og:dynamic` 为 true 来启用此功能。在前置配置中设置了 `og:image` 的页面将使用指定的图片。
+
+您还可以使用 `og:background-image` 为动态生成的 OG 图片设置自定义背景图片,而不是纯色背景。
+
+```yaml docs.yml
+metadata:
+ og:dynamic: true
+ og:background-image: ./images/og-background.png # 可选
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-12.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-12.mdx
new file mode 100644
index 000000000..65561c69e
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-12.mdx
@@ -0,0 +1,41 @@
+---
+tags: ["components", "navigation", "configuration", "docs.yml"]
+---
+
+## 多文件 ZIP 下载
+
+`` 组件现在支持使用新的 `sources` 属性将多个文件打包成单个 ZIP 下载。当您希望用户下载一组相关资源(如品牌徽标、SDK 文件或配置模板)而无需托管预构建的 ZIP 文件时,这非常有用。
+
+向 `sources` 传递一个公开可访问的 URL 数组,组件会在客户端获取每个文件并将它们打包成 ZIP 归档:
+
+```jsx Markdown
+
+
+
+```
+
+
+
+## 折叠部分的 `open-by-default` 选项
+
+侧边栏导航中的部分和文件夹支持新的 `collapsed: open-by-default` 值。使用此值配置的部分默认展开,但显示切换按钮以便用户可以折叠它们。
+
+```yaml docs.yml {3}
+navigation:
+ - section: API 指南
+ collapsed: open-by-default
+ contents:
+ - page: 认证
+ path: ./pages/api/auth.mdx
+ - page: 分页
+ path: ./pages/api/pagination.mdx
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-18.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-18.mdx
new file mode 100644
index 000000000..7ddf2b873
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-18.mdx
@@ -0,0 +1,15 @@
+---
+tags: ["local-development", "configuration"]
+---
+
+## 稳定的命名预览链接
+
+通过向 `fern generate --docs --preview` 传递 `--id` 参数,与审阅者分享单个预览链接,该链接在您推送更改时保持最新状态。使用相同的 `--id` 重新运行会就地更新现有预览,而不是创建新的 URL。
+
+```bash
+fern generate --docs --preview --id my-feature
+```
+
+要在 CI 中设置此功能,请更新您的 [GitHub Actions 工作流](/learn/docs/preview-publish/preview-changes#automate-with-github-actions),将分支名称作为 `--id` 传递。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-23.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-23.mdx
new file mode 100644
index 000000000..707abfdb7
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-23.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["self-hosted"]
+---
+
+## 自托管部署的页面反馈日志记录
+
+自托管部署现在将[页面反馈](/learn/docs/user-feedback)事件记录为带有 `[fern-docs-feedback]` 前缀的结构化 JSON。过滤您的容器日志以捕获用户反馈,包括点赞/踩投票和书面消息。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-27.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-27.mdx
new file mode 100644
index 000000000..04a410fe2
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-27.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["seo"]
+---
+
+## 站点地图时间戳
+
+您的站点地图条目现在包含一个 `` 时间戳,该时间戳对读者不可见,专门供搜索引擎使用,以优先抓取最近更新的页面。时间戳仅在页面内容实际更改时更新——空格或大小写等微不足道的格式差异会被忽略。这遵循了 [Google 的站点地图最佳实践](https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-30.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-30.mdx
new file mode 100644
index 000000000..d452a7362
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-30.mdx
@@ -0,0 +1,19 @@
+---
+tags: ["customization", "configuration", "docs.yml"]
+---
+
+## 标签对齐和位置选项
+
+您现在可以使用 `docs.yml` 中的 `theme.tabs` 微调标签的外观和行为。选择默认的下划线或气泡样式,将标签放在标题或边栏中,并从单个配置块中心对齐标题标签。
+
+```yaml docs.yml
+theme:
+ tabs:
+ style: bubble
+ alignment: center
+ placement: header
+```
+
+现有的字符串简写(例如 `theme.tabs: bubble`)继续用于简单的样式更改。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-03-31.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-03-31.mdx
new file mode 100644
index 000000000..5e976769b
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-03-31.mdx
@@ -0,0 +1,37 @@
+---
+tags: ["configuration", "docs.yml", "ai-features", "integrations"]
+---
+
+## 配置 `fern check` 规则严重性
+
+您现在可以使用 `check.rules` 属性直接在 `docs.yml` 文件中配置 `fern check` 运行的验证规则的严重性。将单个规则设置为 `"warn"`(非阻塞)或 `"error"`(阻塞)来控制哪些检查会使您的构建失败。
+
+```yaml docs.yml
+check:
+ rules:
+ broken-links: error
+ example-validation: warn
+```
+
+`--broken-links` 和 `--strict-broken-links` CLI 标志现已弃用,推荐使用此配置。
+
+
+
+## AI 搜索升级
+
+Ask Fern 现在运行在 Claude 4.6 Sonnet 上,提供更快、更准确的答案。
+
+
+
+## Context7 集成
+
+在您的 Fern 文档站点上托管 [Context7](https://context7.com/) 验证文件。在 `docs.yml` 中添加 `integrations.context7`,指向您的 `context7.json` 文件,Fern 将在您域名的 `/context7.json` 路径提供此文件。
+
+```yaml docs.yml
+integrations:
+ context7: ./path/to/context7.json
+```
+
+需要 Fern CLI 版本 `4.52.0` 或更高版本。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-02.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-02.mdx
new file mode 100644
index 000000000..192cd81ed
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-02.mdx
@@ -0,0 +1,36 @@
+---
+tags: ["ai", "configuration", "api-reference", "docs.yml", "fern-check"]
+---
+
+## llms.txt 中的每页指令
+
+您可以添加一个指令,当页面提供给 AI 代理时会自动添加到每个页面的开头——包括单个 Markdown 页面 URL 和 `llms-full.txt` 中的每个页面部分。该指令仅对请求 Markdown 的代理可见;面向人类的文档不受影响。
+
+```yaml docs.yml
+agents:
+ page-directive: "For a complete page index, fetch https://docs.example.com/llms.txt"
+```
+
+
+
+## 缺失重定向检查规则
+
+`fern check` 的 `missing-redirects` 规则检测在没有重定向的情况下被删除或移动的页面。它将您当前的文档导航与之前发布的状态进行比较,当之前发布的 URL 会返回 404 时发出警告。在 `docs.yml` 中配置其严重性:
+
+```yaml docs.yml
+check:
+ rules:
+ missing-redirects: error
+```
+
+需要通过 `fern login` 或 `FERN_TOKEN` 环境变量进行身份验证。在首次发布、未经身份验证或网络不可用时跳过检查。
+
+需要 Fern CLI 版本 `4.57.0` 或更高版本。
+
+
+
+## 库文档生成器
+
+从您的 Python 或 C++ 库源代码生成 MDX 文档页面,并将其包含在您的 Fern Docs 站点中。在 `docs.yml` 中配置您的库,运行 `fern docs md generate`,生成的页面将作为导航部分与您的其他文档一起出现。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-09.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-09.mdx
new file mode 100644
index 000000000..b73af26a9
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-09.mdx
@@ -0,0 +1,31 @@
+---
+tags: ["ai", "ask-fern", "configuration", "docs.yml"]
+---
+
+## AI 智能体默认页面指令
+
+现在为 AI 智能体提供的每个页面都包含一个默认指令,告诉智能体如何以编程方式导航您的文档 — 指向 `.md` URL、`llms.txt` 和 `llms-full.txt`。该指令使用您站点的域名和基础路径自动生成,无需配置。
+
+```text title="默认页面指令" wordWrap
+For clean Markdown of any page, append .md to the page URL. For a complete documentation index, see https://docs.example.com/llms.txt. For full documentation content, see https://docs.example.com/llms-full.txt.
+```
+
+您仍然可以使用自定义指令覆盖默认指令,或完全禁用它。
+
+
+
+## 独立搜索组件
+
+使用 [`@fern-api/search-widget`](https://www.npmjs.com/package/@fern-api/search-widget) 包在任何 React 站点上嵌入 Ask Fern 的 AI 驱动搜索。该组件呈现一个按钮,点击后打开连接到您文档内容的搜索模态框。它需要 React 19;所有其他依赖项都已打包。
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-10.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-10.mdx
new file mode 100644
index 000000000..09c40ff07
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-10.mdx
@@ -0,0 +1,19 @@
+---
+tags: ["ai", "configuration", "docs.yml"]
+---
+
+## 自定义 `llms.txt` 和 `llms-full.txt` 文件
+
+提供您自己的 `llms.txt` 和 `llms-full.txt` 文件,而不是使用自动生成的版本。在 `docs.yml` 的 `agents` 键下添加文件路径:
+
+```yaml docs.yml
+agents:
+ llms-txt: ./path/to/llms.txt
+ llms-full-txt: ./path/to/llms-full.txt
+```
+
+自定义文件在根级 `/llms.txt` 和 `/llms-full.txt` 端点提供。嵌套路径继续使用自动生成的输出。
+
+需要 Fern CLI 版本 `4.67.0` 或更高版本。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-11.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-11.mdx
new file mode 100644
index 000000000..9fc946e5b
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-11.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["api-reference", "ai"]
+---
+
+## AsyncAPI 规范端点
+
+对于包含 WebSocket 通道的站点,Fern 文档站点在 `/asyncapi.json` 和 `/asyncapi.yaml` 提供您的原始 AsyncAPI 2.6.0 规范。下载它用于客户端生成、合约测试或导入到兼容 AsyncAPI 的工具中。该规范也从您站点的 `llms.txt` 链接,因此 AI 编码助手可以自动发现和使用它。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-14.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-14.mdx
new file mode 100644
index 000000000..6ea8f6b28
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-14.mdx
@@ -0,0 +1,19 @@
+---
+tags: ["ai-features", "api-reference", "mdx"]
+---
+
+## AI 搜索模型更新
+
+Ask Fern 现在使用 [Claude 4.6 Sonnet](https://www.anthropic.com/news/claude-sonnet-4-6) 和 [Claude 4.5 Haiku](https://www.anthropic.com/news/claude-haiku-4-5)。
+
+
+
+## 使用 `api:` 语法链接到 API Reference 部分
+
+`api:` 链接语法现在支持链接到 API Reference 部分的根目录。使用 `api:apiName` 创建一个在构建时解析到特定 API Reference 着陆页的链接。这在您的项目有多个 API 时很有用。
+
+```mdx Markdown
+Explore the [Plant Store API](api:plant-store) reference.
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-20.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-20.mdx
new file mode 100644
index 000000000..5f23b3d2c
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-20.mdx
@@ -0,0 +1,26 @@
+---
+tags: ["navigation", "configuration", "docs.yml"]
+---
+
+## 移动端目录栏
+
+使用 [`guide` 和 `overview` 布局](/learn/docs/configuration/page-level-settings#layout)的页面现在可以在移动端和平板设备视口中在头部下方显示粘性目录栏。该栏显示滚动进度指示器和当前标题,点击时展开为完整目录。
+
+
+
+
+
+在 `docs.yml` 的 `layout` 下添加 `mobile-toc: true` 来启用:
+
+```yaml docs.yml
+layout:
+ mobile-toc: true
+```
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-21.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-21.mdx
new file mode 100644
index 000000000..ea67c0b6f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-21.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["customization", "components"]
+---
+
+## 从自定义脚本定位 logo
+
+`` 现在渲染时带有 `data-fern-logo` 属性,因此自定义脚本可以使用 `document.querySelector('#fern-header [data-fern-logo]')` 定位 logo。使用它在特定页面重写 logo 的 `href` 或修改其他行为。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-22.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-22.mdx
new file mode 100644
index 000000000..4a75ac879
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-22.mdx
@@ -0,0 +1,11 @@
+---
+tags: ["developer-tools"]
+---
+
+## 合并时清理 GitLab 预览部署
+
+更新的 [GitLab CI/CD 流水线](/learn/docs/developer-tools/git-lab#add-the-cicd-pipeline)现在包含一个 `cleanup_preview` 阶段,在合并请求合并到默认分支后删除该 MR 的预览部署,避免陈旧的预览残留。
+
+要采用此工作流程,请用更新的版本替换您的 `.gitlab-ci.yml` 文件。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-23.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-23.mdx
new file mode 100644
index 000000000..cfd6cbe3f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-23.mdx
@@ -0,0 +1,11 @@
+---
+tags: ["developer-tools"]
+---
+
+## 在合并时清理 GitHub Actions 预览部署
+
+[GitHub Actions 预览工作流](/learn/docs/preview-publish/preview-changes#automate-with-github-actions) 现在有一个可选的配套 `cleanup-preview.yml` 工作流,可以在 PR 合并后删除拉取请求的预览部署,这样过期的预览就不会留存。
+
+要采用此工作流,请在现有预览工作流旁边添加 `.github/workflows/cleanup-preview.yml`。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-24.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-24.mdx
new file mode 100644
index 000000000..a538819de
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-24.mdx
@@ -0,0 +1,11 @@
+---
+tags: ["ai-features"]
+---
+
+## "连接到 Claude Code" 页面操作
+
+启用了 [Ask Fern](/learn/docs/ai-features/ask-fern/overview) 的 Fern Docs 网站现在会在现有页面操作旁显示"连接到 Claude Code"按钮。点击按钮会复制一个 `claude mcp add` 命令。读者可以将其粘贴到终端中,以将您网站的 [MCP 服务器](/learn/docs/ai-features/mcp-server)注册到 Claude Code。
+
+此操作默认启用,可以通过在 `docs.yml` 中设置 `page-actions.options.claude-code: false` 来关闭。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/changelog/2026-04-27.mdx b/fern/translations/zh/products/docs/pages/changelog/2026-04-27.mdx
new file mode 100644
index 000000000..254d642c0
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/changelog/2026-04-27.mdx
@@ -0,0 +1,9 @@
+---
+tags: ["configuration", "docs.yml"]
+---
+
+## 全局主题
+
+在单个控制仓库中定义您的文档品牌,并在多个网站之间共享。使用 `fern docs theme` CLI 命令导出、上传和管理主题,然后在任何子仓库的 `docs.yml` 中通过 `global-theme` 属性按名称引用主题。
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/component-library/custom-components/reusable-markdown.mdx b/fern/translations/zh/products/docs/pages/component-library/custom-components/reusable-markdown.mdx
new file mode 100644
index 000000000..9c5ebfe7f
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/component-library/custom-components/reusable-markdown.mdx
@@ -0,0 +1,86 @@
+---
+title: 可重复使用的片段
+description: 使用可重复使用的自定义 Markdown 片段为您的文档提供单一来源,保持内容同步。编辑一次,处处更新。
+sidebar-title: 可复用代码片段
+---
+
+使用单一来源保持您的文档 DRY(Don't Repeat Yourself):定义一次可重复使用的 Markdown 片段,然后在多个地方引用它。这样,您只需要在一个地方更新片段即可保持所有引用同步。
+
+可重复使用的片段适用于常量(API 限制、订阅价格、版本号)、重复的警告或注释以及标准化格式块。
+
+
+
+
+在您的 `fern` 项目的任意位置创建一个名为 `snippets` 的文件夹。在 `snippets` 文件夹内,为您想要定义的每个片段创建一个新的 Markdown 文件。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+在每个片段文件中,定义您想要重复使用的内容。
+
+```mdx title="snippets/peace-lily.mdx"
+Peace lilies are easy to grow and relatively trouble-free.
+```
+
+
+
+
+为了使片段更加灵活,您可以使用参数(也称为变量)。参数使用 `{{parameterName}}` 语法,可以放在片段内容的任何位置。
+
+```mdx title="snippets/watering-schedule.mdx"
+Remember to water your {{plant}} every {{interval}} days.
+```
+
+然后,您可以在每次使用片段时为这些参数传递不同的值。
+
+
+
+
+要在您的文档中使用片段,请通过其文件路径(包括 `.mdx` 扩展名)引用它。如果您在片段中使用了参数(变量),请为每个参数传递值:
+
+
+
+
+ ```jsx
+
+
+ They symbolize peace and prosperity.
+
+
+ ```
+
+
+
+
+
+
+ They symbolize peace and prosperity.
+
+
+
+
+
+
+ `src` 路径是以 `fern` 文件夹为根目录的绝对路径。无论您从哪个页面引用,路径都是相同的:
+
+ | 文件夹结构 | 引用 |
+ | --- | --- |
+ | `fern/snippets/peace-lily.mdx` | `src="/snippets/peace-lily.mdx"` |
+ | `fern/docs/snippets/peace-lily.mdx` | `src="/docs/snippets/peace-lily.mdx"` |
+ | `fern/docs/guides/snippets/peace-lily.mdx` | `src="/docs/guides/snippets/peace-lily.mdx"` |
+
+
+
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/component-library/default-components/accordions.mdx b/fern/translations/zh/products/docs/pages/component-library/default-components/accordions.mdx
new file mode 100644
index 000000000..16b1e7a87
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/component-library/default-components/accordions.mdx
@@ -0,0 +1,110 @@
+---
+title: 手风琴组件
+sidebar-title: 手风琴组件
+description: 为您的 Fern 文档添加可展开的手风琴组件。非常适合 FAQ、设置面板以及内容的渐进式展示。
+---
+
+
+`` 组件可创建可展开的内容区域,内容支持搜索且符合 SEO 规范,即使在折叠状态下也可被访问。可将手风琴组件用于 FAQ、文档章节、设置面板,或任何通过渐进式展示能提升可读性的内容。
+
+您可以使用单个手风琴,也可以使用 `` 将多个手风琴组合在一起。
+
+## 用法
+
+
+
+
+ 第 1 节的内容,默认展开
+
+
+ 第 2 节的内容
+
+
+
+
+```jsx Markdown
+
+
+ 第 1 节的内容,默认展开
+
+
+ 第 2 节的内容
+
+
+```
+
+## 变体
+
+在每个手风琴中,您都可以嵌入图片、视频和其他组件(提示框、代码块等)以呈现丰富的交互式内容。
+
+### 多媒体
+
+
+
+
+
+
+
+
+
+```jsx Markdown
+
+
+
+
+
+```
+
+### 嵌套组件
+
+
+
+
+ 这里是嵌入在手风琴组件中的提示框
+
+
+
+
+```jsx Markdown
+
+
+ 这里是嵌入在手风琴组件中的提示框
+
+
+```
+
+### 默认展开
+
+
+
+ 使用 `defaultOpen` 属性可以让特定手风琴在页面加载时默认展开。这对于突出重要信息或常用内容非常有用。
+
+
+
+```jsx Markdown
+
+ 使用 `defaultOpen` 属性可以让特定手风琴在页面加载时默认展开。这对于突出重要信息或常用内容非常有用。
+
+```
+
+## 属性
+
+
+ 显示在手风琴标题栏中的标题
+
+
+
+ 手风琴展开时显示的内容。可以包含文本、Markdown 和组件。
+
+
+
+ 页面加载时手风琴是否默认展开。如未指定,则默认折叠。
+
+
+
+ 手风琴的唯一 ID。用于链接和导航。如未指定,将自动生成一个 ID。
+
+
+
+ 应用于手风琴组件的额外 CSS 类名
+
diff --git a/fern/translations/zh/products/docs/pages/component-library/default-components/anchor.mdx b/fern/translations/zh/products/docs/pages/component-library/default-components/anchor.mdx
new file mode 100644
index 000000000..f1553f47c
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/component-library/default-components/anchor.mdx
@@ -0,0 +1,99 @@
+---
+title: Anchor
+description: 为段落、表格和其他无标题内容创建可链接的锚点
+sidebar-title: 锚点组件
+---
+
+`` 组件为段落、表格和代码块等特定内容创建直接链接。当您需要引用不会自动生成链接的非标题内容时,请使用锚点。
+
+
+ 标题会根据其文本内容自动生成锚点链接,因此您无需对标题使用锚点组件。
+
+
+## 使用方法
+
+用 `` 标签包装您的内容并为其分配一个自定义锚点 ID,您可以使用井号符号在 URL 中链接到该锚点(示例:`https://website.com/page#data`)。
+
+
+
+
这句话有一个名为 `#data` 的自定义锚点。您可以通过此 URL 访问它:https://buildwithfern.com/learn/docs/writing-content/components/anchor#data。
+
+
+
+```jsx Markdown
+这句话有一个名为 `#data` 的自定义锚点。您可以通过此 URL 访问它:https://buildwithfern.com/learn/docs/writing-content/components/anchor#data。
+```
+
+## 变体
+
+### 锚点表格
+
+
+
+
+ | 端点 | 方法 | 描述 |
+ |----------|--------|-------------|
+ | `/plants` | GET | 检索所有植物 |
+ | `/plants/:id` | GET | 检索特定植物 |
+ | `/plants` | POST | 创建新植物 |
+
+
+
您可以直接链接到 [API 端点表格](#api-endpoints)。
+
+
+
+
+```jsx Markdown
+
+
+| 端点 | 方法 | 描述 |
+|----------|--------|-------------|
+| `/plants` | GET | 检索所有植物 |
+| `/plants/:id` | GET | 检索特定植物 |
+| `/plants` | POST | 创建新植物 |
+
+
+
+您可以直接链接到 [API 端点表格](#api-endpoints)。
+```
+
+### 锚点代码块
+
+
+
+
+ ```python
+ def water_plant(plant_id, amount):
+ """Water a plant with specified amount"""
+ headers = {"Authorization": f"Bearer {api_key}"}
+ return requests.post(f"https://api.example.com/plants/{plant_id}/water",
+ json={"amount": amount},
+ headers=headers)
+ ```
+
+ 在您的实现中参考 [浇水代码示例](#example-code)。
+
+
+
+````jsx Markdown
+
+
+```python
+def water_plant(plant_id, amount):
+ """Water a plant with specified amount"""
+ headers = {"Authorization": f"Bearer {api_key}"}
+ return requests.post(f"https://api.example.com/plants/{plant_id}/water",
+ json={"amount": amount},
+ headers=headers)
+```
+
+
+
+在您的实现中参考 [浇水代码示例](#example-code)。
+````
+
+## 属性
+
+
+ 此内容的锚点 ID。在 URL 中使用井号引用它(示例:`#data`)
+
\ No newline at end of file
diff --git a/fern/translations/zh/products/docs/pages/component-library/default-components/aside.mdx b/fern/translations/zh/products/docs/pages/component-library/default-components/aside.mdx
new file mode 100644
index 000000000..2e0060e4d
--- /dev/null
+++ b/fern/translations/zh/products/docs/pages/component-library/default-components/aside.mdx
@@ -0,0 +1,19 @@
+---
+title: Aside
+description: 使用 Fern 的 Aside 组件为您的文档页面添加浮动、粘性内容。非常适合展示代码示例和 API 端点片段。
+sidebar-title: 侧边栏组件
+---
+
+`