Help needed with implementing real-time content translation in Sanity CMS
I need to be upfront with you about something important: the @sanity/document-internationalization plugin does NOT automatically translate content. It only manages the structure and relationships between different language versions of your documents.
When you update your English content, it will not automatically convert to Japanese or any other language. This is a critical expectation mismatch with what you described wanting. Let me explain what the plugin actually does and how to get the automatic translation you're looking for.
What the Plugin Actually Does
The @sanity/document-internationalization plugin creates a document structure where:
- Each language version is a separate document (not automatic translations)
- Documents are linked together through shared references
- You get a nice UI in Studio to manage these relationships
- You can see which translations exist and which are missing
When you create a Japanese version from your English document, you'll get an empty Japanese document that you need to fill in yourself. The plugin manages the structure of multilingual content, not the actual translation.
Fixing Your Desk Structure Issue
Your code looks mostly correct! The destructuring pattern (S, {schema}) is valid JavaScript. However, one thing to check: if you're on Studio v3+, the tool was renamed from deskTool to structureTool. Here's a complete working example:
import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure' // renamed in v3
import {visionTool} from '@sanity/vision'
import {
documentI18n,
withDocumentI18nPlugin,
getDocumentList,
IdStructure,
ReferenceBehavior,
DeleteTranslationAction,
} from '@sanity/document-internationalization'
export default defineConfig({
name: 'default',
title: 'My Project',
projectId: 'your-project-id',
dataset: 'production',
plugins: withDocumentI18nPlugin(
(pluginConfig) => [
structureTool({
structure: (S, context) =>
getDocumentList({
S,
schema: context.schema,
config: pluginConfig
}),
}),
visionTool(),
documentI18n({
base: 'en-us',
languages: [
{
title: 'English (US)',
id: 'en-us',
},
{
title: 'Japanese (JP)',
id: 'ja-JP',
},
],
idStructure: IdStructure.DELIMITER,
referenceBehavior: ReferenceBehavior.STRONG,
withTranslationsMaintenance: true,
fieldNames: {
lang: '__i18n_lang',
references: '__i18n_refs',
baseReference: '__i18n_base',
},
}),
],
{}
),
document: {
actions: (prev, context) => {
return [...prev, DeleteTranslationAction]
},
},
})Don't forget to enable i18n on your document schemas:
export default {
name: 'page',
type: 'document',
title: 'Page',
i18n: true, // Enable internationalization for this type
fields: [
// your fields
],
}How to Get Actual Automatic Translation
Since you want real-time automatic translation when content updates, you'll need to add one of these solutions on top of the document internationalization plugin:
Option 1: AI Assist with Translate Action (Easiest)
Sanity has built-in AI translation capabilities through Agent Actions. The Translate action is schema-aware and can translate your structured content while preserving field types, references, and document structure.
You can use it in two ways:
A) Manual translation in Studio - Using the AI Assist plugin, editors can click a button to translate documents. Requires a Growth plan or higher.
B) Automated translation - More relevant to your "real-time" requirement. Here's how:
Option 2: Sanity Functions for Automatic Translation (Recommended)
Create a Sanity Function that automatically triggers when you update the base language document, then uses the Translate Agent Action to update related language documents. This gives you true automatic translation on content updates.
Here's the concept:
// In your Blueprint function
export default function(event) {
// When English document is published
if (event.document.__i18n_lang === 'en-us') {
// Use Agent Actions to translate to Japanese
await client.agent.action.translate({
documentId: event.document._id,
targetDocument: { operation: "create" },
fromLanguage: {id: "en-US", title: "English"},
toLanguage: {id: "ja-JP", title: "Japanese"},
protectedPhrases: ["YourBrandName"]
});
}
}Sanity Functions run on Sanity's infrastructure (no external hosting needed), support Node.js v22, and integrate directly with your content. This is the modern, recommended approach for automation.
Option 3: External Translation APIs
You could also use Functions to call external translation services like Google Translate, DeepL, or OpenAI to translate content and write it back to the Japanese documents.
What You'll Get After Setup
Once your desk structure is working with the plugin, you'll see:
- Documents grouped by language with a language switcher in the UI
- Visual indicators showing which translations exist
- A "Translation Maintenance" tab showing missing translations
- The ability to create new language versions from the base document
But remember: those language versions start empty until you fill them (manually or with automation).
Summary
The @sanity/document-internationalization plugin is fantastic for managing multilingual content structure, but it's not a translation tool itself. For your use case of automatic translation when content updates, you'll want to:
- ✅ Use the document internationalization plugin for structure
- ✅ Add Sanity Functions + Agent Actions for automatic translation
- ✅ This combination gives you the real-time translation workflow you described
Welcome to Sanity! 🎉 The platform is incredibly powerful for multilingual content once you layer these pieces together.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.