# General Translation Integrations: Настройка Sanity
URL: https://generaltranslation.com/ru/docs/integrations/sanity/guides/configuring-sanity.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Как настроить плагин gt-sanity от General Translation для locales, фильтров документов, локализации на уровне полей, учетных данных и синглтонов.

Настройте работу General Translation в Sanity Studio с помощью функции `gtPlugin`.

В этом руководстве рассматриваются самые распространенные параметры. Полный список см. в [справочнике по конфигурации плагина](/docs/integrations/sanity/reference/plugin-configuration).

## Добавьте плагин [#add-plugin]

Добавьте `gtPlugin` в конфигурацию Studio. Этот шаг также рассматривается в [Quickstart](/docs/integrations/sanity/quickstart).

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

export default defineConfig({
  plugins: [
    gtPlugin({
      sourceLocale: 'en',
      locales: ['es', 'zh', 'ja'],
      translateDocuments: [{ type: 'article' }, { type: 'page' }],
    }),
  ],
});
```

## Просмотр переводов по локалям [#browse-locales]

Sanity обычно отображает переведённые документы рядом с исходными. Используйте `gtStructureItems`, чтобы сгруппировать каждый тип переводимых документов в отдельной панели для каждой локали, сохранив остальные элементы структуры.

```ts title="sanity.config.ts"
import { defineConfig } from 'sanity';
import { structureTool } from 'sanity/structure';
import { gtPlugin, gtStructureItems } from 'gt-sanity';

export default defineConfig({
  plugins: [
    gtPlugin({
      sourceLocale: 'en',
      locales: ['es', 'zh', 'ja'],
      translateDocuments: [{ type: 'article' }, { type: 'page' }],
    }),
    structureTool({
      structure: (S, context) =>
        S.list()
          .title('Content')
          .items([
            ...gtStructureItems(S, context),
            S.divider(),
            ...S.documentTypeListItems(),
          ]),
    }),
  ],
});
```

Панель исходной локали включает документы без языкового поля, поэтому в ней по-прежнему отображается контент, созданный до установки плагина. Типы, локализованные на месте с помощью интернационализированных массивов, пропускаются, поскольку их переводы остаются в исходном документе.

Если в Studio нужны только типы, сгруппированные по локалям, передайте полный резолвер `gtStructure()` в `structureTool`:

```ts
import { gtStructure } from 'gt-sanity';

structureTool({ structure: gtStructure() });
```

Передайте `types` одному из помощников, чтобы переопределить группировку типов документов. Используйте `sourceTitle`, чтобы переименовать панель исходного текста, или `localeTitle`, чтобы задать пользовательские заголовки панелей целевых локалей. (См. [справочник помощников структуры](/docs/integrations/sanity/reference/plugin-configuration#structure-helpers)).

## Укажите исходную и целевые локали [#set-locales]

Используйте `sourceLocale` для исходного языка, а `locales` — для целевых языков.

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'zh', 'ja'],
});
```

Если у вас уже есть `gt.config.json`, вы можете добавить его в конфигурацию плагина через оператор расширения. `defaultLocale` также принимается как алиас для `sourceLocale`.

```ts title="sanity.config.ts"
import gtConfig from './gt.config.json';

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

Исходная локаль определяется в таком порядке: `sourceLocale`, затем `defaultLocale`, затем локаль по умолчанию в библиотеке. Если заданы и `sourceLocale`, и `defaultLocale`, приоритет у `sourceLocale`. Плагин удаляет исходную локаль и повторяющиеся элементы из `locales`, поэтому в общей `gt.config.json` можно безопасно указывать локаль по умолчанию.

## Добавьте языковое поле [#language-field]

Переводы на уровне документов хранятся в отдельных документах. Плагин использует языковое поле, чтобы указывать локаль каждого документа. По умолчанию это поле называется `language`. Локализация на уровне полей не использует это поле.

```ts title="schema/article.ts"
import { defineField, defineType } from 'sanity';

export const articleType = defineType({
  name: 'article',
  title: 'Article',
  type: 'document',
  fields: [
    defineField({
      name: 'language',
      type: 'string',
      readOnly: true,
      hidden: true,
    }),
  ],
});
```

Чтобы использовать другое имя поля, задайте `languageField` и укажите это же имя в своей схеме.

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'zh', 'ja'],
  languageField: 'locale',
});
```

## Выберите, какие документы переводить [#choose-documents]

