# General Translation Integrations: Sanity 插件 配置
URL: https://generaltranslation.com/zh/docs/integrations/sanity/reference/plugin-configuration.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 为 Sanity Studio 配置 General Translation 的 gt-sanity 插件。gtPlugin 的 API 参考。

在你的 Sanity config 中使用 `gtPlugin` 函数注册 General Translation。传入一个选项对象。

```ts title="sanity.config.ts"
import { gtPlugin } from 'gt-sanity';

gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'fr'],
  translateDocuments: [{ type: 'article' }],
});
```

## 选项 [#options]

| 选项                                                                | 说明                                                 | 类型                                                                    | 可选 | 默认值                                   |
| ----------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------- | -- | ------------------------------------- |
| [`sourceLocale`](#source-locale)                                  | 源语言代码，例如 `en`。                                     | `string`                                                              | 是  | `defaultLocale`，然后使用库默认值              |
| [`defaultLocale`](#default-locale)                                | `sourceLocale` 的别名，便于展开 `gt.config.json`。          | `string`                                                              | 是  | —                                     |
| [`locales`](#locales)                                             | 目标区域设置代码。会移除源区域设置和重复条目。                            | `string[]`                                                            | 否  | —                                     |
| [`customMapping`](#custom-mapping)                                | 自定义区域设置代码映射和属性覆盖。                                  | [`CustomMapping`](/docs/platform/core/reference/types/custom-mapping) | 是  | —                                     |
| [`apiKey`](#api-key)                                              | General Translation API 密钥。                        | `string`                                                              | 是  | Secrets 文档                            |
| [`projectId`](#project-id)                                        | General Translation 项目 ID。                         | `string`                                                              | 是  | Secrets 文档                            |
| [`secretsNamespace`](#secrets-namespace)                          | 私有凭据文档的 `_id`。                                     | `string`                                                              | 是  | `generaltranslation.secrets`          |
| [`languageField`](#language-field)                                | 用于存储区域设置的文档字段。                                     | `string`                                                              | 是  | `language`                            |
| [`translateDocuments`](#translate-documents)                      | 过滤可翻译的文档。                                          | `TranslateDocumentFilter[] \| string[]`                               | 是  | `[]`                                  |
| [`singletons`](#singletons)                                       | 视为单例的文档 ID。                                        | `string[]`                                                            | 是  | `[]`                                  |
| [`singletonMapping`](#singleton-mapping)                          | 将源 ID 和区域设置映射到翻译后的单例 ID。                           | `(sourceDocumentId: string, locale: string) => string`                | 是  | `` `${sourceDocumentId}-${locale}` `` |
| [`showDocumentInternationalization`](#show-doc-i18n)              | 自动添加 `@sanity/document-internationalization`。      | `boolean`                                                             | 是  | `true`                                |
| [`internationalizedArray`](#internationalized-array)              | 为字段级本地化配置 `sanity-plugin-internationalized-array`。 | `GTFieldLevelLocalizationConfig`                                      | 是  | —                                     |
| [`fieldLevelLocalization`](#field-level-localization)             | `internationalizedArray` 的别名。                      | `GTFieldLevelLocalizationConfig`                                      | 是  | —                                     |
| [`translationLevel`](#translation-level)                          | 选择文档级、字段级或混合翻译。                                    | `'document' \| 'internationalizedArray' \| 'mixed'`                   | 是  | `'document'`                          |
| [`fieldLevelDocuments`](#field-level-documents)                   | 在混合模式下使用字段级本地化的文档类型。                               | `TranslateDocumentFilter[] \| string[]`                               | 是  | `[]`                                  |
| [`autoRefresh`](#auto-refresh)                                    | 自动轮询翻译状态的初始状态。                                     | `boolean`                                                             | 是  | `true`                                |
| [`autoImport`](#auto-import)                                      | 翻译完成后自动导入的初始状态。                                    | `boolean`                                                             | 是  | `true`                                |
| [`autoPatchReferences`](#auto-patch-references)                   | 导入后自动修补引用的初始状态。                                    | `boolean`                                                             | 是  | `false`                               |
| [`autoPublish`](#auto-publish)                                    | 导入后自动发布的初始状态。                                      | `boolean`                                                             | 是  | `false`                               |
| [`preserveExistingTranslations`](#preserve-existing-translations) | **保存本地编辑**开关的初始状态。                                 | `boolean`                                                             | 是  | `false`                               |
| [`ignoreFields`](#ignore-fields)                                  | 从源内容复制但不翻译的字段。                                     | `FieldMatcher[]`                                                      | 是  | `[]`                                  |
| [`dedupeFields`](#dedupe-fields)                                  | 从源内容复制，并在每个区域设置中保持唯一的字段。                           | `FieldMatcher[]`                                                      | 是  | `[]`                                  |
| [`skipFields`](#skip-fields)                                      | 从翻译后的文档中移除的字段。                                     | `FieldMatcher[]`                                                      | 是  | `[]`                                  |
| [`additionalStopTypes`](#additional-stop-types)                   | 额外保留且不翻译的 schema 类型。                               | `string[]`                                                            | 是  | `[]`                                  |
| [`additionalSerializers`](#additional-serializers)                | 用于 marks 和 block 类型的自定义 HTML 序列化器。                 | `Partial<PortableTextHtmlComponents>`                                 | 是  | `{}`                                  |
| [`additionalDeserializers`](#additional-deserializers)            | 自定义 HTML 反序列化器。                                    | `CustomDeserializers`                                                 | 是  | `{}`                                  |
| [`additionalBlockDeserializers`](#additional-block-deserializers) | 自定义 Portable Text block 反序列化规则。                    | `unknown[]`                                                           | 是  | `[]`                                  |

## 区域设置选项 [#locale-options]

### `sourceLocale` [#source-locale]

**类型** `string` · **可选** · **默认值** `defaultLocale`，否则使用库默认值

源语言代码，例如 `en`。插件按以下顺序解析源区域设置：先是 `sourceLocale`，然后是 `defaultLocale`，最后是 `generaltranslation` 库的默认值。

### `defaultLocale` [#default-locale]

**Type** `string` · **可选**

`sourceLocale` 的别名，因此你可以直接将 `gt.config.json` 展开传入 插件。如果两者都已设置，则以 `sourceLocale` 为准。

```ts
import gtConfig from './gt.config.json';

gtPlugin({ ...gtConfig });
```

### `locales` [#locales]

**Type** `string[]` · **Required**

要翻译到的目标区域设置代码，例如 `['es', 'fr', 'ja']`。插件会在配置翻译或 Sanity 的本地化插件之前，移除重复条目以及任何与解析后的源区域设置相同的条目。

| 版本      | 变更                                            |
| ------- | --------------------------------------------- |
| `3.1.1` | 在配置翻译和 Sanity 本地化插件之前，移除重复的目标区域设置以及解析后的源区域设置。 |

### `customMapping` [#custom-mapping]

**类型** [`CustomMapping`](/docs/platform/core/reference/types/custom-mapping) · **可选**

用于将区域设置代码自定义映射到名称，或覆盖区域设置属性。会传递给 `generaltranslation` 库。 (参见 [CustomMapping](/docs/platform/core/reference/types/custom-mapping)) 。

## 凭据 [#credentials]

默认情况下，该 插件 会从 Sanity 的私有文档中读取凭据。 (请参阅[存储凭据](/docs/integrations/sanity/guides/configuring-sanity#store-credentials)) 。

### `apiKey` [#api-key]

**类型** `string` · **可选** · **默认值** 从 secrets 文档读取

你的 General Translation API 密钥。如果已设置，启动时会将其传递给库。如果存在 secrets 文档，则其 `secret` 字段会在运行时优先生效。建议优先使用 secrets 文档，以免将密钥纳入版本控制。

### `projectId` [#project-id]

**类型** `string` · **可选** · **默认值** 从 secrets 文档读取

你的 General Translation 项目 ID。如果存在 secrets 文档，则其中的 `project` 字段会在运行时优先生效。

### `secretsNamespace` [#secrets-namespace]

**类型** `string` · **可选** · **默认值** `generaltranslation.secrets`

用于存放凭证的私有 Sanity 文档的 `_id`。该 插件 会通过 `_id` 获取此文档，并将其 `secret` 字段作为 API 密钥，`project` 字段作为 project ID 读取。给 `_id` 加上前导 `.` 后，该文档即使位于公共数据集中也会保持私有。

```js title="populateSecrets.js"
import { getCliClient } from 'sanity/cli';

const client = getCliClient({ apiVersion: '2026-04-06' });

client.createOrReplace({
  _id: 'generaltranslation.secrets',
  _type: 'generaltranslation.secrets',
  secret: process.env.GT_API_KEY,
  project: process.env.GT_PROJECT_ID,
});
```

## 文档相关选项 [#document-options]

### `languageField` [#language-field]

**类型** `string` · **可选** · **默认值** `language`

用于存储每个文档级翻译区域设置的字段。请为使用文档级本地化进行翻译的文档类型添加一个同名字段，并在查询时使用它来获取特定区域设置的文档。字段级本地化不使用此字段。

### `translateDocuments` [#translate-documents]

**类型** `TranslateDocumentFilter[] | string[]` · **可选** · **默认值** `[]`

用于筛选哪些文档可以翻译。接受筛选对象或简写类型字符串。每个字符串条目 `'article'` 都会标准化为 `{ type: 'article' }`，不包含 `documentId` 或 `type` 的条目会被丢弃。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  translateDocuments: [
    { type: 'article' },
    { documentId: 'homepage' },
    'page', // { type: 'page' } 的简写
  ],
});
```

`TranslateDocumentFilter` 的结构如下：

```ts
type TranslateDocumentFilter = {
  documentId?: string; // 通过 _id 匹配特定文档
  type?: string; // 匹配指定 schema 类型的所有文档
};
```

`type` 条目还会决定 [`showDocumentInternationalization`](#show-doc-i18n) 启用哪些 schema 类型。

### `singletons` [#singletons]

**类型** `string[]` · **可选** · **默认值** `[]`

被视为单例文档的文档 ID，例如站点设置或导航。它们的翻译后文档 ID 由 [`singletonMapping`](#singleton-mapping) 推导。

### `singletonMapping` [#singleton-mapping]

**类型** `(sourceDocumentId: string, locale: string) => string` · **可选** · **默认值** `` `${sourceDocumentId}-${locale}` ``

将单例的源文档 ID 和区域设置映射为翻译后单例的文档 ID。默认映射规则是确定的，因此 `siteSettings` 在西班牙语中会变为 `siteSettings-es`。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  singletons: ['siteSettings'],
  singletonMapping: (sourceDocumentId, locale) => `${sourceDocumentId}_${locale}`,
});
```

### `showDocumentInternationalization` [#show-doc-i18n]

**类型** `boolean` · **可选** · **默认值** `true`

当为 `true` 时，插件 会添加 `@sanity/document-internationalization` 插件，并提供语言徽章、翻译菜单以及按语言划分的文档模板。它会将 [`translateDocuments`](#translate-documents) 中的 `type` entries 作为 schema 类型，并将源区域设置后接标准化后的目标区域设置作为受支持的语言，因此仅在 `translateDocuments` 包含文档类型时才会生效。使用 国际化数组 原地本地化的文档类型会被自动排除。将其设为 `false` 即可自行管理国际化。

如果你已经在 Studio 中注册了 `@sanity/document-internationalization`，请保留现有 setup，并将此选项设为 `false`，这样该插件 (以及它的 `translation.metadata` 文档类型) 就只会注册一次——注册两次会导致重复的 schema 类型错误。翻译功能在你的实例中可照常工作：无论这些内容是由哪次注册添加的，该插件都会通过 [`languageField`](#language-field) 和 `translation.metadata` 文档读取和写入文档。请在两处配置中使用相同的语言 ID 和 language field。

## 字段级本地化 [#field-level]

字段级本地化会将每种区域设置的值以国际化数组的形式存储在同一个文档中。它基于 [`sanity-plugin-internationalized-array`](https://github.com/sanity-io/sanity-plugin-internationalized-array) 实现：`gtPlugin` 会配置该原生插件，而该插件会注册 `internationalizedArray*` schema 类型以及 Studio 编辑 UI。存储的数据采用 `{ _key, _type, language, value }` 这种项结构，因此现有的国际化数组内容无需迁移——而且无论这些类型是由 `gtPlugin` 注册，还是由你自己的 `internationalizedArray()` 注册，翻译的工作方式都相同。

<Callout type="info">
  **v3 中的变更：** 字段级本地化现由 `sanity-plugin-internationalized-array` 提供，而不是由 GT 生成的类型和组件提供。`createInternationalizedArrayTypes`、`FieldLevelUIComponents` 以及 `typePrefix`、`includeCompatibilityTypes` 和 `components` 选项已被移除；如果传入已移除的选项，系统会记录警告并将其忽略。
</Callout>

### `internationalizedArray` [#internationalized-array]

**类型** `GTFieldLevelLocalizationConfig` · **可选**

用于配置字段级本地化的 `sanity-plugin-internationalized-array`。区域设置标识始终来自 `sourceLocale` 和 `locales`；如果你自行注册原生插件，请不要设置此选项，以确保 schema 类型只注册一次。

```ts
type GTFieldLevelLocalizationConfig = {
  enabled?: boolean; // 默认值：false
  fieldTypes?: FieldLevelFieldType[]; // 默认值：['string', 'text']
  languageTitles?: Record<string, string>;
  getLanguageTitle?: (locale: string) => string;
  defaultLanguages?: string[]; // 默认值：[sourceLocale]
  // 透传至 sanity-plugin-internationalized-array
  apiVersion?: string;
  buttonLocations?: ('field' | 'unstable__fieldAction' | 'document')[];
  buttonAddAll?: boolean;
  languageDisplay?: 'titleOnly' | 'codeOnly' | 'titleAndCode';
};

type FieldLevelFieldType =
  | string
  | {
      name: string;
      type: string;
      title?: string;
      of?: unknown[];
      fields?: unknown[];
      options?: Record<string, unknown>;
    };
```

`fieldTypes` 条目可接受 Sanity 类型名称 (`'string'`、`'text'`) 、`'block'` 简写 (一个 Portable Text 数组) ，或用于定义自定义包装字段的对象条目；名为 `seo` 的对象条目会注册 `internationalizedArraySeo`。当两者都已设置时，`getLanguageTitle` 会覆盖 `languageTitles`。`defaultLanguages` 用于控制在空的本地化字段中预填充哪些区域设置，默认值为源区域设置。`apiVersion`、`buttonLocations`、`buttonAddAll` 和 `languageDisplay` 会原样传递给原生插件。

### `fieldLevelLocalization` [#field-level-localization]

**类型** `GTFieldLevelLocalizationConfig` · **可选**

是 [`internationalizedArray`](#internationalized-array) 的说明性别名。

### `translationLevel` [#translation-level]

**类型** `'document' | 'internationalizedArray' | 'mixed'` · **可选** · **默认值** `'document'`

控制匹配文档的翻译方式：

* `'document'` 为每个区域设置创建一份文档
* `'internationalizedArray'` 对已配置字段进行原地本地化
* `'mixed'` 对 [`fieldLevelDocuments`](#field-level-documents) 采用字段级本地化，对其他所有内容采用文档级本地化

### `fieldLevelDocuments` [#field-level-documents]

**类型** `TranslateDocumentFilter[] | string[]` · **可选** · **默认** `[]`

指定在 `translationLevel` 为 `'mixed'` 时使用国际化数组的文档类型。每一项都是一个类型过滤器，例如 `{ type: 'siteSettings' }`，或简写字符串 `'siteSettings'`。这里不支持文档 ID 过滤器。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'fr'],
  translateDocuments: [{ type: 'post' }, { type: 'siteSettings' }],
  internationalizedArray: {
    enabled: true,
    fieldTypes: ['string', 'text', 'block'],
    languageTitles: { es: 'Español', fr: 'Français' },
  },
  translationLevel: 'mixed',
  fieldLevelDocuments: [{ type: 'siteSettings' }],
});
```

然后在 schema 中使用生成的类型：

```ts
defineField({
  name: 'title',
  type: 'internationalizedArrayString',
});
```

## 翻译工作流程选项 [#workflow-options]

这些选项用于设置开关的初始值。当编辑者在 Studio 中更改某个开关时，插件会将全部五项偏好设置保存到 `localStorage`，并以 Sanity 项目和数据集为键。后续访问时，已存储的值会优先于插件配置。如果浏览器存储不可用，更改会一直生效，直到 Studio 重新加载。

### `autoRefresh` [#auto-refresh]

**类型** `boolean` · **可选** · **默认值** `true`

设置**自动刷新**的初始状态。启用后，文档对话框会每 10 秒轮询一次翻译状态。无论此设置为何，手动**刷新**都会检查一次。

### `autoImport` [#auto-import]

**类型** `boolean` · **可选** · **默认值** `true`

设置**完成时自动导入**的初始状态。启用后，文档对话框会导入在其打开期间完成的翻译。它不会自动重新导入对话框打开时已完成的翻译，从而避免覆盖现有的 Sanity 编辑内容。启动新的翻译运行会重置这一基准。

### `autoPatchReferences` [#auto-patch-references]

**类型** `boolean` · **可选** · **默认值** `false`

设置文档级翻译中**导入后自动修补**的初始状态。启用后，导入文档中的引用会重新指向同一区域设置的翻译后文档。如果翻译后文档已发布且不存在草稿，插件会基于已发布版本创建草稿，并修补该草稿，而不修改已发布的内容。

### `autoPublish` [#auto-publish]

**类型** `boolean` · **可选** · **默认值** `false`

设置文档级翻译的**导入后自动发布**初始状态。导入始终会创建或更新草稿。启用此选项后，当源文档发布时，每个导入的翻译都会自动发布。

### `preserveExistingTranslations` [#preserve-existing-translations]

**类型** `boolean` · **可选** · **默认值** `false`

设置**保存本地编辑**开关的初始状态。启用后，会在执行翻译运行前将 Sanity 中当前的翻译发送到 General Translation。这样，源文本未变更的内容将保留现有措辞，不会被再次翻译。

```ts title="sanity.config.ts"
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'fr'],
  translateDocuments: [{ type: 'post' }],
  preserveExistingTranslations: true,
});
```

编辑者可通过 **Translations** 工具或文档对话框更改此偏好设置。与其他工作流偏好设置一样，其已保存的选择会在后续访问时优先于已配置的初始值。

<Callout type="warn">
  启用该开关后，Sanity 中的内容会替换 General Translation 为该文档版本保存的内容，包括已完成但尚未导入的翻译。请先导入所有待处理的翻译，再启用此开关。
</Callout>

 (请参阅[保留对翻译的编辑](/docs/integrations/sanity/guides/translating-content#preserve-edits)) 。

### 版本历史

| 版本      | 变更                                                                                                                                                                                          |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `3.1.0` | 新增 **保存本地编辑** 开关及其 `preserveExistingTranslations` 选项、**保存本地编辑** 操作和 **从头重新翻译**。                                                                                                             |
| `3.1.4` | 新增 `autoRefresh`、`autoImport`、`autoPatchReferences` 和 `autoPublish` 插件选项，并可按项目和数据集分别持久化。将 `autoPatchReferences` 和 `autoPublish` 的默认值改为 `false`；`autoRefresh` 和 `autoImport` 仍为 `true`。      |
| `3.1.6` | 文档级导入会根据已发布状态创建草稿，而非修补已发布文档，因此导入不再绕过自动发布设置。                                                                                                                                                 |
| `4.0.0` | 新增对 Sanity 6 的支持，并停止支持 Sanity 5 系列。该 package 仅支持 ESM，需要 Node.js 22.12 或更高版本，并声明 `sanity` 的 peer 版本范围为 `^6.9.2`；此前随附的 Studio package 现为 peer 依赖项。使用 Sanity 6.0 至 6.8 的 Studio 应继续使用 `3.1.x`。 |

## Studio 结构辅助函数 [#structure-helpers]

`gt-sanity` 导出两个可选启用的辅助函数，用于在 Sanity&#39;s structure tool 中按区域设置对文档级翻译进行分组。

| 辅助函数               | 描述                                | 返回值                 |
| ------------------ | --------------------------------- | ------------------- |
| `gtStructureItems` | 构建按区域设置分组的列表项，以便组合成自定义结构。         | `ListItemBuilder[]` |
| `gtStructure`      | 构建包含按区域设置分组列表项的完整 **Content** 结构。 | `StructureResolver` |

```ts
type GTStructureOptions = {
  types?: string[];
  sourceTitle?: string;
  localeTitle?: (typeTitle: string, locale: string, label: string) => string;
};

function gtStructureItems(
  S: StructureBuilder,
  context?: StructureResolverContext,
  options?: GTStructureOptions
): ListItemBuilder[];

function gtStructure(options?: GTStructureOptions): StructureResolver;
```

默认情况下，这些辅助函数会按 `translateDocuments` 中的文档类型分组。通过国际化数组原地本地化的类型不包括在内。源窗格包含语言字段缺失或与 `sourceLocale` 匹配的文档；每个目标窗格则包含语言字段与相应区域设置匹配的文档。

* `types` 会覆盖从插件配置中选定的文档类型。
* `sourceTitle` 会替换源窗格的区域设置标签。
* `localeTitle` 接收 schema 类型标题、区域设置代码和格式化后的区域设置标签，并返回各目标窗格的标题。

如果无法解析出任何文档类型，该辅助函数会记录一条警告，且不返回任何列表项。 (有关配置示例，请参阅[按区域设置浏览翻译](/docs/integrations/sanity/guides/configuring-sanity#browse-locales)) 。

## 字段匹配器 [#field-matchers]

`ignoreFields`、`dedupeFields` 和 `skipFields` 均接受一个由 `FieldMatcher` 对象组成的数组。匹配器通过 JSONPath `property` 表达式匹配字段，并且还可通过 `documentId` 将范围可选地限制到单个源文档。若要在某个字段出现的所有位置都排除它，建议在 schema 中通过 [schema 排除选项](#schema-exclusion) 对其进行标记。

```ts
type FieldMatcher = {
  documentId?: string | null; // 通过 _id 限定到特定源文档
  fields?: {
    property: string; // JSONPath 表达式，例如 $.slug
    type?: string; // 可选的 schema 类型提示，例如 slug
  }[];
};
```

### `ignoreFields` [#ignore-fields]

**类型** `FieldMatcher[]` · **可选** · **默认值** `[]`

这些字段会直接从源文档复制到翻译后的文档，不会发送到翻译 API。适用于在不同区域设置中应保持完全一致的值，例如类别或标签。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  ignoreFields: [
    // 对所有文档原样复制 category 字段
    { fields: [{ property: '$.category' }] },
    // 仅对一个文档原样复制 tags 字段
    { documentId: 'homepage', fields: [{ property: '$.tags' }] },
  ],
});
```

### `dedupeFields` [#dedupe-fields]

**类型** `FieldMatcher[]` · **可选** · **默认值** `[]`

首次创建翻译后的文档时，会从源值复制这些字段，并通过附加区域设置使其保持唯一。常用于 slug。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'fr'],
  // "about" 变为 "about-es" 和 "about-fr"
  dedupeFields: [{ fields: [{ property: '$.slug', type: 'slug' }] }],
});
```

对于 slug 字段，插件 会更新 slug 对象的 `current` 值。如果之后有人修改了翻译后的 slug，后续导入会保留这个修改后的值。

### `skipFields` [#skip-fields]

**类型** `FieldMatcher[]` · **可选** · **默认值** `[]`

会从翻译后的文档中完全移除的字段。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  skipFields: [
    { fields: [{ property: '$.slug', type: 'slug' }] },
    { documentId: 'homepage', fields: [{ property: '$.debugInfo' }] },
  ],
});
```

## schema 排除选项 [#schema-exclusion]

字段和类型可以直接在 schema 中排除，无需在 plugin-config 中添加条目。在序列化期间，plugin 会检查每个 schema 定义的 `options` 中是否包含这些命名空间，并将匹配项从发送去翻译的内容中移除：

| 选项                                             | 源插件                                     |
| ---------------------------------------------- | --------------------------------------- |
| `options.gt.exclude`                           | `gt-sanity`                             |
| `options.documentInternationalization.exclude` | `@sanity/document-internationalization` |
| `options.aiAssist.exclude`                     | `@sanity/assist`                        |

每个选项都接受 `boolean`；只有显式设为 `true` 时才会排除。排除规则适用于任意嵌套深度。被排除的内容绝不会发送去翻译，因此翻译后的文档会保留源值不变。

```ts
defineField({
  name: 'internalNotes',
  type: 'string',
  options: { gt: { exclude: true } },
});
```

在自定义类型定义的 `options` 中设置排除选项后，该类型的所有出现位置都会被排除，这与原生插件的“字段或类型”语义一致。旧版的 `localize: false` 字段属性也仍然会继续生效。

`gt-sanity` 会扩展 Sanity 的 schema 选项类型 (即 `GTSchemaFieldOptions` 接口) ，因此 `options.gt` 在任何字段定义中都能通过类型检查。

*注意：schema 排除是根据字段名称和类型来标记字段的；如果规则需要按 ID 匹配特定文档，或按区域设置转换值，请使用 [`ignoreFields`、`skipFields` 和 `dedupeFields`](#field-matchers)。*

## 序列化 [#serialization]

该插件会先将文档序列化为 HTML 以便翻译，再将结果反序列化回 Sanity 字段。大多数项目都不需要这些选项。

### `additionalStopTypes` [#additional-stop-types]

**类型** `string[]` · **可选** · **默认值** `[]`

添加到[默认 停止类型](#stop-types)中的额外 schema 类型，这些类型会被保留而不进行翻译。

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  additionalStopTypes: ['codeBlock', 'mux.video', 'mux.videoAsset'],
});
```

### `additionalSerializers` [#additional-serializers]

**类型** `Partial<PortableTextHtmlComponents>` · **可选** · **默认值** `{}`

与默认序列化器合并使用的自定义序列化器，遵循 `@portabletext/to-html` 的组件结构 (如 `types`、`marks`、`block`、`list`、`listItem` 等) 。最常见的用法是序列化自定义 `marks`。

对于自定义 `marks`，请用 `attachGTData` 包裹输出，以确保该标记的数据在翻译后仍能保留。

```ts title="sanity.config.ts"
import { attachGTData, gtPlugin } from 'gt-sanity';

gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  additionalSerializers: {
    marks: {
      link: ({ value, children }) =>
        attachGTData(`<a>${children}</a>`, value, 'markDef'),
      inlineMath: ({ value, children }) =>
        attachGTData(`<span>${children}</span>`, value, 'markDef'),
    },
  },
});
```

`attachGTData(html, data, 'markDef')` 会将 `data` 进行 base64 编码后写入 `html` 第一个元素的 `data-gt-internal` 属性中，并返回更新后的 HTML。导入时，plugin 会读取该属性以重新构建 mark 定义。

```ts
function attachGTData(
  html: string,
  data: Record<string, unknown>,
  type: 'markDef'
): string;
```

### `additionalDeserializers` [#additional-deserializers]

**类型** `CustomDeserializers` · **可选** · **默认值** `{}`

按类型区分的自定义反序列化器，用于将已翻译的 HTML 元素转换回 Sanity 对象。

```ts
type CustomDeserializers = {
  types?: Record<
    string,
    (element: HTMLElement) => Record<string, unknown> | unknown[]
  >;
} & Record<string, unknown>;
```

### `additionalBlockDeserializers` [#additional-block-deserializers]

**类型** `unknown[]` · **可选** · **默认值** `[]`

额外的 Portable Text 块反序列化规则，会追加到插件的内置规则后面。每条规则都是一个带有 `deserialize(node, next)` 方法的对象，其结构与 `@portabletext/block-tools` 的规则格式一致。

## 默认停止类型 [#stop-types]

这些 schema 类型会被保留，且绝不会发送去翻译。你可以使用 [`additionalStopTypes`](#additional-stop-types) 添加更多类型。

```ts
const defaultStopTypes = [
  'reference',
  'date',
  'datetime',
  'file',
  'geopoint',
  'image',
  'number',
  'crop',
  'hotspot',
  'boolean',
  'url',
  'color',
  'code',
];
```

slug 字段默认*不会*被跳过，因此除非你使用 [`dedupeFields`](#dedupe-fields) 或 [`skipFields`](#skip-fields)，否则 slug 的 `current` 字符串会被翻译。

## 导出的辅助工具 [#helpers]

`gt-sanity` 还导出了一些用于 Studio 结构、高级序列化和自定义文档节点的基础组件。大多数项目都不需要它们。

* `TranslationsTab` — `structureTool` 的文档标签页组件。 (参见[配置 Sanity](/docs/integrations/sanity/guides/configuring-sanity#translations-tab)) 。
* `gtStructure` / `gtStructureItems` 和 `GTStructureOptions` — 按区域设置分组的 Studio 结构辅助工具。 (参见 [Studio 结构辅助函数](#structure-helpers)) 。
* `attachGTData` / `detachGTData` — 用于附加和读取自定义序列化器使用的编码标记数据。
* `BaseDocumentSerializer`, `BaseDocumentDeserializer`, `BaseDocumentMerger` — 默认的序列化、反序列化和合并实现。
* `defaultStopTypes`, `customSerializers` — 默认的 停止类型 和序列化器集合。
* `documentInternationalization` 及其类型 (`DocumentInternationalizationConfig`, `Language`, `Metadata`, `TranslationReference`) — 从 `@sanity/document-internationalization` 重新导出。
* `internationalizedArray`、`internationalizedArrayLanguageFilter` 和 `isInternationalizedArrayItemType`，以及 `InternationalizedArrayPluginConfig` 和 `InternationalizedArrayLanguage` 类型 — 从 `sanity-plugin-internationalized-array` 重新导出。
* `GTSchemaFieldOptions` — `options.gt` 对应的 schema 选项接口。 (参见 [Schema 排除选项](#schema-exclusion)) 。

## 完整示例 [#complete-example]

```ts title="sanity.config.ts"
import { defineConfig } from 'sanity';
import { attachGTData, gtPlugin } from 'gt-sanity';

export default defineConfig({
  plugins: [
    gtPlugin({
      // 必填
      sourceLocale: 'en',
      locales: ['es', 'fr', 'de', 'ja'],

      // 文档与字段
      languageField: 'language',
      translateDocuments: [{ type: 'article' }, { type: 'page' }],
      singletons: ['siteSettings', 'navigation'],
      singletonMapping: (id, locale) => `${id}_${locale}`,

      // 字段行为
      ignoreFields: [{ fields: [{ property: '$.category' }] }],
      dedupeFields: [{ fields: [{ property: '$.slug', type: 'slug' }] }],
      skipFields: [{ fields: [{ property: '$.internalNotes' }] }],

      // 序列化 — 仅在默认配置无法处理你的 schema 时使用
      additionalSerializers: {
        marks: {
          link: ({ value, children }) =>
            attachGTData(`<a>${children}</a>`, value, 'markDef'),
        },
      },
    }),
  ],
});
```

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
