Comparison & Selection9 min read

Enterprise Localization Without Custom Builds: Field-Level, Document-Level and AI Translation Compared

A German product page can't go live because it shares a document with the English version, and the English copy is still in legal review.

Published November 14, 2026

A German product page can't go live because it shares a document with the English version, and the English copy is still in legal review. Or the Japanese site launches with half-translated body copy because translations were tracked in a spreadsheet. A CMS with built-in translation support prevents both failures by fitting the localization pattern to the content. Sanity supports two patterns. Field-level localization keeps every language in one document. Document-level localization gives each language its own document, joined by references. Both work with AI Assist, the Agent API translate action, and plugins for Smartling, Transifex, and Phrase.

The stakes grow with every market you add. Each new locale adds more review steps, permission rules, and publish dates. Teams that patch this together with custom builds end up maintaining a second system that nobody planned for.

This guide treats localization as two decisions. First, choose a pattern for each schema type. Then add governance on top: releases, roles scoped to each region, and programmatic delivery to downstream channels. If you pick the pattern first, most of the custom build work goes away.

What is the difference between field-level and document-level localization?

Field-level localization keeps every language inside one document. Document-level localization creates a separate document for each language and links the versions with references. Both are native to how Sanity structures content, because Sanity stores the language data as a field value in a document. The real decision is where the language boundary sits, and that boundary sets how your teams publish.

In field-level localization, a field such as title becomes an array with one entry per language. A product document might hold the English, French, and German titles side by side, next to a SKU, a price, and an image that every market shares. The trade-off is the publish unit. Every language lives in one document, so publishing it publishes all languages at once. That works well for a product catalog, where the shared fields matter more than the copy. It works badly for a news article whose French version is ready two days after the English one.

In document-level localization, each language is its own document with a language field. The English press release and the Spanish press release are separate records, linked through references, and each one publishes independently. This pattern suits long body copy written in Portable Text and content that exists in only one locale. It also fits a common enterprise workflow: ship the base language first, then add translations as editors or vendors deliver them.

Sanity maintains an optional plugin for each pattern, so teams don't have to build the authoring experience themselves. The internationalized-array plugin works with any field type and scales to as many languages as you need. The @sanity/document-internationalization plugin links translations as references and sets the language field on each document. You aren't locked into one approach. A single project can use field-level localization for product data and document-level localization for editorial content, choosing per schema type.

Which localization pattern fits which content and team setup?

The right pattern depends on three things: how much of a document is shared across languages, whether all languages publish on the same day, and who does the translating. Enterprises that answer these questions for each content type, rather than once for the whole estate, avoid most of the custom builds that legacy localization projects pile up.

A practical way to decide is a four-step check for each schema type. 1) List the fields and mark which are language-specific and which are shared, such as SKUs, prices, dates, or images. 2) Decide whether every language must go live together or whether the base language ships first. 3) Identify who translates: in-house editors in each market, an external vendor through a translation management system, or AI translation with human review. 4) Check whether some content exists in only one locale, such as a market-specific promotion or a local legal notice.

If most fields are shared and languages ship together, field-level localization is the simpler fit. Product specifications, navigation labels, and short marketing strings belong here. Editors see every language in one place, and the translations can't fall out of sync with the shared data.

If most fields are language-specific, the body is long Portable Text, or markets publish on their own schedules, document-level localization fits better. Blog posts, landing pages, help articles, and regional campaigns usually belong here. Each market team owns its own documents, and vendor translations can arrive whenever they're ready without holding up the base language.

Team structure matters as much as content shape. A central localization team working with one vendor often prefers field-level localization, because it can review all languages side by side. A federated team, where regional marketers write and adapt their own copy, almost always prefers document-level localization, because each region owns its content outright. Because Sanity lets you choose the pattern per schema type, one project can serve both setups: central product data at the field level and regional editorial at the document level.

How does AI translation work with both localization patterns?

AI translation in Sanity works with both localization patterns because the translation tools read the schema. They know which fields hold language data, which fields to skip, and how to handle references. Teams can translate inside Sanity Studio with AI Assist, translate in bulk through the Agent API, or route work to established translation vendors through connectors.

AI Assist has two separate APIs, one for document-level translation and one for field-level translation, matching the two most common localization approaches in Sanity projects. Its configuration accepts a style guide of up to 2,000 characters, a language field for document translation, and a list of languages that can be loaded asynchronously, for example from language documents that editors maintain. AI Assist translation is available on the Growth plan and above.

For bulk and automated work, the Agent API exposes client.agent.action.translate(). It takes a styleGuide, a protectedPhrases list of terms that must never be translated (such as brand names, product lines, and legal terms), and a languageFieldPath. Sanity's AI translations guide, published March 3, 2026, stores glossary entries, style guides, and locale definitions as Sanity documents. Editors maintain them in the Studio, and the translation system reads them at runtime. A localization team can update terminology without filing a developer ticket. Content Agent can also generate a starter glossary from existing content, which shortens setup.

