# General Translation Integrations: Configuración del plugin de Sanity URL: https://generaltranslation.com/es/docs/integrations/sanity/reference/plugin-configuration.mdx --- title: Configuración del plugin de Sanity description: Configura el plugin gt-sanity de General Translation para Sanity Studio. Referencia de la API de gtPlugin. --- Configura General Translation en Sanity Studio con la función `gtPlugin`. Pasa un único objeto de opciones. ```ts title="sanity.config.ts" import { gtPlugin } from 'gt-sanity'; gtPlugin({ sourceLocale: 'en', locales: ['es', 'fr'], translateDocuments: [{ type: 'article' }], }); ``` ## Opciones [#options] | Opción | Descripción | Tipo | Opcional | Predeterminado | | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -------- | --------------------------------------------------------------- | | [`sourceLocale`](#source-locale) | Código del idioma de origen, como `en`. | `string` | Sí | `defaultLocale`, luego el valor predeterminado de la biblioteca | | [`defaultLocale`](#default-locale) | Alias de `sourceLocale`, para expandir `gt.config.json`. | `string` | Sí | — | | [`locales`](#locales) | Códigos de configuración regional de destino. | `string[]` | No | — | | [`customMapping`](#custom-mapping) | Mapeos personalizados de códigos de configuración regional y anulaciones de propiedades. | [`CustomMapping`](/docs/platform/core/reference/types/custom-mapping) | Sí | — | | [`apiKey`](#api-key) | Clave API de General Translation. | `string` | Sí | Documento de secretos | | [`projectId`](#project-id) | ID del proyecto de General Translation. | `string` | Sí | Documento de secretos | | [`secretsNamespace`](#secrets-namespace) | `_id` del documento privado de credenciales. | `string` | Sí | `generaltranslation.secrets` | | [`languageField`](#language-field) | Campo del documento que almacena la configuración regional. | `string` | Sí | `language` | | [`translateDocuments`](#translate-documents) | Filtra qué documentos se pueden traducir. | `TranslateDocumentFilter[] \| string[]` | Sí | `[]` | | [`singletons`](#singletons) | ID de documentos tratados como singletons. | `string[]` | Sí | `[]` | | [`singletonMapping`](#singleton-mapping) | Asocia un ID de origen y una configuración regional con un ID de singleton traducido. | `(sourceDocumentId: string, locale: string) => string` | Sí | `` `${sourceDocumentId}-${locale}` `` | | [`showDocumentInternationalization`](#show-doc-i18n) | Agrega automáticamente `@sanity/document-internationalization`. | `boolean` | Sí | `true` | | [`internationalizedArray`](#internationalized-array) | Configura la localización a nivel de campo con listas internacionalizadas. | `GTFieldLevelLocalizationConfig` | Sí | — | | [`fieldLevelLocalization`](#field-level-localization) | Alias de `internationalizedArray`. | `GTFieldLevelLocalizationConfig` | Sí | — | | [`translationLevel`](#translation-level) | Elige la traducción a nivel de documento, a nivel de campo o mixta. | `'document' \| 'internationalizedArray' \| 'mixed'` | Sí | `'document'` | | [`fieldLevelDocuments`](#field-level-documents) | Tipos de documento que usan localización a nivel de campo en modo mixto. | `TranslateDocumentFilter[] \| string[]` | Sí | `[]` | | [`ignoreFields`](#ignore-fields) | Campos copiados del origen sin traducir. | `FieldMatcher[]` | Sí | `[]` | | [`dedupeFields`](#dedupe-fields) | Campos copiados del origen y convertidos en valores únicos por configuración regional. | `FieldMatcher[]` | Sí | `[]` | | [`skipFields`](#skip-fields) | Campos eliminados de los documentos traducidos. | `FieldMatcher[]` | Sí | `[]` | | [`additionalStopTypes`](#additional-stop-types) | Tipos de schema adicionales que se conservan sin traducir. | `string[]` | Sí | `[]` | | [`additionalSerializers`](#additional-serializers) | serializador HTML personalizados para marcas y tipos de bloque. | `Partial` | Sí | `{}` | | [`additionalDeserializers`](#additional-deserializers) | deserializador HTML personalizados. | `CustomDeserializers` | Sí | `{}` | | [`additionalBlockDeserializers`](#additional-block-deserializers) | Reglas personalizadas de deserialización de bloques de Portable Text. | `unknown[]` | Sí | `[]` | ## Opciones de configuración regional [#locale-options] ### `sourceLocale` [#source-locale] **Tipo** `string` · **Opcional** · **Predeterminado** `defaultLocale`, y luego el valor predeterminado de la biblioteca El código del idioma de origen, como `en`. El plugin determina la configuración regional de origen en este orden: `sourceLocale`, luego `defaultLocale` y, por último, el valor predeterminado de la biblioteca `generaltranslation`. ### `defaultLocale` [#default-locale] **Tipo** `string` · **Opcional** Alias de `sourceLocale`, que se acepta para que puedas pasar un `gt.config.json` directamente al plugin mediante spread. Si se establecen ambos, `sourceLocale` tiene prioridad. ```ts import gtConfig from './gt.config.json'; gtPlugin({ ...gtConfig }); ``` ### `locales` [#locales] **Tipo** `string[]` · **Obligatorio** Los códigos de configuración regional de destino para traducir, como `['es', 'fr', 'ja']`. ### `customMapping` [#custom-mapping] **Tipo** `CustomMapping` · **Opcional** Mapeos personalizados de códigos de configuración regional a nombres, o anulaciones de propiedades de la configuración regional. Se pasa a la biblioteca `generaltranslation`. Consulta [CustomMapping](/docs/platform/core/reference/types/custom-mapping). ## Credenciales [#credentials] De forma predeterminada, el plugin obtiene las credenciales de un documento privado de Sanity. Consulta [Guardar credenciales](/docs/integrations/sanity/guides/configuring-sanity#store-credentials). ### `apiKey` [#api-key] **Tipo** `string` · **Opcional** · **Predeterminado** tomado del documento de secretos Tu clave de API de General Translation. Si se configura, se pasa a la biblioteca al iniciarse. Si hay un documento de secretos, su campo `secret` tiene prioridad en tiempo de ejecución. Se recomienda usar el documento de secretos para que las claves no queden en el control de versiones. ### `projectId` [#project-id] **Tipo** `string` · **Opcional** · **Predeterminado** se lee del documento de secretos El ID del proyecto de tu proyecto de General Translation. Cuando hay un documento de secretos, su campo `project` tiene prioridad en tiempo de ejecución. ### `secretsNamespace` [#secrets-namespace] **Tipo** `string` · **Opcional** · **Valor predeterminado** `generaltranslation.secrets` El `_id` del documento privado de Sanity que contiene las credenciales. El plugin recupera este documento por `_id` y usa su campo `secret` como clave de API y su campo `project` como ID del proyecto. Un `.` al inicio del `_id` hace que el documento siga siendo privado, incluso en un conjunto de datos público. ```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, }); ``` ## Opciones del documento [#document-options] ### `languageField` [#language-field] **Tipo** `string` · **Opcional** · **Predeterminado** `language` El campo del documento que se usa para almacenar la configuración regional de cada documento. Agrega un campo con este nombre a cada tipo de documento traducible y consúltalo para recuperar una configuración regional específica. ### `translateDocuments` [#translate-documents] **Tipo** `TranslateDocumentFilter[] | string[]` · **Opcional** · **Predeterminado** `[]` Filtra qué documentos se pueden traducir. Acepta objetos de filtro o cadenas abreviadas con tipos. Cada entrada de cadena `'article'` se normaliza a `{ type: 'article' }`, y se descartan las entradas que no tengan `documentId` o `type`. ```ts gtPlugin({ sourceLocale: 'en', locales: ['es'], translateDocuments: [ { type: 'article' }, { documentId: 'homepage' }, 'page', // forma abreviada de { type: 'page' } ], }); ``` `TranslateDocumentFilter` tiene esta estructura: ```ts type TranslateDocumentFilter = { documentId?: string; // coincide con un documento específico por _id type?: string; // coincide con todos los documentos de un tipo de esquema }; ``` Las entradas de `type` también determinan qué tipos de esquema habilita [`showDocumentInternationalization`](#show-doc-i18n). ### `singletons` [#singletons] **Tipo** `string[]` · **Opcional** · **Predeterminado** `[]` IDs de documentos que se tratan como singletons, como la configuración del sitio o la navegación. Los IDs de sus documentos traducidos se derivan de [`singletonMapping`](#singleton-mapping). ### `singletonMapping` [#singleton-mapping] **Tipo** `(sourceDocumentId: string, locale: string) => string` · **Opcional** · **Predeterminado** `` `${sourceDocumentId}-${locale}` `` Asigna el ID del documento de origen de un singleton y una configuración regional al ID del documento del singleton traducido. El valor predeterminado es determinista, por lo que `siteSettings` pasa a ser `siteSettings-es` en español. ```ts gtPlugin({ sourceLocale: 'en', locales: ['es'], singletons: ['siteSettings'], singletonMapping: (sourceDocumentId, locale) => `${sourceDocumentId}_${locale}`, }); ``` ### `showDocumentInternationalization` [#show-doc-i18n] **Tipo** `boolean` · **Opcional** · **Predeterminado** `true` Cuando es `true`, el plugin añade `@sanity/document-internationalization` con insignias de idioma, un menú de traducción y plantillas de documentos para cada idioma. Usa las entradas `type` de [`translateDocuments`](#translate-documents) como tipos de esquema y `[sourceLocale, ...locales]` como idiomas admitidos, por lo que solo surte efecto cuando `translateDocuments` incluye tipos de documento. Los tipos de documento localizados en el mismo documento con listas internacionalizadas se excluyen automáticamente. Establécelo en `false` para gestionar la internacionalización por tu cuenta. ## Localización a nivel de campo [#field-level] La localización a nivel de campo almacena el valor de cada configuración regional en un único documento, como una lista internacionalizada. Los datos almacenados usan la misma estructura de elemento `{ _key, _type, language, value }` que `sanity-plugin-internationalized-array`, por lo que el contenido existente de `internationalized-array` no requiere migración. ### `internationalizedArray` [#internationalized-array] **Tipo** `GTFieldLevelLocalizationConfig` · **Opcional** Configura los tipos de esquema y los componentes de entrada de Studio que se utilizan para la localización a nivel de campo. La identidad de la configuración regional siempre se toma de `sourceLocale` y `locales`. ```ts type GTFieldLevelLocalizationConfig = { enabled?: boolean; // predeterminado: false fieldTypes?: FieldLevelFieldType[]; // predeterminado: ['string', 'text'] languageTitles?: Record; getLanguageTitle?: (locale: string) => string; typePrefix?: string; // predeterminado: 'internationalizedArray' includeCompatibilityTypes?: boolean; // predeterminado: true components?: { input?: ComponentType | false; item?: ComponentType | false; field?: ComponentType | false; }; }; type FieldLevelFieldType = | 'string' | 'text' | 'block' | { name: string; type: string; title?: string; of?: unknown[]; fields?: unknown[]; options?: Record; }; ``` Los atajos integrados de `fieldTypes` son `string`, `text` y `block` (Portable Text). Una entrada de objeto define un tipo generado personalizado. `getLanguageTitle` reemplaza `languageTitles` cuando ambos están configurados. Cada slot de `components` acepta un componente de Studio o `false` para usar el renderizado predeterminado de Sanity. ### `fieldLevelLocalization` [#field-level-localization] **Tipo** `GTFieldLevelLocalizationConfig` · **Opcional** Un alias descriptivo de [`internationalizedArray`](#internationalized-array). ### `translationLevel` [#translation-level] **Tipo** `'document' | 'internationalizedArray' | 'mixed'` · **Opcional** · **Por defecto** `'document'` Controla cómo se traducen los documentos que coinciden: * `'document'` crea un documento por configuración regional * `'internationalizedArray'` localiza los campos configurados en el mismo documento * `'mixed'` usa localización a nivel de campo para [`fieldLevelDocuments`](#field-level-documents) y localización a nivel de documento para todo lo demás ### `fieldLevelDocuments` [#field-level-documents] **Tipo** `TranslateDocumentFilter[] | string[]` · **Opcional** · **Predeterminado** `[]` Selecciona los tipos de documentos que usan listas internacionalizadas cuando `translationLevel` es `'mixed'`. Acepta las mismas formas de filtro y cadenas abreviadas que [`translateDocuments`](#translate-documents). ```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' }], }); ``` Luego, usa los tipos generados en tus schemas: ```ts defineField({ name: 'title', type: 'internationalizedArrayString', }); ``` ## Selectores de campos [#field-matchers] Cada uno de `ignoreFields`, `dedupeFields` y `skipFields` acepta una lista de objetos `FieldMatcher`. Un selector se aplica a campos mediante una expresión JSONPath en `property` y, opcionalmente, puede limitarse a un único documento de origen mediante `documentId`. ```ts type FieldMatcher = { documentId?: string | null; // restringir a un documento de origen por _id fields?: { property: string; // expresión JSONPath, como $.slug type?: string; // sugerencia de tipo de esquema opcional, como slug }[]; }; ``` ### `ignoreFields` [#ignore-fields] **Tipo** `FieldMatcher[]` · **Opcional** · **Predeterminado** `[]` Campos copiados del documento de origen al documento traducido sin enviarlos a la API de traducción. Úselo para valores que deben permanecer idénticos en todas las configuraciones regionales, como categorías o etiquetas. ```ts gtPlugin({ sourceLocale: 'en', locales: ['es'], ignoreFields: [ // Copiar categoría sin cambios para todos los documentos { fields: [{ property: '$.category' }] }, // Copiar etiquetas sin cambios solo para un documento { documentId: 'homepage', fields: [{ property: '$.tags' }] }, ], }); ``` ### `dedupeFields` [#dedupe-fields] **Tipo** `FieldMatcher[]` · **Opcional** · **Predeterminado** `[]` Campos copiados del valor de origen y convertidos en valores únicos al añadir la configuración regional cuando el documento traducido se crea por primera vez. Suele usarse para slugs. ```ts gtPlugin({ sourceLocale: 'en', locales: ['es', 'fr'], // "about" se convierte en "about-es" y "about-fr" dedupeFields: [{ fields: [{ property: '$.slug', type: 'slug' }] }], }); ``` En un campo slug, el plugin actualiza el valor `current` del objeto slug. Si más adelante un editor cambia el slug traducido, las importaciones futuras conservan ese valor editado. ### `skipFields` [#skip-fields] **Tipo** `FieldMatcher[]` · **Opcional** · **Predeterminado** `[]` Campos que se eliminan por completo de los documentos traducidos. ```ts gtPlugin({ sourceLocale: 'en', locales: ['es'], skipFields: [ { fields: [{ property: '$.slug', type: 'slug' }] }, { documentId: 'homepage', fields: [{ property: '$.debugInfo' }] }, ], }); ``` ## Serialización [#serialization] El plugin serializa los documentos a HTML para traducirlos y luego deserializa el resultado de nuevo en campos de Sanity. La mayoría de los proyectos no necesitan estas opciones. ### `additionalStopTypes` [#additional-stop-types] **Tipo** `string[]` · **Opcional** · **Predeterminado** `[]` Tipos de esquema adicionales que se conservarán sin traducir, añadidos a los [tipos de exclusión predeterminados](#stop-types). ```ts gtPlugin({ sourceLocale: 'en', locales: ['es'], additionalStopTypes: ['codeBlock', 'mux.video', 'mux.videoAsset'], }); ``` ### `additionalSerializers` [#additional-serializers] **Tipo** `Partial` · **Opcional** · **Predeterminado** `{}` Serializadores personalizados combinados con los predeterminados, siguiendo la estructura de componentes de `@portabletext/to-html` (`types`, `marks`, `block`, `list`, `listItem`, entre otros). Se usan principalmente para serializar `marks` personalizados. Para `marks` personalizados, envuelve la salida con `attachGTData` para que los datos de la marca se conserven durante la traducción. ```ts title="sanity.config.ts" import { attachGTData, gtPlugin } from 'gt-sanity'; gtPlugin({ sourceLocale: 'en', locales: ['es'], additionalSerializers: { marks: { link: ({ value, children }) => attachGTData(`${children}`, value, 'markDef'), inlineMath: ({ value, children }) => attachGTData(`${children}`, value, 'markDef'), }, }, }); ``` `attachGTData(html, data, 'markDef')` codifica `data` en base64 en un atributo `data-gt-internal` del primer elemento de `html` y devuelve el HTML actualizado. Al importarlo, el plugin lee ese atributo para reconstruir la definición de la marca. ```ts function attachGTData( html: string, data: Record, type: 'markDef' ): string; ``` ### `additionalDeserializers` [#additional-deserializers] **Tipo** `CustomDeserializers` · **Opcional** · **Predeterminado** `{}` Deserializadores personalizados que convierten elementos HTML traducidos nuevamente en objetos de Sanity, organizados por tipo. ```ts type CustomDeserializers = { types?: Record< string, (element: HTMLElement) => Record | unknown[] >; } & Record; ``` ### `additionalBlockDeserializers` [#additional-block-deserializers] **Tipo** `unknown[]` · **Opcional** · **Predeterminado** `[]` Reglas adicionales para deserializar bloques de Portable Text, que se añaden a las reglas integradas del plugin. Cada regla es un objeto con un método `deserialize(node, next)`, que sigue la estructura de regla de `@portabletext/block-tools`. ## Tipos de exclusión predeterminados [#stop-types] Estos tipos de esquema se conservan y nunca se envían a traducción. Añade más con [`additionalStopTypes`](#additional-stop-types). ```ts const defaultStopTypes = [ 'reference', 'date', 'datetime', 'file', 'geopoint', 'image', 'number', 'crop', 'hotspot', 'boolean', 'url', 'color', 'code', ]; ``` Los campos slug *no* se omiten de forma predeterminada, por lo que la cadena `current` de un slug se traduce a menos que uses [`dedupeFields`](#dedupe-fields) o [`skipFields`](#skip-fields). ## Funciones auxiliares exportadas [#helpers] `gt-sanity` también exporta bloques base para la serialización avanzada y nodos de documento personalizados. La mayoría de los proyectos no los necesitan. * `TranslationsTab` — el componente de pestaña del documento para `structureTool`. Consulta [Configurar Sanity](/docs/integrations/sanity/guides/configuring-sanity#translations-tab). * `attachGTData` / `detachGTData` — adjuntan y leen los datos de marca codificados que usan los serializadores personalizados. * `BaseDocumentSerializer`, `BaseDocumentDeserializer`, `BaseDocumentMerger` — las implementaciones predeterminadas para serializar, deserializar y fusionar. * `defaultStopTypes`, `customSerializers` — los tipos de exclusión predeterminados y el conjunto de serializadores. * `documentInternationalization` y sus tipos (`DocumentInternationalizationConfig`, `Language`, `Metadata`, `TranslationReference`) — se reexportan desde `@sanity/document-internationalization`. ## Ejemplo completo [#complete-example] ```ts title="sanity.config.ts" import { defineConfig } from 'sanity'; import { attachGTData, gtPlugin } from 'gt-sanity'; export default defineConfig({ plugins: [ gtPlugin({ // Obligatorio sourceLocale: 'en', locales: ['es', 'fr', 'de', 'ja'], // Documentos y campos languageField: 'language', translateDocuments: [{ type: 'article' }, { type: 'page' }], singletons: ['siteSettings', 'navigation'], singletonMapping: (id, locale) => `${id}_${locale}`, // Comportamiento de campos ignoreFields: [{ fields: [{ property: '$.category' }] }], dedupeFields: [{ fields: [{ property: '$.slug', type: 'slug' }] }], skipFields: [{ fields: [{ property: '$.internalNotes' }] }], // Serialización — solo si los valores predeterminados no cubren tu esquema additionalSerializers: { marks: { link: ({ value, children }) => attachGTData(`${children}`, value, 'markDef'), }, }, }), ], }); ```