Skip to main content
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>
}
namespace
string | string[]
Translation namespace(s) to load. Common namespaces:
  • 'studio' - Studio UI strings
  • 'validation' - Validation messages
  • Custom namespaces from your plugins
options
UseTranslationOptions
Translation options
keyPrefix
string
Prefix to prepend to all translation keys
lng
string
Override the current locale
t
TFunction
Translation function
t('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>
  )
}
locale
Locale
Current locale information
id
string
Locale identifier (e.g., 'en-US', 'nb-NO')
title
string
Display title for the locale
weekInfo
LocaleWeekInfo
Week information for the locale
firstDay
number
First 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
})
id
string
required
Locale identifier (e.g., 'en-US', 'fr-FR')
title
string
required
Display title
weekInfo
LocaleWeekInfo
Week configuration
firstDay
number
First 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',
  },
})
locale
string
required
Target locale identifier
namespace
string
required
Translation namespace
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

locales
Locale[]
Available locales for the Studio
bundles
LocaleResourceBundle[]
Translation bundles

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>
}
i18nText
I18nTextRecord
required
Internationalized text object with locale keys:
{
  'en-US': 'Title',
  'fr-FR': 'Titre'
}
text
string
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

Build docs developers (and LLMs) love