How to Wire AI Translation Into a Multi-Locale Site
A product page ships a flawless English update.
A product page ships a flawless English update. Six hours later, the German locale still reads the old price, the French version dropped a hyperlink during translation, and the Japanese page rendered a wall of text where a structured spec table used to be. Nobody approved any of it, and nobody can say which machine-translated string is safe to publish. Multi-locale translation breaks not because the model is bad at French, but because the pipeline around it loses structure, loses the publish event, and loses the human review step.
Sanity is the AI CMS built to close those gaps. It is the Content Operating System for the AI era, the intelligent backend for companies running AI content operations at scale, which means translation is wired into the data model, the publish event, and the editorial review loop rather than bolted on as a sidebar widget. The difference shows up exactly where naive pipelines fail: structure survives, automation fires on publish, and machine output stays inside governance.
This guide walks the full path. We cover how to model locale-aware content, how to trigger translation on a publish event, why your translation tool must return schema-shaped data instead of prose, where to keep a human in the loop, and the honest point at which you graduate from managed translation to owning the agent loop yourself.
Why naive translation pipelines lose structure, not just words
The first failure mode in multi-locale work is almost never grammar. It is structure loss. A page is not a paragraph of text. It is a typed document: a hero with a heading and a CTA reference, a body of rich text with links and inline annotations, a spec table modeled as repeatable objects, a price stored as a number with a currency code. When a translation step flattens that document into one big string, sends the string to a model, and gets a string back, every structural boundary in the content is now the model's problem to reconstruct. Links get dropped. A reference to another document becomes literal English text. A bolded clause loses its mark. The structured table becomes prose.
This is why the load-bearing rule for AI translation is the same rule that governs every production agent: return structured, schema-shaped data, not a stream of text. A tool that returns prose forces the model to paraphrase, and paraphrasing is where facts go to die. The translation pipelines that work return responses the model can pass straight through into the correct typed fields. The ones that struggle hand back a wall of text and re-narrate it, badly, into whatever structure the developer guesses at downstream.
Sanity addresses this at the format layer. Portable Text represents rich text as structured blocks with marks, annotations, and references, so a translation step operates on a schema-aware object, not a flattened string. Links, formatting, and embedded references survive the round trip because they were never collapsed into text in the first place. The translated heading lands back in the heading field, the translated body lands back as Portable Text blocks, and the price stays a number. Structure preservation is not a post-processing cleanup task; it is a property of how the content was modeled.