Используйте `translateDocuments`, чтобы указать, какие документы можно переводить. Принимает фильтры по типам документов, по ID документов или сокращённые строки типов.

```ts
// По типу документа
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'zh', 'ja'],
  translateDocuments: [{ type: 'page' }, { type: 'post' }],
});
```

```ts
// По конкретному ID документа
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'zh', 'ja'],
  translateDocuments: [{ documentId: 'homepage' }, { documentId: 'about-page' }],
});
```

```ts
// Сокращённая запись строк типов
gtPlugin({
  sourceLocale: 'en',
  locales: ['es'],
  translateDocuments: ['article', 'page'],
});
```

Строковые записи обрабатываются как `{ type: '<string>' }`. `showDocumentInternationalization` использует записи `type`, чтобы определять, для каких типов схем нужно показывать языковые бейджи и шаблоны, поэтому для включения этих возможностей требуются фильтры по типам документов.

## Настройка локализации на уровне полей [#field-level]

По умолчанию `gt-sanity` выполняет перевод на уровне документа, создавая по одному документу для каждой локали. При локализации на уровне полей значение для каждой локали хранится в одном и том же документе в виде интернационализированного массива (`[{ _key, _type, language, value }]` — той же структуры, что и у [`sanity-plugin-internationalized-array`](https://github.com/sanity-io/sanity-plugin-internationalized-array), поэтому существующие данные не нужно мигрировать).

Включите генерацию схемы с помощью `internationalizedArray` (или его алиаса `fieldLevelLocalization`), затем установите `translationLevel` в `'internationalizedArray'`.

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'zh', 'ja'],
  translateDocuments: [{ type: 'post' }],
  internationalizedArray: { enabled: true },
  translationLevel: 'internationalizedArray',
});
```

Локализация на уровне полей реализована с помощью [`sanity-plugin-internationalized-array`](https://github.com/sanity-io/sanity-plugin-internationalized-array), эталонного плагина Sanity. `gtPlugin` настраивает его на основе `sourceLocale` и `locales`, а нативный плагин регистрирует типы схем `internationalizedArray*` и интерфейс редактирования Studio — кнопки добавления для каждого языка, языковые метки и действия с полями работают точно так же, как в автономном плагине. Используйте зарегистрированные типы в своих схемах.

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

По умолчанию плагин регистрирует типы `string` и `text`. Используйте `fieldTypes`, чтобы добавить `block` (Portable Text) или собственные определения объектов.

```ts
internationalizedArray: {
  enabled: true,
  fieldTypes: ['string', 'text', 'block', { name: 'seo', type: 'seoFields' }],
},
```

Если вы уже сами регистрируете `sanity-plugin-internationalized-array` в своем Studio, сохраните текущую конфигурацию и не задавайте `internationalizedArray`, чтобы типы схем регистрировались только один раз. Translation считывает и записывает сохраненные данные `{ _key, _type, language, value }` независимо от того, какой экземпляр плагина зарегистрировал эти типы, поэтому GT достаточно лишь установить `translationLevel` (и `translateDocuments`).

```ts
import { internationalizedArray } from 'gt-sanity';

