Sanity Studio’s internationalization system provides hooks and utilities for translating the Studio UI and managing multiple locales.
useTranslation
Access translation functions for a given namespace.
import {useTranslation} from 'sanity'
function MyComponent() {
const {t} = useTranslation('studio')
return <h1>{t('welcome.title')}</h1>
}
Translation namespace(s) to load. Common namespaces:
'studio' - Studio UI strings
'validation' - Validation messages
- Custom namespaces from your plugins
Translation optionsPrefix to prepend to all translation keys
Override the current locale
Translation functiont('key') // Returns translated string
t('key', {defaultValue: 'Fallback'}) // With fallback
t('key', {count: 5}) // With interpolation
t('key', {name: 'John'}) // With variables
Example with Interpolation
import {useTranslation} from 'sanity'
function WelcomeMessage({userName}: {userName: string}) {
const {t} = useTranslation('studio')
return (
<div>
<h1>{t('welcome.title')}</h1>
<p>{t('welcome.message', {name: userName})}</p>
</div>
)
}
useLocale
Access current locale information.
import {useLocale} from 'sanity'
function LocaleInfo() {
const locale = useLocale()
return (
<div>
<p>Locale: {locale.id}</p>
<p>Title: {locale.title}</p>
</div>
)
}
Current locale informationLocale identifier (e.g., 'en-US', 'nb-NO')
Display title for the locale
Week information for the localeFirst day of week (0 = Sunday, 1 = Monday)
defineLocale
Define a custom locale for your Studio.
import {defineLocale} from 'sanity'
export const myLocale = defineLocale({
id: 'en-US',
title: 'English (US)',
weekInfo: {firstDay: 0}, // Sunday
})
Locale identifier (e.g., 'en-US', 'fr-FR')
Week configurationFirst day of week (0-6, where 0 = Sunday)
defineLocaleResourceBundle
Define translation resources for a locale.
import {defineLocaleResourceBundle} from 'sanity'
export const enUSBundle = defineLocaleResourceBundle({
locale: 'en-US',
namespace: 'studio',
resources: {
'welcome.title': 'Welcome',
'welcome.message': 'Hello, {{name}}!',
'actions.save': 'Save',
'actions.publish': 'Publish',
},
})
resources
Record<string, string>
required
Key-value pairs of translations
Configuration
Configure locales in your Studio config:
import {defineConfig, defineLocale, defineLocaleResourceBundle} from 'sanity'
const frFR = defineLocale({
id: 'fr-FR',
title: 'French',
})
const frFRBundle = defineLocaleResourceBundle({
locale: 'fr-FR',
namespace: 'studio',
resources: {
'welcome.title': 'Bienvenue',
// ... more translations
},
})
export default defineConfig({
// ...
i18n: {
locales: [frFR],
bundles: [frFRBundle],
},
})
i18n Configuration
Available locales for the Studio
Translate Component
Component for inline translations:
import {Translate} from 'sanity'
function MyComponent() {
return (
<div>
<Translate t={(t) => t('welcome.title')} />
{/* With interpolation */}
<Translate
t={(t) => t('welcome.message', {name: 'John'})}
/>
</div>
)
}
t
(t: TFunction) => string
required
Function that receives translation function and returns translated string
useI18nText
Resolve internationalized text records:
import {useI18nText} from 'sanity'
function SchemaTitle({i18nTitle}: {i18nTitle: I18nTextRecord}) {
const title = useI18nText(i18nTitle)
return <h2>{title}</h2>
}
Internationalized text object with locale keys:{
'en-US': 'Title',
'fr-FR': 'Titre'
}
Resolved text for current locale, with fallback to default locale
Example: Multi-language Studio
// locales/fr-FR.ts
import {defineLocale, defineLocaleResourceBundle} from 'sanity'
export const frFR = defineLocale({
id: 'fr-FR',
title: 'Français',
weekInfo: {firstDay: 1}, // Monday
})
export const frFRResources = defineLocaleResourceBundle({
locale: 'fr-FR',
namespace: 'studio',
resources: {
// Common actions
'actions.save': 'Enregistrer',
'actions.publish': 'Publier',
'actions.unpublish': 'Dépublier',
'actions.delete': 'Supprimer',
// Navigation
'nav.structure': 'Structure',
'nav.vision': 'Vision',
// Document editor
'editor.title': 'Titre',
'editor.publish-info': 'Publié le {{date}}',
},
})
// sanity.config.ts
import {defineConfig} from 'sanity'
import {frFR, frFRResources} from './locales/fr-FR'
export default defineConfig({
// ...
i18n: {
locales: [frFR],
bundles: [frFRResources],
},
})
// Usage in component
import {useTranslation} from 'sanity'
import {Button} from '@sanity/ui'
function SaveButton() {
const {t} = useTranslation('studio')
return (
<Button text={t('actions.save')} tone="primary" />
)
}
Example: Plugin with Translations
// myPlugin.ts
import {definePlugin, defineLocaleResourceBundle} from 'sanity'
const myPluginBundle = defineLocaleResourceBundle({
locale: 'en-US',
namespace: 'my-plugin',
resources: {
'tool.title': 'My Tool',
'tool.description': 'Description of my tool',
'action.import': 'Import Data',
'action.export': 'Export Data',
},
})
export const myPlugin = definePlugin({
name: 'my-plugin',
i18n: {
bundles: [myPluginBundle],
},
tools: [
{
name: 'my-tool',
// Tool will use 'my-plugin' namespace for translations
component: MyToolComponent,
},
],
})
// MyToolComponent.tsx
import {useTranslation} from 'sanity'
function MyToolComponent() {
const {t} = useTranslation('my-plugin')
return (
<div>
<h1>{t('tool.title')}</h1>
<p>{t('tool.description')}</p>
</div>
)
}
Available Namespaces
'studio' - Core Studio UI strings
'validation' - Validation messages
'copy-paste' - Copy/paste functionality
- Plugin-specific namespaces defined by installed plugins