Skip to main content

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:
//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

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

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:
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

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)
    Image
  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
    Image

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”)
    Image
  2. Click Preview to review translations
    Image
  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.