plugins: [
  internationalizedArray({
    languages: [
      { id: 'en', title: 'English' },
      { id: 'es', title: 'Spanish' },
    ],
    fieldTypes: ['string'],
  }),
  gtPlugin({
    sourceLocale: 'en',
    locales: ['es'],
    translateDocuments: [{ type: 'post' }],
    translationLevel: 'internationalizedArray',
  }),
],
```

Чтобы сочетать обе стратегии, установите `translationLevel` в `'mixed'` и перечислите типы документов с переводом на уровне полей в `fieldLevelDocuments`.

```ts
gtPlugin({
  sourceLocale: 'en',
  locales: ['es', 'zh', 'ja'],
  translateDocuments: [{ type: 'post' }, { type: 'siteSettings' }],
  internationalizedArray: { enabled: true },
  translationLevel: 'mixed',
  fieldLevelDocuments: [{ type: 'siteSettings' }],
});
```

Типы документов, локализуемые на месте, автоматически исключаются из `@sanity/document-internationalization`, поэтому для них не отображаются языковые бейджи и не создаются шаблоны документов для отдельных локалей. Во время импорта плагин обновляет только целевую локаль в исходном документе, сохраняя все остальные языки.

(См. [справочник по конфигурации плагина](/docs/integrations/sanity/reference/plugin-configuration#field-level), чтобы узнать обо всех параметрах на уровне полей).

## Исключить поля из перевода [#exclude-fields]

Пометьте поле в схеме, чтобы его содержимое не попадало в перевод. Укажите `options.gt.exclude` в определении поля.

```ts title="schema/article.ts"
defineField({
  name: 'internalNotes',
  type: 'string',
  options: { gt: { exclude: true } },
});
```

Исключённые поля никогда не отправляются на перевод, поэтому в переведённых документах исходное значение остаётся без изменений. Исключение действует на любом уровне вложенности.

Плагин также учитывает параметры исключения стандартных плагинов локализации Sanity, поэтому, если ваша схема уже их использует, вам не нужно добавлять вторую отметку:

* `options.documentInternationalization.exclude` из `@sanity/document-internationalization`
* `options.aiAssist.exclude` из `@sanity/assist`
* устаревшее свойство поля `localize: false`

Чтобы исключить все вхождения пользовательского типа, задайте этот параметр в определении самого типа.

```ts title="schema/objects/legalDisclaimer.ts"
export const legalDisclaimer = defineType({
  name: 'legalDisclaimer',
  type: 'object',
  // Исключает этот тип везде, где он используется
  options: { gt: { exclude: true } },
  fields: [
    defineField({ name: 'jurisdiction', type: 'string' }),
    defineField({ name: 'text', type: 'text' }),
  ],
});
```

Для правил, которые ориентируются на документы по ID или преобразуют значения для каждой локали — например, для устранения дубликатов slug, — используйте вместо этого параметры уровня плагина [`ignoreFields`, `skipFields`, and `dedupeFields`](/docs/integrations/sanity/reference/plugin-configuration#field-matchers).

## Настройка документов-синглтонов [#singletons]

Используйте `singletons` для документов, которые существуют в единственном экземпляре на сайте, например для настроек сайта или навигации. `singletonMapping` определяет, как ID переведённого документа-синглтона формируется на основе исходного ID и локали.

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

Если не указать `singletonMapping`, по умолчанию `sourceDocumentId` и `locale` сопоставляются со значением `` `${sourceDocumentId}-${locale}` `` (например, `siteSettings-es`).

## Хранение учётных данных [#store-credentials]

Плагин считывает ваш API-ключ и ID проекта из приватного документа Sanity, у которого `_id` совпадает с `secretsNamespace` (по умолчанию — `generaltranslation.secrets`). Создайте его с помощью разового скрипта.

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

const client = getCliClient({ apiVersion: '2025-09-15' });

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

```bash
GT_API_KEY=your-api-key GT_PROJECT_ID=your-project-id npx sanity exec populateSecrets.js --with-user-token
```

Поле `secret` используется как API-ключ, а поле `project` — как ID проекта. Чтобы считывать учетные данные из другого документа, укажите в `secretsNamespace` значение `_id` этого документа.

Вы также можете передать `apiKey` и `projectId` напрямую в `gtPlugin`, но рекомендуется использовать документ secrets, чтобы учетные данные не попадали в систему контроля версий. Если указаны оба варианта, во время выполнения приоритет имеет документ secrets.

Соглашение об использовании приватного документа предотвращает неаутентифицированные публичные запросы; оно не заменяет разрешения Sanity для аутентифицированных пользователей Studio. Ограничьте доступ к набору данных с помощью [ролевого управления доступом Sanity](https://www.sanity.io/docs/access-control) и удалите разовый скрипт после создания документа.

## Добавьте необязательную вкладку «Переводы» [#translations-tab]

Действие документа **Перевести** добавляется автоматически. Чтобы вкладка «Переводы» также отображалась в редакторе документа, добавьте `TranslationsTab` в `structureTool`.

```ts title="sanity.config.ts"
import { defineConfig } from 'sanity';
import { structureTool } from 'sanity/structure';
import { gtPlugin, TranslationsTab } from 'gt-sanity';

export default defineConfig({
  plugins: [
    structureTool({
      defaultDocumentNode: (S) =>
        S.document().views([
          S.view.form(),
          S.view.component(TranslationsTab).title('General Translation'),
        ]),
    }),
    gtPlugin({
      sourceLocale: 'en',
      locales: ['es', 'zh', 'ja'],
    }),
  ],
});
```

## Next steps

- /docs/integrations/sanity/guides/translating-content
- /docs/integrations/sanity/guides/managing-translations
- /docs/integrations/sanity/guides/querying-translations

## Sitemap

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