
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeGreat question! Managing all site data including navigation, labels, and text snippets in Sanity is definitely achievable and a common pattern. Here's how to approach this for a multi-language project:
For navigation, footer, and site-wide text, you'll want to use singleton documents. These are document types that only have one instance and are perfect for global settings. You'd typically create schemas like:
siteSettings - for global configurationnavigation - for main menu structurefooter - for footer contentlabels - for UI strings like button text, form labels, etc.Setting up singletons requires configuring three things in your sanity.config.js: the Structure Builder to create direct links to these documents, template filtering to prevent creating duplicates, and document actions to disable deletion. The singleton document guide walks through this, or you can use the singleton-tools plugin to simplify setup.
Sanity offers two main approaches for multi-language content, and based on the localization documentation, here's what works best:
Document-level localization (recommended for most cases): Each language gets its own complete document. The @sanity/document-internationalization plugin handles this by creating separate documents linked through a shared reference. This means you'd have navigation-en, navigation-es, etc. This approach:
Field-level localization: Store all translations within the same document. While convenient for simple use cases, this isn't recommended for complex content or Portable Text fields as it can quickly hit attribute limits and create unwieldy data structures.
For navigation specifically, you might create a schema like:
{
name: 'navigation',
type: 'document',
fields: [
{
name: 'items',
type: 'array',
of: [{
type: 'object',
fields: [
{ name: 'label', type: 'string' },
{ name: 'url', type: 'string' },
// or reference to pages
{ name: 'page', type: 'reference', to: [{ type: 'page' }] }
]
}]
}
]
}For UI labels and strings, consider grouping them logically:
{
name: 'labels',
type: 'document',
fields: [
{ name: 'submitButton', type: 'string' },
{ name: 'learnMore', type: 'string' },
{ name: 'contactUs', type: 'string' }
// etc.
]
}The document-level approach with the @sanity/document-internationalization plugin combined with singleton documents for global content is generally the most scalable and maintainable solution for what you're describing. It keeps your data clean and makes it easy for editors to manage translations independently.
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store