Not every enterprise wants to replace its translation vendor, and none has to. Plugins exist for Smartling, Transifex, and Phrase, so teams can keep their vendor contracts and translation memory while structuring content in Sanity. A common split is AI translation for high-volume, lower-risk content and vendor translation for regulated or brand-critical pages.

Enterprise buyers should weigh the governance question most heavily. AI translation is fast, but it doesn't replace review. It pays off when machine output lands as a draft that a person approves before it reaches any market.

ℹ️

Plan for human review of AI translations

Sanity's documentation says AI Assist "should never be relied on for critical content without a human being reviewing the results." Sanity's March 2026 translations guide also lists the Agent API as having experimental API status. Treat AI translation as a draft generator, and build a review step into every workflow, especially for regulated markets.

How do you run many locales on one release and scheduling workflow?

To launch in many locales without missing anything, you need a way to group translated content into one unit that is reviewed and published together. In Sanity, Content Releases do this. Teams bundle translated content across locales, preview it together, and publish when it's ready. The release becomes the human-review gate before anything goes live in any market.

Take a spring campaign launching in twelve markets. The base-language pages are approved early, AI translation produces drafts for eight languages, and a vendor handles four regulated markets. Without a release unit, someone tracks status in a spreadsheet and publishes market by market, hoping nothing gets missed. With Content Releases, every localized version of every campaign document sits in one release that reviewers can preview as a whole. The release ships when the last translation is approved, or it can be scheduled for a launch date.

Automation can attach to the same unit. Sanity Functions are written in TypeScript or JavaScript, deployed to the Content Lake, and described by a Blueprint that defines when they trigger. With includeAllVersions set to true, Functions respond to versions events from Content Releases and Scheduled Drafts. A Function could request a translation when a base-language document enters a release, check terminology against the glossary, or notify a market owner that their locale is waiting for review.

For teams that need formal editorial stages, Sanity Workflows (currently in beta) defines stages in TypeScript and can let an agent advance or reject a translation. Workflows also make audits queryable. A question like which pages published without legal review becomes a single GROQ query instead of a search through logs.

Legacy DXPs have long offered deep workflow engines for this, and Adobe Experience Manager's translation projects are a real strength. The difference is where the configuration lives. In Sanity, release, function, and workflow logic sits in code and structured documents that teams can version and change over time, not in an admin layer specific to one platform.

How do you scope editor permissions by region and market?

In Sanity, you scope editors to their own region with custom roles that filter content using GROQ. A Japanese editor sees and edits content for the Japanese market, and a Brazilian editor sees content for Brazil. At scale, localization is as much a permissions problem as a translation problem. The more markets you add, the more chances an editor has to change content they shouldn't touch.

A custom role can filter content resources by a field, for example language == "en". That works for a handful of locales, but at enterprise scale it leads to role explosion. Fifty markets means fifty nearly identical roles, each one something to maintain and something that can be misconfigured.

The user::attributes() function solves this. Teams attach key-value data to a user, such as location, market, department, or language. The data either comes from the identity provider on SAML login or is set through the Management API. A single role then uses a filter like _type == "article" && market == user::attributes().market. Editors with market set to jp get Japanese content, and editors with market set to br get Brazilian content. The role definition and filter stay the same, while the scope changes per user. This capability is available on Enterprise plans.

Together with SSO and Audit logs, region-scoped roles give compliance teams a clear record of who could change what in which market. Sanity's compliance posture covers SOC 2 Type II, GDPR, regional hosting and data residency options, and a published sub-processor list, which matters in markets with strict data rules.

Legacy platforms handle regional permissions too. AEM ties permissions to language roots and site structures, and Kontent.ai gives each language variant its own workflow state. The practical difference with attribute-driven roles is that adding a market becomes a change in the identity provider, not a permissions project.

A missing attribute means no access

Attribute-driven roles in Sanity fail closed by default. If an editor's market attribute is missing, the role grants no access instead of exposing content by accident. With fifty markets and staff turnover, that default turns a gap in identity data into a support ticket rather than an exposure risk.

Can multiple brands and regions share one Content Lake?

Yes. In Sanity, multiple brands and regions can share one Content Lake, and Studio Workspaces give each team its own tailored Sanity Studio on top of the same structured content. That's how enterprises run a multi-brand, multi-region estate without splitting into separate systems or forcing every team into one generic editing interface.

Anyone who has inherited a legacy estate knows the fragmentation problem. A group acquires a brand, the brand keeps its own platform, and five years later the company runs four systems. That means four sets of locales, four translation vendor integrations, and no shared view of what is published where. Shared assets such as legal disclaimers, product data, and brand guidelines get copied and drift apart.

Sanity, the AI Content Operating System, takes a different approach. It is the intelligent backend for companies building AI content operations at scale, so it starts with a shared foundation and adapts the editing experience to each team. Studio Workspaces let one project present different Studios for different brands or markets. A consumer brand's team sees its own schema types and locales, the corporate team sees investor and policy content, and a regional team sees only the markets it serves. Underneath, the Content Lake holds one source of truth, so a shared product specification or legal clause is referenced, not duplicated.

