Displaying Localized String Titles in Sanity Studio with Field-Level Translations

4 replies
Last updated: Jan 27, 2021
Problems with locale fields
Working with localization, and first tried the intl-plugin, but couldn't get it to work, so figured I'd go with standard field level translations by following the docs, but I can't figure out how to display the correct title for the post in the studio. Right now the title looks like this (image).

I kind of understand how it would work if I followed the docs and had the localized string in the same doc as the page schema, but is there any way I can pass down the title from my localeString.js to my page.js schema type?

Providing my localeString.js as well as my page.js in the thread
AI Update

I can see you're working with field-level translations and running into the common challenge of displaying localized titles in Studio's preview. The issue is that when you have a localized string object (like {en: "English Title", no: "Norwegian Title"}), the preview shows the entire object rather than the specific language you want.

The solution is to use the preview configuration's select and prepare functions to extract and display the correct language from your localeString object. Here's how to set it up:

// page.js
import localeString from './localeString'

export default {
  name: 'page',
  type: 'document',
  fields: [
    {
      name: 'title',
      type: 'localeString'
    },
    // ... other fields
  ],
  preview: {
    select: {
      title: 'title' // This selects the entire localeString object
    },
    prepare({title}) {
      return {
        title: title?.en || title?.no || 'Untitled', // Pick your default language
        subtitle: 'Page'
      }
    }
  }
}

However, if you want to make it more dynamic and show the current language the editor is working in, you can select multiple language fields using dot notation to access nested fields:

preview: {
  select: {
    titleEn: 'title.en',
    titleNo: 'title.no'
  },
  prepare({titleEn, titleNo}) {
    // Choose which language to display as primary
    return {
      title: titleEn || titleNo || 'Untitled',
      subtitle: titleNo ? `NO: ${titleNo}` : undefined
    }
  }
}

Note on the Language Filter Plugin: If you want a more sophisticated solution where the preview automatically shows the language you're currently editing, consider using the Language Filter plugin. It provides a language selector in Studio and can help manage which language is displayed throughout the interface.

For field-level translations, be aware that while this approach works well for simple strings, the Sanity documentation recommends document-level localization over field-level for Portable Text and complex content to avoid hitting attribute limits.

The key insight here is that you don't need to "pass down" the title from your localeString schema to your page schema. Instead, you configure the preview directly in your page schema to extract the specific language field you want to display. The select object can access nested properties using dot notation ('title.en'), which pulls out just the English version from your localeString object.

Show original thread
4 replies
localeString.js
const supportedLanguages = [
  { id: 'en', title: 'English', isDefault: true },
  { id: 'se', title: 'Swedish' },
];

export default {
  title: 'Localized string',
  name: 'localeString',
  type: 'object',
  // Fieldsets can be used to group object fields.
  // Here we omit a fieldset for the "default language",
  // making it stand out as the main field.
  fieldsets: [
    {
      title: 'Translations',
      name: 'translations',
      options: { collapsible: true },
    },
  ],
  // Dynamically define one field per language
  fields: supportedLanguages.map((lang) => ({
    title: lang.title,
    name: lang.id,
    type: 'string',
    fieldset: lang.isDefault ? null : 'translations',
  })),
};
--

page.js

import { FaFileAlt } from 'react-icons/fa';

export default {
  name: 'page',
  title: 'Pages',
  type: 'document',
  icon: FaFileAlt,
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'localeString',
    },

    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
    },

    {
      name: 'date',
      title: 'Date',
      type: 'date',
      options: {
        dateFormat: 'YYYY-MM-DD',
        calendarTodayLabel: 'Set current date',
      },
    },

    {
      name: 'pageContent',
      title: 'Content',
      type: 'blockContent',
    },
  ],
};
something like this in page.js

{
   ...,
   preview: {
    select: {
      title: "title.en",
    },
  },
}
Well shit it really was that simple...
Hahaha thanks a ton! Much appreciated

Sanity – Build the way you think, not the way your CMS thinks

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.

Was this answer helpful?