> ## Documentation Index
> Fetch the complete documentation index at: https://support.lilt.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sanity

> Connect Sanity to Lilt for seamless, AI-driven translations.

## Overview

The LILT Sanity Connector streamlines the localization of your Sanity CMS content. By integrating directly with your Sanity Studio, you can request translations for your documents and receive translated content back without leaving your CMS. The connector is a Sanity Studio v3 plugin. The connector can support complex content models including nested and embedded content, and both instant (AI-only) and verified (human-reviewed) translation workflows.

## Prerequisites

* Sanity Studio v3 project
* Node.js >= 18
* A Sanity API token with **read + write** permissions (created in Sanity management console > API settings)

## Setup

### Step 1: Install dependencies

### 1a. Configure npm for LILT packages

Add to `.npmrc` in the project root:

```text theme={null}
//npm.pkg.github.com/:_authToken=<GITHUB_TOKEN>
@lilt:registry=https://npm.pkg.github.com
always-auth=true
```

The GitHub token needs `read:packages` scope. LILT will provide this or the customer can generate one with access to the LILT org.

### 1b. Install packages

```bash theme={null}
npm install @lilt/sanity-plugin @sanity/document-internationalization
```

### Step 2: Add language field to translatable schema types

Every document type that should be translatable **must** have a hidden `language` field. Without it, the connector cannot see the document.

## Overview

```tsx theme={null}
import {defineField} from 'sanity'

// Add this field to each translatable document type
defineField({
  name: 'language',
  type: 'string',
  readOnly: true,
  hidden: true,
})
```

Example in a full schema type:

```tsx theme={null}
export default defineType({
  name: 'blogPost',
  title: 'Blog Post',
  type: 'document',
  fields: [
    defineField({
      name: 'language',
      type: 'string',
      readOnly: true,
      hidden: true,
    }),
    defineField({name: 'title', type: 'string', title: 'Title'}),
    defineField({name: 'body', type: 'array', title: 'Body', of: [{type: 'block'}]}),
    // ... other fields
  ],
})
```

**Types that should NOT have the language field** (and will not be translatable):

* Tag or category types used only for internal classification (e.g., ArticleTag, CaseStudyTag)
* Script or code embed types
* Types that only contain references, images, or non-text configuration

### Step 3: Configure plugins in sanity.config.ts

```tsx theme={null}
import {defineConfig} from 'sanity'
import {liltPlugin} from '@lilt/sanity-plugin'
import {documentInternationalization} from '@sanity/document-internationalization'

export default defineConfig({
  // ... existing config (projectId, dataset, etc.)

  plugins: [
    // 1. Document internationalization (manages language variants)
    documentInternationalization({
      supportedLanguages: [
        {id: 'en', title: 'English'},
        {id: 'es', title: 'Spanish'},
        {id: 'de', title: 'German'},
        // Add all target languages here
      ],
      schemaTypes: [
        'blogPost',
        'page',
        // List every translatable document type name
      ],
    }),

    // 2. Lilt translation plugin
    liltPlugin({
      languageField: 'language',
      connectorUrl: '<PROVIDED_BY_LILT>',    // Lilt connector backend URL
      pluginApiUrl: '<PROVIDED_BY_LILT>',    // Lilt Plugin API URL
    }),

    // ... other plugins (deskTool, etc.)
  ],
})
```

LILT will provide the `connectorUrl` and `pluginApiUrl` values during onboarding. These are environment-specific.

### Step 4: Deploy and verify

1. Deploy the updated Sanity Studio
2. Open Sanity Studio in a browser
3. Click the LILT tab in the top navigation bar
4. Authenticate with the connector token (provided by LILT during onboarding)
   <Frame>
     <img src="https://mintcdn.com/lilt-db26f913/DHG6UTz_aQQzIjK2/images/image-76.png?fit=max&auto=format&n=DHG6UTz_aQQzIjK2&q=85&s=68a02e108460d276176bcea2d99415f8" alt="Image" width="5118" height="1798" data-path="images/image-76.png" />
   </Frame>
5. Verify translatable document types appear in the resource type dropdown
6. Verify documents load in the list view

## How Translation Works

### Browsing and selecting content

The LILT plugin provides a resource browser within Sanity Studio for selecting content to translate.

**Resource type filtering:** Use the resource type dropdown to filter by content type (e.g., Pages, Blog Posts). Document types appear with names based on their schema type.

**Search:** Use the search field to find specific documents by name within a selected resource type.

**Pagination:** For resource types with many documents, navigate through paginated results. Selections persist across pages when using bulk selection.

> **Note:** Only published documents appear in the connector. Draft-state documents are not shown.