Model your business: locale-aware content as the foundation
Before any model translates anything, you have a modeling decision that determines whether the whole pipeline is sane. This maps to the first Sanity pillar, model your business. The question is how locales relate to documents. Two patterns dominate. In a field-level approach, each translatable field holds a map of locale to value, so one document carries all languages. In a document-level approach, each locale is its own document linked by a shared translation reference. Field-level keeps everything in one place and is friendly to small sites; document-level scales better when locales diverge, have separate publishing schedules, or need independent review and permissions.
The enterprise consequence is that locale go-live is rarely uniform. Legal needs the German page reviewed by a regional team before launch. The Japanese market gets the feature two weeks later. A campaign goes live in five locales at midnight local time, not all at once. A field-level blob fights all of that, because everything shares one publish state. Document-per-locale lets each market move on its own clock while still tracing back to a single source of truth.
This is where being the Content Operating System rather than a headless content layer matters. Sanity does not make you pick its preferred shape and bend your workflow to it. You model locale the way your business actually operates, and the translation automation, the review routing, and the delivery layer all read from that same model. Content Lake holds one canonical graph of typed documents, and every locale, every channel, and every downstream consumer queries the same source. There is no separate translation database to keep in sync with the CMS, which is the silo that breaks freshness in bolted-on setups.
Automate everything: translate on the publish event with Functions
The second pillar, automate everything, is where the pipeline comes alive. The natural trigger for translation is the moment the source locale changes. An editor finishes the English page, hits publish, and that publish event should be the thing that fans the content out to every target locale. If translation is a manual button an editor remembers to press, you will ship stale locales. If it is a scheduled batch job, you will translate content that has not changed and miss content that did.
Sanity Functions are serverless content-automation hooks that bind an editorial event to a pipeline without standing up separate infrastructure. A translate-on-publish Function listens for the publish of a source document, calls the translation step, and writes the results back. The same hook pattern covers enrich-on-publish and moderate-on-publish, so translation is one member of a family of event-driven automations rather than a special-case integration. Because the Function runs against the content model, it knows which fields are translatable and which are not, so it does not waste a model call re-translating a SKU or a hex color.
The translation work itself runs on Agent Actions, the schema-aware APIs for generating, transforming, and translating content with LLMs, exposed over HTTP anywhere you can run code. Schema awareness is the whole point. Because Agent Actions are grounded in the schema, translations land back in the correct typed fields instead of arriving as a wall of text a developer has to re-parse. You describe the transform in terms of the document shape, and the result is a mutation that fits the model. Contrast this with hosting an AI app in a fixed sidebar slot or wiring an LLM call into a low-code flow: those run beside the content model, while Agent Actions run inside it.
Read, write, and composite tools in a translation pipeline
It helps to decompose a translation pipeline into the three categories of tools every production agent needs, because they have different blast radii and different auth boundaries. Read tools fetch the source-locale content: query the published English document, pull the fields marked translatable, look up any referenced documents that also need localizing. The auth boundary for reads usually rides on the user's session token, so the pipeline reads exactly what that editor can see, no more.
Write tools mutate the target-locale documents. This is the step that actually creates or updates the German, French, and Japanese versions, and it is the step you want behind the tightest controls, because a write tool that runs unattended is how unreviewed machine output reaches production. Keeping writes explicit and scoped, rather than letting a model freely mutate whatever it decides, is the difference between an automation you trust and one you disable after the first incident.
Composite tools wrap a multi-step workflow behind a single call. A translate, stage for review, and schedule go-live sequence maps to several backend operations, but you expose it as one composite tool so the model is not orchestrating the multi-step work itself. This keeps the model focused on the language task it is good at and keeps the orchestration in deterministic code you can test. The practical build order mirrors how production agents get shipped: start with a few read-only tools and no writes, write the system prompt somewhere a non-engineer can edit it, stand up trace logging, and ship to a dark URL. Then build an eval suite of representative translations scored by hand, hold the model constant, and iterate. Translation quality is an evaluation problem, not a vibe.
Power anything: governing machine translation before it goes live
The third pillar, power anything, serves every locale from one source of truth to any channel, but enterprise translation has a hard prerequisite first: no machine output publishes unreviewed. A model that confidently mistranslates a legal disclaimer or a pricing clause is a liability, not a productivity gain, and the entire value of wiring AI into the CMS evaporates if the result is a flood of unaccountable copy.
This is where governance running through the Studio and Content Releases earns its place in the pipeline. A translate-on-publish Function does not push the German page straight to production. It stages the translation, routes it for human review in the editorial loop, and lets a regional reviewer approve, edit, or reject before the locale go-live is scheduled. Content Releases let you bundle a set of translated documents, review them together, and schedule them to publish as a coordinated launch, which is exactly what a five-locale campaign needs. Inside the Studio, AI Assist gives editors in-context LLM helpers for the human-in-the-loop work, for example translating a page's headings into multiple locales or rewriting a translated block in a target voice, so the reviewer is augmenting rather than retyping.
The governance story is also a compliance story. Sanity carries SOC 2 Type II and GDPR, offers regional hosting and data residency, and publishes its sub-processor list, which matters when translated content includes regulated copy and when the markets you serve have their own data rules. The point is not that AI translates faster. The point is that it translates inside a reviewable, governed loop, so speed never comes at the cost of accountability.
When to graduate from managed translation to owning the loop
Most teams should start with the simplest thing that works. The simple case is document-level translation through a managed path: let the platform handle the retrieval, the transform, and the write-back, and keep your own code surface small. This is genuinely the right first move, and treating it as a stopgap is a mistake. It is the simple path working until you outgrow it.
You will know you have crossed the line when a customer requirement pulls you there. Vipps hit exactly this point with localization. You can do document-level translation through Sanity Context, but past a certain scale it is cleaner to assume ownership and translate programmatically: pull the initial context into your own system prompt, treat that prompt like a page builder with sections, references, and logic, and reach past the managed path when a specific requirement demands it. The graduation is not a failure of the simple approach. It is a signal that your localization needs have become specific enough that owning the agent loop pays for itself.
What makes this graduation safe in Sanity is that you are not migrating to a different system to do it. The content model, the publish event through Functions, and the governance through the Studio and Content Releases stay exactly where they are. You swap the translation step from a managed call to your own orchestrated loop while everything around it holds constant. That continuity is the dividend of treating the CMS as the protagonist: the LLM is one consumer of structured content, and you can change how that consumer works without re-platforming the content it reads from.
AI translation surfaces compared: native, bolted-on, or community-driven
| Feature | Sanity | Contentful | Strapi + LangChain.js | Directus |
|---|---|---|---|---|
| Translation API model | Native, schema-aware Agent Actions exposed over HTTP, so translations land back in the correct typed fields rather than as flat text. | App Framework hosts AI sidebar apps in predefined UI slots; capable and extensible, but not a schema-aware translation API you call from anywhere. | You wire orchestration yourself with LangChain.js and Next.js tutorials; flexible, but translation is glue code you own and maintain, not a native surface. | First-party OpenAI integration runs inside low-code Flows; approachable for non-developers, but surface-level actions that do not tap schema the way Agent Actions do. |
| Publish-event automation | Functions bind translate-on-publish to the editorial publish event server-side, with no separate infrastructure to stand up. | Webhooks plus App Framework can trigger flows; you assemble and host the automation logic around the editorial event yourself. | Lifecycle hooks plus your own job runner; doable, but you build and operate the event-to-translation plumbing end to end. | Flows can trigger on events and call OpenAI, which is convenient for simple steps but constrained by what the low-code flow exposes. |
| Structure preservation | Portable Text keeps blocks, marks, annotations, and references intact across translation, so links and embedded references survive the round trip. | Rich text travels through whatever the sidebar app sends; preserving structured marks and references is on the app you build. | Depends entirely on how your LangChain chain chunks and reassembles content; structure fidelity is your responsibility. | Flow steps pass field values to OpenAI; rich structure and references must be handled by the flow author. |
| Governance of machine output | The Studio plus Content Releases stage, review, and schedule translations, so machine output never publishes unreviewed and locales launch together. | Editorial workflows and roles exist; coordinating multi-locale review and scheduled launches is configured per workflow. | Draft and publish states plus review tooling are available, but you assemble multi-locale review and scheduling yourself. | Roles and revisions support review; coordinated multi-document locale launches are built from flows and permissions. |
| In-editor AI for reviewers | AI Assist offers in-Studio helpers like translating a page's headings into multiple locales or rewriting a block in a target voice. | Quick Start AI and Studio AI bring in-editor assistance through hosted apps in the fixed editorial UI. | No native in-editor AI; assistance comes from whatever frontend or admin extension you build. | AI Researcher and OpenAI extensions add in-app assistance, oriented around flow actions rather than schema-aware editing. |
| Scaling to owned agent loop | Start managed, then graduate to owning the loop programmatically (the Vipps localization path) without changing model, publish event, or governance. | Scaling beyond sidebar apps means building a separate orchestration layer alongside the platform. | Already self-owned, which is the point and the cost: you carry the orchestration and its maintenance from day one. | Heavier or programmatic translation generally moves outside Flows into custom services you operate. |