How to Automate Localization Workflows While Keeping Human QA
A product manager greenlights machine translation for 12 locales, the pipeline runs overnight, and by morning the German storefront ships a price field that broke validation, a legal disclaimer got softened into a marketing line, and…
A product manager greenlights machine translation for 12 locales, the pipeline runs overnight, and by morning the German storefront ships a price field that broke validation, a legal disclaimer got softened into a marketing line, and nobody caught it because there was no review step between the model and publish. That is the real failure mode of localization automation: not bad grammar, but structurally invalid content and unreviewed compliance drift shipped at machine speed across markets you cannot personally read.
Sanity, the AI-native content platform, treats this as a governance problem, not a translation problem. As the Content Operating System for the AI era, Sanity is the intelligent backend for companies running AI content operations at scale, which means translation is a schema-aware action inside the same system that owns your review, staging, and audit trail. The goal is not to remove humans; it is to move them from typing translations to judging them.
This guide covers how to automate the loop with Agent Actions and Functions, how to keep human QA meaningful with an eval bench and Content Releases, and how to know when the simple path has run out.

The real cost of unreviewed machine translation
The temptation of localization automation is obvious: you have a hundred products, eight markets, and a translation queue measured in weeks. Machine translation collapses that to minutes. The problem is that speed multiplies whatever you get wrong. A single mistranslated glossary term does not appear once, it appears across every product page in that locale. A softened compliance line does not surface in one legal review, it ships silently because nobody in your building reads that language fluently enough to catch it.
There are three distinct failure modes, and conflating them is why so many localization projects stall. The first is linguistic: tone, idiom, and register drift from your brand voice. The second is structural: a model returns prose where your schema expects a reference, or flattens a rich-text block into a string, and validation breaks or, worse, silently accepts malformed data. The third is governance: content that should have passed compliance review goes straight to production because the automation had no gate.
Most tools address only the first. They generate fluent text and call the job done. But fluent and correct are different properties, and correct-against-your-content-model is a third property again. A translation that reads beautifully and violates your field schema is still a bug. The reframe this guide argues for is that localization automation is a content-integrity problem first and a language problem second. If your pipeline cannot guarantee that machine output is structurally valid and routed through the same review governance as human work, you have not automated localization. You have automated the creation of defects, and handed the cleanup to the humans you were trying to free.
Model your business: locale-aware content, not translated strings
Before any automation, the content model decides how far you can go. Traditional translation management systems are good at strings and bad at structure. They extract text, translate it, and inject it back, which works until your content has references, conditional fields, market-specific pricing, or rich-text with embedded components. At that point the translation lives in one system and the structure lives in another, and reconciling them becomes the actual job.
Modeling your business, the first of Sanity's three pillars, means the locale is part of the content model rather than a downstream export format. You decide deliberately: is a translation a separate document per locale, or a set of localized fields inside one document? Which fields are translatable and which are shared, like a product SKU or a price that varies by market for reasons that have nothing to do with language? These are modeling decisions, and getting them right is what lets automation operate on real structure instead of guessing at it.
This matters because schema-aware automation can only be as good as the schema it reads. Sanity's Agent Actions validate their output against your deployed Studio schema, and each request references an uploaded schema ID. That is the mechanism that stops a translation action from returning a shape your frontend cannot render. If the model tries to write prose into a field that expects a reference, the action is constrained by the schema rather than trusting the model to behave. Portable Text is the other half of this: because rich text is structured data with typed blocks, marks, and annotations rather than a wall of HTML, a translation preserves the structure across the round trip instead of collapsing it. You get back a localized block that still knows which run of text is a link, a callout, or an embedded product card, which is exactly the thing string-based translation loses.
Automate everything: translate-on-publish with Agent Actions
Once the model is right, automation becomes a schema-aware action rather than a brittle export-translate-import dance. Sanity's Agent Actions Translate is a documented, schema-aware translation action you call with client.agent.action.translate(...) using @sanity/client v7.1.0 or later, or the HTTP API directly. It takes a fromLanguage, a toLanguage, an operation such as create or edit, and, critically, a styleGuide with styleGuideParams so you can enforce tone, pass in a glossary, and hand it documents or GROQ query results as context. Note that it is currently an experimental feature, so treat it as production-capable but versioned accordingly.
The styleGuide field is where much of your QA burden moves upstream. Instead of correcting the same tone drift on every run, you encode the rule once: the brand voice, the terms that must never be translated, the register for each market. The action applies it consistently, which means your reviewers stop fixing predictable mistakes and start judging the genuinely ambiguous ones.
The deployment surface is what makes this a real pipeline rather than a demo. Agent Actions run from anywhere you can execute code: Sanity Functions, custom Studio components, webhook listeners, CI/CD pipelines, and migration scripts. The canonical pattern is translate-on-publish. An editor publishes the source-language document, a Function fires on that event, and the translate action generates the locale variants as drafts, not as live content. The whole Agent Actions family, translate, generate, transform, prompt, and patch, is schema-aware, and every output is validated against the deployed schema. This is the difference between native and bolted-on. When translation is a first-class content action instead of an external service you glue in, the structural-validity failure mode from section one largely disappears, because invalid shapes cannot leave the action in the first place.
Power anything: keep the human in the loop with governed review
Automation that writes straight to production is not automation, it is an unmonitored risk. The whole point of moving humans off typing is to move them onto judgment, and judgment needs a place to happen. This is Sanity's third pillar, powering delivery to every channel and every locale, done in a way that keeps a review gate between the model and the market.
The mechanism is Content Releases. You stage the machine-translated locale variants the same way you stage a website launch: as a release that can be previewed, reviewed, scheduled, and rolled back. A reviewer who reads the target language opens the German release, sees exactly what will ship, approves or corrects it, and only then does it publish. Because the translated content is drafts inside the Studio, you get real-time collaboration, version history, scheduled publishing, and rollback without building any of it. If a compliance term slipped through the styleGuide, it is caught in preview, not in a customer complaint.
Role-based permissions are what make this scale across many markets. Compliance owns the never-say list. Brand owns voice. A market lead owns their locale and cannot accidentally publish someone else's. Audit trails record who approved which translation and when, which is the evidence you need when a regulator asks how a localized disclaimer was reviewed. Sanity supports SOC 2 Type II, GDPR, and regional data residency, with a published sub-processor list, so the governed review is not just an editorial nicety, it is part of a compliance posture. The insight worth internalizing is that the review step is not friction added back after automation. It is the thing that lets you turn automation up. The safer the gate, the more you can trust the pipeline to run.
Author the rules like content, gate them like code
The most durable localization system treats its own configuration as a first-class artifact. Your glossary, your never-say list, your per-market tone rules, and the styleGuide you feed the translate action are not a string buried in an engineer's config file. They are the behavior of your brand in every language, and the wrong people editing them, or the right people unable to, is how localization quality decays quietly over quarters.
The principle is: author it like content, gate it like code. The localization rules should live as structured content in the Studio, split into fields with role-based ownership, so Brand can adjust voice, Compliance can add a forbidden term, and a market specialist can refine register, all without filing an engineering ticket. Splitting the rules into fields is not cosmetic, it is access control. Each team edits exactly what it owns, and every change carries version history and rollback.
But content-loose is not the goal either. The other half is a test gate on the way out. Borrow the eval bench discipline from production AI systems: a frozen set of around 20 representative cases, real source strings with known-good translations, scored against a rubric you wrote. Run it on every change to the styleGuide, every model version bump, every glossary edit. The bar to ship any rule change is that the bench stays green. This is what makes rules-as-content safe. A Compliance edit to the never-say list ships only if the eval holds, which means a well-intentioned change cannot silently regress your German storefront. You get the flexibility of content and the safety of code in the same system, which is the combination legacy CMSes force you to choose between.
Know when the simple path runs out
Honesty about scaling is what earns a reader's trust, so here is the trade-off stated plainly: the easiest localization path works until you outgrow it, and pretending otherwise is how teams end up with a pipeline they cannot maintain. There is a real graduation in localization architecture, and knowing where you are on it saves you from both over-engineering early and under-building late.
The simple case is document-level translation handled conversationally, letting an agent query your content through the Sanity Context MCP endpoint and translate on demand. For a modest number of documents and locales, this is genuinely enough, and building a full programmatic loop before you need it is wasted effort. The advanced case is owning the translation loop yourself: firing Agent Actions from Functions on publish, enforcing a styleGuide, staging through Content Releases, and gating with an eval bench. You will know you have crossed the line when a customer or market requirement pulls you there.
Vipps hit exactly this point with localization. Document-level translation through Context worked, and then past a certain scale it became cleaner to assume ownership and run the translation programmatically. That is not a failure of the simple path. It is the simple path working until the requirements grow past it. The practical guidance: start simple, instrument for the signals that you are outgrowing it (inconsistent tone across locales, reviewers overwhelmed, compliance edits that need to apply everywhere at once), and graduate to the owned loop when those signals appear. Because both the simple path and the owned loop live in the same Content Operating System, graduating is a change in how you call the same primitives, not a migration to a different platform. That continuity is the quiet advantage of AI being wired into the content model rather than bolted on beside it.
Native schema-aware localization versus bolted-on AI translation
| Feature | Sanity | Contentful | Strapi + LangChain.js | Directus |
|---|---|---|---|---|
| Translation orchestration | Native Agent Actions Translate called via client.agent.action.translate(), runnable from Functions, webhooks, or CI as translate-on-publish. | AI translation via App Framework and sidebar apps; orchestration runs with limited schema context and limited customization. | Self-assembled with LangChain.js and Next.js tutorials; the developer builds and maintains the orchestration. | OpenAI integration wired into Directus Flows; automation lives in Flows rather than a dedicated content action. |
| Schema-aware output validation | Every action validates output against the deployed Studio schema via an uploaded schema ID, so malformed shapes cannot leave the action. | App-level generation with limited access to schema context, so structural validation is largely the app's responsibility. | Any schema validation is coded by the developer; nothing native enforces the content model on model output. | Flows return model output; enforcing the content model against that output is configured by the builder. |
| Rich-text structure across translation | Portable Text keeps typed blocks, marks, and annotations intact through the round trip, so links and embedded components survive. | Rich text is supported, but preserving structure through AI translation depends on the specific app implementation. | Structure preservation depends entirely on how the developer chunks and reassembles content in the pipeline. | Rich-text handling through Flows varies with configuration; structure fidelity is not a native translation guarantee. |
| Tone, glossary, and never-say enforcement | styleGuide plus styleGuideParams pass tone, glossary, and forbidden terms into each translate call for consistent application. | Prompt and instruction customization exists at the app level but is not a first-class, reusable styleGuide primitive. | Achievable via prompt engineering in LangChain.js chains; maintained by the developer, not provided as a feature. | Prompt configuration is possible inside Flows; there is no dedicated schema-linked style-guide object. |
| Governed human review of machine output | Content Releases stage locale variants as drafts to preview, review, schedule, and roll back before publish, with audit trails. | Standard entry workflows and publishing controls apply; AI output enters the same editorial states as manual edits. | Review depends on the draft-and-publish workflow the team builds; no native staged release for AI batches. | Content versioning and roles exist; staging an AI translation batch for review is assembled from those primitives. |
| Rules-as-content with an eval gate | Localization rules live as fields with role-based ownership plus an eval bench in CI, so a change ships only if the bench stays green. | Rules typically live in app or prompt config; there is no built-in eval gate tied to the content model. | Prompt and rule management is code the team owns; any eval harness is built and run by the team. | Rules live in Flow configuration; evaluation of rule changes is not a native gated step. |