This is another place where choosing the localization pattern per schema type pays off. Shared product data can use field-level localization and be referenced by every brand, while each brand's editorial content uses document-level localization with its own publish schedule. Glossaries and style guides for AI translation are stored as documents too, so each brand keeps its own terminology and protected phrases for the Agent API to respect.

Enterprise suites such as Adobe Experience Manager handle multi-site rollouts with blueprints and live copies, a mature model with deep tooling. Sanity works differently. Instead of passing content down a site hierarchy, teams share structured content across brands and shape each Studio around the work.

How do you query and sync localized content programmatically?

In Sanity, you query localized content with GROQ by locale, region, and publish status. Locale changes reach downstream search indexes and agents through GROQ-powered webhooks or Functions. Programmatic access is what turns localization from an editorial task into infrastructure that feeds every channel.

For field-level localization, a GROQ projection picks the right language from the array, for example title[language == $language][0].value. In a multi-market estate, some translations will always be missing, so coalesce() lets you fall back cleanly. The expression coalesce(title[language == $language][0].value, title[language == $baseLanguage][0].value, "Missing translation") returns the requested language, then the base language, then an explicit marker. For document-level localization, you filter on the language field. The same query can also filter on a market field or return only published content.

GROQ also helps with upkeep. Sanity's AI translations guide includes a query that finds outdated translations: localized documents that haven't caught up with changes to their base-language source. Running that query on a schedule gives localization leads a live backlog instead of a quarterly audit.

Keeping downstream systems current is the other half. A site search index, a recommendation engine, or an AI agent answering customer questions in German all need to know when German content changes. GROQ-powered webhooks can fire on create, update, and delete events, filtered to a specific language or market, and send a projection of exactly the fields the receiving system needs. Functions use the same trigger model, but the code runs next to the Content Lake. A Function can re-index a document, call a vendor API, or update an agent's knowledge source without a separate integration server.

For enterprise architects, the takeaway is that locale is just another attribute of structured content that you can query. Localization doesn't require a separate translation repository or a sync job that drifts out of date.

Localization compared: Sanity, AEM, Contentstack, and Kontent.ai

FeatureSanityAdobe Experience ManagerContentstackKontent.ai
Localization patternsField-level and document-level patterns, chosen per schema type, with Sanity-maintained plugins: internationalized-array and @sanity/document-internationalization.Language roots and language copies for localizing pages, plus MSM blueprints and live copies for rolling out localized sites across a large estate.A localized entry for each locale that inherits from a configured fallback language until an editor localizes it. Fallback is set per locale.Language variants of each content item, each with its own content, workflow state, comments, and version history.
AI and vendor translationAI Assist document and field APIs (Growth plan and up), Agent API translate() with styleGuide and protectedPhrases (experimental), plus Smartling, Transifex, and Phrase plugins.The Translation Integration Framework connects machine and human translation providers, including vendors such as XTM. It is mature and well suited to regulated translation programs.Workflows and automation are defined in the platform UI. Teams usually connect machine or vendor translation through integrations around localized entries.Translation is usually connected through integrations or vendor services, and the per-variant workflow controls how each translated variant moves through review.
Publishing each language independentlyDocument-level localization publishes each language on its own schedule. Field-level publishes all languages together, so teams choose per schema type.Language copies are separate pages, so markets can publish independently, while live copies can inherit updates from blueprint sources.Each locale's entry publishes separately once it's localized. Entries that haven't been localized keep inheriting content from the fallback language.Each language variant has its own workflow state and versions, so translated variants can publish on their own schedule.
Coordinated multi-locale launchesContent Releases bundle translated content across locales so reviewers can preview it together and publish when ready. Functions can react to release versions events.Translation projects and a deep workflow engine coordinate localized changes. Governance is strong but takes specialist setup and administration.Releases group entries for deployment to environments. Workflows are configured in the platform UI rather than versioned in code.Per-variant workflows and scheduled publishing coordinate launches one language at a time, which suits teams that review each locale separately.
Regional editor permissionsCustom roles with GROQ filters. user::attributes() scopes one role to each editor's market using SAML IdP data and fails closed (Enterprise plans).Granular permissions tied to language roots and site structure. They are mature for large estates but administered per site tree.Roles can be restricted by locale and content type and are configured in the platform UI for each stack.Roles can be limited to specific languages and workflow steps, matching permissions to the per-variant review model.
Multi-brand, multi-region estatesStudio Workspaces give each brand or market a tailored Studio over one Content Lake, so shared content is referenced rather than copied.MSM blueprints and live copies roll content out across sites and brands. The model is proven but takes significant implementation effort.Multi-brand estates are usually organized as separate stacks, or within one stack by locale and content type, depending on governance needs.Multi-brand setups typically use separate projects or environments, with spaces and collections to organize content by brand.

Ready to try Sanity?

See how Sanity can transform your enterprise content operations.