Tips for localizing the rich text editor in Sanity.io using a custom localeBlock type.

6 replies
Last updated: May 14, 2020
Looking into localization and sanity. Been using this guide: https://www.sanity.io/docs/localization which works ok for strings. But I need to localize the rich text editor as well (array of block). Any tips on how to create a new localeBlock type?
AI Update

Good news! You're on the right track. The guide you're using is a solid foundation, but you're correct that localizing Portable Text (block content) needs special consideration.

The short answer: For rich text editors (Portable Text/block arrays), you should use document-level localization rather than field-level localization. This means creating separate documents for each language version instead of trying to nest translations within the same document.

Here's why this matters: Field-level localization with Portable Text can quickly hit Sanity's attribute limits because block arrays create numerous unique paths in your data structure. When you multiply that by multiple languages in the same document, you can run into serious issues.

How to implement document-level localization for block content:

  1. Use the official plugin: Install @sanity/document-internationalization which is specifically designed for this approach. It handles creating and linking translated documents.

  2. Structure your schema normally: Your block content field stays as a regular type: 'array' of blocks - no special wrapping needed:

{
  name: 'content',
  type: 'array',
  of: [{type: 'block'}]
}
  1. Add language metadata: Each document gets a language field, and the plugin manages the relationships between language versions automatically.

  2. Query by language: When fetching content, filter by language:

*[_type == "post" && language == "fr"]

The beauty of this approach is that your rich text editor works exactly the same way in all languages - you're just editing different documents. Each language version is independent, which also means translators can work without affecting other languages, and you can publish them on different schedules.

If you need fields that are shared across all language versions (like image galleries), you can maintain those in the base language document and reference them from translations.

we’ve done it exactly the same way
just change
string
to
blockContent
in that example
I tried, but seems block does not like "fieldset"
Hey
user E
, the example below is a contentype with tabs to switch between the different locales:
import Tabs from 'sanity-plugin-tabs'
import { languages } from '../../supportedLanguages'

export default {
  name: 'localeBlock',
  type: 'object',
  inputComponent: Tabs,
  fieldsets: languages.map(lang => ({
    title: lang.title,
    name: lang.id
  })),

  options: {
    layout: 'object'
  },

  fields: languages.map(lang => ({
    title: ' ',
    name: lang.id,
    type: 'array',
    of: [
      {
        type: 'block',
        styles: [{ title: 'Normal', value: 'normal' }],
        lists: [],
        marks: {
          decorators: [
            { title: 'Strong', value: 'strong' },
            { title: 'Emphasis', value: 'em' }
          ]
        }
      }
    ],
    fieldset: lang.id
  })),

  preview: {
    select: {
      title: 'title'
      // media: 'logo',
    }
  }
}
const supportedLanguages = [    
    {id: 'nb', title: 'Norwegian', isDefault: true},
    {id: 'en', title: 'English'}
  ]
  
  export default {
    name: 'localeBlock',
    type: 'object',
    fieldsets: [
      {
        title: 'Oversettelser',
        name: 'translations',
        options: {collapsible: true}
      }
    ],
    fields: supportedLanguages.map(lang => (
      {
        title: lang.title,
        name: lang.id,
        type: 'block',
        //fieldset: lang.isDefault ? null : 'translations'
      }
    ))
  }
As long as I comment out fieldset it works, but now I don't get the collapsible area for translations like I do from strings.
ooh nice I didn’t know about that way of doing tabs

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?