### Creating a translation job

1. In the LILT tab, click **Translate**
2. Select your translation type:
   * **Instant** — translation with AI and no human intervention, delivered automatically
   * **Verified** — translated and then reviewed in the LILT platform
3. Choose source and target languages
4. Select documents from the resource browser
5. Click **Submit for translation**
   <Frame>
     <img src="https://mintcdn.com/lilt-db26f913/DHG6UTz_aQQzIjK2/images/image-77.png?fit=max&auto=format&n=DHG6UTz_aQQzIjK2&q=85&s=9dabf229d7bdf482b3f7e7cc09c4de19" alt="Image" width="5090" height="2266" data-path="images/image-77.png" />
   </Frame>

### Tracking translation status

After submission, jobs progress through the following stages: **Draft → Submitted → In-progress → Complete**.

**Instant translations** are processed automatically and delivered back to Sanity once complete. No further action is required after submission — simply wait for the job status to reach “Complete,” then import.

**Verified translations** are sent to the LILT platform for human review. In most configurations, this will be completely managed by the LILT team. Once the LILT expert completes their review, the translated content is delivered back and the job status will update to “Complete.”

### Importing translations

1. In the **Orders** tab, find a completed job (status: “Delivered”)
   <Frame>
     <img src="https://mintcdn.com/lilt-db26f913/DHG6UTz_aQQzIjK2/images/image-78.png?fit=max&auto=format&n=DHG6UTz_aQQzIjK2&q=85&s=1dca1baa8a12726ce69aa91869323912" alt="Image" width="5130" height="1506" data-path="images/image-78.png" />
   </Frame>
2. Click **Preview** to review translations
   <Frame>
     <img src="https://mintcdn.com/lilt-db26f913/DHG6UTz_aQQzIjK2/images/image-79.png?fit=max&auto=format&n=DHG6UTz_aQQzIjK2&q=85&s=41fcca3c8ea391230726c0cdda2f22a9" alt="Image" width="5124" height="1350" data-path="images/image-79.png" />
   </Frame>
3. Click **Import** to create translated variants in Sanity

### What happens after import

* A new **draft variant document** is created for each target language
* The source document is **never modified**
* Translated variants appear in the document’s **Translations** panel (language picker)
* Variants are created as **drafts** by default and must be manually published in Sanity Studio
* The document slug receives a language suffix (e.g., `my-page` becomes `my-page-de`)
* A **Translation Metadata** section becomes visible on translated documents in the Sanity Studio sidebar, showing translation status and links between source and translated variants

### Re-translating content

Submitting the same document for the same target language again will **overwrite** the existing translation variant. No duplicates are created.

## Troubleshooting

### “I can’t see my document type in the resource dropdown”

The document type is likely missing the `language` field. Add it to the schema and redeploy. Additionally, non-translatable types (such as tag or category types) are intentionally excluded from the dropdown.

### “I can’t find a specific document in the list”

* The document may be in **draft state**. Only published documents appear in the connector.
* Try using the search field to narrow the results.

### “Translation is missing some fields”

All string and text fields are extracted by default. If specific fields should not be translated (such as slugs, image references, or display settings), ask your LILT contact to configure DNT (Do Not Translate) filters. Conversely, if fields you expected to be translated are missing, contact your LILT representative to review the content extraction configuration.

### “Where are my translated documents?”

After import, translations appear as draft documents. Look for them in:

1. The **Translations** panel on the source document (language picker)
2. The document list, filtered to the target language
3. Under **Translation Metadata** in the Sanity Studio sidebar

### “How do I delete a translation?”

Navigate to the **Translation Metadata** section in the Sanity Studio sidebar for the translated document. From there you can delete the translation metadata entry. Note that this removes the link between the source and translated variant — the translated document itself may need to be deleted separately.

### “My nested content wasn’t translated”

Check with your support team to see if your connector setup supports translating nested entries or not. This setting to translate nested entries can be configured by the LILT Team using the field `sanity_include_nested_content`.

### “My job is stuck or shows an error”

If a job remains in “In-progress” for an unexpectedly long time or you see an error during import, try the following:

* **Refresh the page** and check the job status again in the **Orders** tab. Temporary connection issues can sometimes cause the status to appear stale.
* **Re-submit the job** if the status has not progressed. Submitting the same document again will not create duplicates — it will update the existing translation.

## What LILT Configures

These are handled by the LILT team during onboarding:

* Connector creation and API credentials
* Translation memory and model configuration
* Workflow configuration (instant vs. verified)
* Content filters (DNT rules for non-translatable fields such as slugs, images, and display settings)
* Resource type visibility and excluded types
* Whether nested entries are included for translation or not.
