# sanity: Configuration
URL: https://generaltranslation.com/en-US/docs/sanity/guides/configuration.mdx
---
title: Configuration
description: Configure the gt-sanity plugin for your Sanity project
---
## Overview
The `gtPlugin` function accepts a configuration object to customize translation behavior, locale settings, and document handling.
```typescript title="sanity.config.ts"
import { gtPlugin } from 'gt-sanity';
export default defineConfig({
plugins: [
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'], // Replace with your target locales
languageField: 'language',
singletons: ['siteSettings', 'navigation'],
}),
],
});
```
## Basic configuration
### Source and target locales
Define your source language and target locales:
```typescript
gtPlugin({
sourceLocale: 'en', // Source language for content
locales: ['es', 'zh', 'ja'], // Target languages for translation
});
```
### Using `defaultLocale` from `gt.config.json`
If you already have a `gt.config.json` (e.g. from using `gt-next` or `gt-react`), you can spread it directly into the plugin config. The `defaultLocale` field is accepted as an alias for `sourceLocale`:
```typescript
import gtConfig from './gt.config.json';
gtPlugin({
...gtConfig, // { defaultLocale: 'en', locales: ['es', 'zh', 'ja'] }
});
```
If both `sourceLocale` and `defaultLocale` are provided, `sourceLocale` takes precedence.
### Language field
Specify which field stores the document's locale. Defaults to `'language'`:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
languageField: 'locale', // By default, documents use 'language' field. Here we use 'locale' instead.
});
```
## Document filtering
### Translate specific document types
Limit translation to specific document types:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
translateDocuments: [{ type: 'page' }, { type: 'post' }],
});
```
### Translate specific documents
Target specific document IDs:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
translateDocuments: [
{ documentId: 'homepage' },
{ documentId: 'about-page' },
],
});
```
## Singleton documents
Singletons are Sanity documents that exist as a single instance with translated variants. Configure how translated versions are named:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
singletons: ['siteSettings', 'navigation', 'footer'], // List of singleton document IDs
singletonMapping: (docId, locale) => `${docId}-${locale}`, // Optional function to customize the ids of the translated singleton documents
});
```
By default, translations for singletons will have randomly generated ids unless `singletonMapping` is provided.
## Ignoring fields
Fields you don't want translated or sent to the GT API, but that should still be copied over from the source document to the translation. Ignored fields are stripped before serialization (so the content is never sent to the API), then restored from the source document after the translated document is created.
Use `ignoreFields` for fields like categories, tags, or internal metadata that should have the same value on both the source and translated documents but don't need translation:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
ignoreFields: [
{ fields: [{ property: '$.category' }] }, // same category across all languages
{ fields: [{ property: '$..linkType' }] }, // internal link metadata
{ fields: [{ property: '$..frequencies.default' }] },
],
});
```
`property` is a [JSONPath](https://goessner.net/articles/JsonPath/) expression that matches one or more fields in documents.
`type` is an optional parameter to further filter the fields to ignore to specific types.
## Deduplicating fields
Fields you don't want translated or sent to the GT API, but that should still be copied from the source document and made unique when a translated document is first created. Dedupe fields are stripped before serialization, then restored from the source document with the target locale appended.
Use `dedupeFields` for Sanity slugs or other string-like identifiers that should stay based on the source value but must be unique per language:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
dedupeFields: [
{ fields: [{ property: '$.slug', type: 'slug' }] }, // "about" becomes "about-es"
],
});
```
For Sanity slug fields, the plugin updates the slug object's `current` value. For example, `{ _type: 'slug', current: 'about' }` becomes `{ _type: 'slug', current: 'about-es' }` when the Spanish document is created. If an editor later changes the translated slug, future translation imports preserve that edited value.
## Skipping fields
Fields that shouldn't be automatically copied over to translated documents at all. Unlike `ignoreFields` (which preserves the source value on the translation), `skipFields` removes the matched fields entirely from the translated document.
Use `skipFields` for fields like SEO canonical URLs, source-only metadata, or slugs that editors should set manually per language:
```typescript
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
skipFields: [
{ fields: [{ property: '$.slug', type: 'slug' }] }, // editors set slugs manually per language
{ fields: [{ property: '$.canonicalUrl' }] }, // only relevant on source
{
documentId: 'homepage',
fields: [{ property: '$.debugInfo' }], // source-only debug data
},
],
});
```
## Serialization options
Extend the default serialization behavior:
```typescript
import { attachGTData, gtPlugin } from 'gt-sanity';
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'zh', 'ja'],
additionalSerializers: {
// Additional serializers for marks (custom annotations)
marks: {
link: ({ value, children }) =>
attachGTData(`${children}`, value, 'markDef'),
inlineMath: ({ value, children }) =>
attachGTData(`${children}`, value, 'markDef'),
},
},
});
```
See the [Serialization Guide](/docs/sanity/guides/serialization) for details.
## Complete example
```typescript title="sanity.config.ts"
import { defineConfig } from 'sanity';
import { gtPlugin } from 'gt-sanity';
export default defineConfig({
name: 'default',
title: 'My Project',
projectId: 'your-project-id',
dataset: 'production',
plugins: [
gtPlugin({
sourceLocale: 'en',
locales: ['es', 'fr', 'de', 'ja', 'zh'],
languageField: 'language',
singletons: ['siteSettings', 'navigation'],
translateDocuments: [{ type: 'article' }, { type: 'page' }],
ignoreFields: [
{
fields: [{ property: '$.publishedAt' }],
},
],
dedupeFields: [
{
fields: [{ property: '$.slug', type: 'slug' }],
},
],
skipFields: [
{
fields: [{ property: '$.internalNotes' }],
},
],
}),
],
schema: {
types: schemaTypes,
},
});
```
## Next steps
- [Serialization Guide](/docs/sanity/guides/serialization) - Custom serialization rules
- [API Reference](/docs/sanity/api/plugin-config) - Full configuration options