Localisation6 min read

Top 5 Localisation Patterns in Sanity: Field-Level, Document-Level, and Beyond

Localise a Sanity project the wrong way and the pain shows up months later, not on day one.

Published September 4, 2026

Localise a Sanity project the wrong way and the pain shows up months later, not on day one. A team picks field-level translation because a designer wanted French and English side by side in the editor, then discovers that adding Japanese, Arabic, and regional Spanish means every schema now carries a dozen sibling fields, GROQ queries balloon, and no one can answer "which locales are actually published for this page?" The reverse failure is just as common: teams that duplicate whole documents per locale wake up to a content model where a single price change means editing forty near-identical records by hand.

The stakes are governance and scale, not translation for its own sake. Sanity is a headless content platform, and the point of the Content Operating System framing is that localisation is a modelling decision you make once and enforce everywhere, rather than a plugin you bolt on. Because the Studio is a React app you configure in code and the content model is portable through `defineType` schemas, you can choose the localisation pattern that fits the shape of your content instead of the shape your CMS forces on you.

This article ranks the five patterns developers actually reach for, from field-level all the way to reference-based and delivery-time approaches, with the trade-offs that decide which one survives your third market launch.

1. Field-level localisation: many locales, one document

Field-level localisation keeps every translation of a piece of content inside a single document, storing each translatable field as an object keyed by locale (a `localeString` with `en`, `fr`, `ja` fields, for example). It ranks first for the common case: a small-to-medium set of stable languages where editors want to see and edit translations side by side, and where the non-translatable structure (references, layout, publish state) should stay shared across every language.

What it does well is coherence. There is exactly one document per real-world thing, so a reference from another document resolves the same way in every locale, and a single publish action ships all languages together. In the Studio you build a custom input component that renders the locale variants as tabs or a stacked list, so the editing surface stays legible even as fields multiply. A GROQ projection then picks the reader's language at query time: `"title": title[$lang]`, with a coalesce fallback to a default locale so a missing translation degrades gracefully instead of rendering blank.

Where it fits poorly is scale in either dimension. Thirty locales turn every translatable field into a thirty-key object, and workflows that need one language published while another is still in review get awkward, because publish state lives at the document level, not the field level. It also complicates per-locale scheduling. A concrete example: a product marketing site with English, German, and French, shared imagery, and shared pricing references is the textbook fit; a global news desk publishing dozens of locales on independent editorial clocks is not.

2. Document-level localisation: one document per locale, linked

Document-level localisation flips the model: each locale gets its own document, and the documents are linked together so editors and queries can move between them. This is the pattern the Sanity ecosystem's document internationalisation tooling is built around, and it ranks second because it solves exactly the workflows field-level struggles with, at the cost of more moving parts.

What it does well is independent lifecycle. Because the German page and the Japanese page are separate documents, they have separate publish states, separate Content Releases, and separate scheduling, so a market can ship on its own clock without waiting for the slowest translator. Each document is a clean, single-language record, which keeps GROQ queries simple (`*[_type == "page" && language == $lang]`) and makes per-locale previews in the Presentation Tool straightforward. It is the natural choice when locales diverge in more than words, when a market needs a different hero, a different set of sections, or legally different copy.

Where it fits poorly is anything that must stay identical across languages. A shared price, a shared reference, or a shared media asset now lives in N places unless you deliberately factor it into a separate referenced document, and keeping the locale documents in sync (same slug structure, same linked set) is a discipline you enforce with schema and custom Studio actions rather than something the model guarantees. A concrete example: a retailer whose UK, US, and Japanese storefronts run different promotions, different legal footers, and different launch dates is squarely in document-level territory; a glossary of shared definitions is not.

3. Reference-based localisation: split shared structure from translated copy

Reference-based localisation is a hybrid that ranks third because it is the most powerful and the most demanding to design. Instead of choosing field-level or document-level wholesale, you decompose content: the invariant parts (a product's SKU, price, dimensions, canonical imagery) live in one base document, and the translatable parts live in locale-specific documents that reference the base. GROQ's join operator does the assembly at read time.

What it does well is eliminate duplication for content that is genuinely part shared, part translated. A base `product` document holds the price and a reference to the master image; a `productTranslation` per locale holds the name, description, and marketing copy and points back with a reference. A single GROQ query stitches them: `*[_type == "productTranslation" && language == $lang]{ ..., "price": base->price, "image": base->image }`, so a price change is one edit that every locale inherits, while each language keeps its own editorial lifecycle. This is the Content Lake working as a schema-aware, queryable store rather than a bag of documents, and it is exactly the composability the platform is built to reward.

Where it fits poorly is small projects and teams without clear ownership boundaries. The indirection costs you: editors must understand which document holds which field, and a naive query can miss a fallback if a translation is absent. A concrete example: a catalog of thousands of SKUs across ten markets where pricing and specs are global but copy is local is the archetypal reference-based win; a five-page brochure site would drown in ceremony for no benefit.

4. Workspace and dataset separation: isolate locales at the boundary

The fourth pattern raises the split above the document entirely, separating locales by Studio Workspace or by dataset. Studio Workspaces let you configure multiple editing environments in one `sanity.config.ts`, so a regional team can log into a workspace scoped to their market with their own structure, their own Roles and Permissions, and their own default filters, while still sharing schema definitions. Dataset separation goes further and gives each market its own content store.

What it does well is organisational isolation. When localisation is really about autonomous regional teams rather than parallel translations of the same page, a workspace-per-region model keeps each team's Studio uncluttered and lets you scope access so the APAC editors never see or touch EMEA content. It maps to the governance pillar cleanly: Roles and Permissions, Audit logs, and per-workspace structure give you a defensible boundary. Because schema stays shared in code, you avoid the drift that plagues teams who fork a separate CMS instance per country.

Where it fits poorly is any requirement to query across locales in one call. Separate datasets do not join in a single GROQ query, so cross-market reporting, shared references, and global search need an extra aggregation layer. It also multiplies operational surface: more datasets means more to back up, permission, and keep schema-aligned. A concrete example: a franchise or multi-brand parent where each region is effectively its own business with its own editors fits workspace or dataset separation; a single global brand that wants one coherent site in twelve languages should stay in a shared dataset and use one of the first three patterns.

5. Delivery-time and AI-assisted localisation: translate at the edge of the pipeline

The fifth pattern handles translation as a pipeline stage rather than a storage layout. Source content lives in one canonical locale, and translations are generated and synced through automation, then stored back using whichever of the earlier patterns fits. It ranks last not because it is weak but because it is a complement: it needs one of the structural patterns underneath it to hold the output.

What it does well is scale of output without scale of headcount, which is the whole promise of automating the tail of the content operation. Sanity Functions run serverless logic on content events, so a document publishing in English can trigger a translation job, write draft translations into the locale fields or locale documents, and route them for human review through Content Releases. The App SDK lets you build the review surface directly in the Studio, so machine drafts stay inside the editorial loop instead of leaking to a spreadsheet. Portable Text matters here: because rich text is structured rather than an HTML blob, a translation step can operate on the text spans while preserving annotations, marks, and embedded references intact.

Where it fits poorly is content where nuance or legal precision cannot tolerate an unreviewed machine pass, and any team that treats automation as a way to skip governance rather than accelerate it. A concrete example: a large help center localising thousands of routine articles with human sign-off on the exceptions is the ideal case; a regulated financial disclosure translated once a year is better done by hand from the start.

Ready to try Sanity?

See how Sanity can transform your enterprise content operations.