how to implement localization on blocks?

4 replies
Last updated: Oct 5, 2020
Hi!Does anyone have an idea on how to implement localization on blocks? I tried doing it with a similar approach to this
https://www.sanity.io/docs/localization but I’m having trouble with the queries in Gatsby, I could do a work around and get the data, but maybe someone knows a better way?
Thanks!
AI Update

I totally understand the challenge with localizing Portable Text blocks in Gatsby! The issue you're running into is pretty common, and there are a few approaches that work better than others.

The main problem with field-level localization for blocks (as shown in the docs you linked) is that when you have localized Portable Text fields, querying them through gatsby-source-sanity can get tricky because of how the _raw fields are generated.

Here's what works best:

For Portable Text specifically, you'll want to use the _raw fields that gatsby-source-sanity generates. If you have a field-level localization structure like:

{
  name: 'localeBlockContent',
  type: 'object',
  fields: [
    {
      name: 'en',
      type: 'array',
      of: [{type: 'block'}]
    },
    {
      name: 'es',
      type: 'array',
      of: [{type: 'block'}]
    }
  ]
}

Then in your Gatsby query, you'd access it like:

query {
  allSanityYourType {
    nodes {
      _rawLocaleBlockContent
    }
  }
}

And then access the specific language in your component:

const content = data._rawLocaleBlockContent[currentLanguage]

Important caveat: Field-level localization for Portable Text isn't actually recommended by Sanity because it can quickly consume your attribute limits and create complex data structures.

Better approach - Document-level localization:

Consider using document-level localization instead, where each language version is a separate document. This works much better with gatsby-source-sanity and gives you cleaner queries:

query($language: String!) {
  allSanityPost(filter: { language: { eq: $language } }) {
    nodes {
      _rawBody
    }
  }
}

This avoids the nested query complexity and works more naturally with Gatsby's GraphQL layer. You'd add a language field to your document schema and create separate documents for each language version.

The _raw fields are special to gatsby-source-sanity and provide the raw Portable Text data with proper reference resolution. They're not available in Sanity's GraphQL playground, which can make debugging a bit tricky, but they're essential for querying block content in Gatsby.

Hope this helps! If you're still having specific query issues with your current setup, feel free to share the error messages and I can help troubleshoot further! ✨

Show original thread
4 replies
An approach I’ve considered for localization of a full site, is to just have a seperate dataset … I don’t know how that would compare, but think it could be the cleanest approach.
Since I don’t need the localization for the entire site, I’m not sure it’s the best approach for me. But thanks for responding, Ben.
Hi Ximena, what’s your current approach? Something like this?
import supportedLanguages from './supportedLanguages'

export default {
  name: 'localeBlockContent',
  type: 'object',
  fieldsets: [
    {
      title: 'Translations',
      name: 'translations',
      options: {collapsible: true}
    }
  ],
  fields: supportedLanguages.map(lang => ({
    title: lang.title,
    name: lang.id,
    type: 'blockContent',
    fieldset: lang.isDefault ? null : 'translations'
  }))
}
This would give you essentially the same structure as with the locale fields from the example, nesting the block content in the locale codes. If you’ve set up a utility to deeply localise entire documents (
https://www.sanity.io/docs/localization#deeply-localizing-an-entire-document-545b44e4b950 ), you won’t have to specify things further.
One direction would then be:

import BlockContent from '@sanity/block-content-to-react'
...
<BlockContent blocks={data.sanityPost._rawContent} serializers={serializers} />
...
export const query = graphql`
  query myPostQuery {
    sanityPost(_id: { eq: "myPostId" }) {
      _rawContent
    }
  }
`
Thank you Peter! I was having trouble because of weird nesting I think, but this helped a lot 😁

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?