Using localized bodyPortableText with coalescing in GROQ query

4 replies
Last updated: Jun 2, 2020
Hi! I’m having trouble using a localized bodyPortableText in query. I used the
localeString
example but switched the used type from
string
to
bodyPortableText
. How do I now combine the use of language parameter, coalescing and expanding the array content of the
bodyPortableText
in the projection? 😬
AI Update

I understand you're having trouble querying a localized bodyPortableText field where you need to combine a language parameter, coalescing, and expanding the array content.

The key is understanding that with localized arrays (like when using the internationalized-array plugin), you need to:

  1. Filter to the correct language
  2. Access the value property
  3. Expand the Portable Text array with []
  4. Wrap it in coalesce() for fallbacks

Here's the pattern:

*[_type == "yourDocType"] {
  title,
  "body": coalesce(
    bodyPortableText[_key == $language][0].value[],
    bodyPortableText[_key == $baseLanguage][0].value[],
    []
  )
}

Breaking this down:

  • bodyPortableText[_key == $language][0] - Filters the localized array to your language and gets the first match
  • .value[] - The crucial part! The [] at the end expands the Portable Text array content (all the blocks, marks, inline objects, etc.)
  • coalesce(...) - Tries your requested language first, falls back to base language, then empty array

Without the []: You'd get the Portable Text as a nested structure rather than expanded content.

With the []: You get the actual block content that you can render.

If you need to transform the Portable Text blocks themselves, you can project inside the expansion:

"body": coalesce(
  bodyPortableText[_key == $language][0].value[]{
    ...,
    _type == "image" => {
      ...,
      asset->
    }
  },
  bodyPortableText[_key == $baseLanguage][0].value[],
  []
)

This pattern is covered in the Sanity localization documentation, specifically in the "Querying localized arrays with GROQ" section. The same principles apply whether you're working with simple strings or complex Portable Text content - the [] expansion is what makes it work for arrays within arrays.

Show original thread
4 replies
Nevermind again, just figured it out πŸ™‚
Here is the projection that worked:
"terms": coalesce(terms[$language], <http://terms.fi|terms.fi>)[] {
        ...,
        children[]{
          ...,
          "asset": asset->
        }
      }
Thanks for sharing! We should probably add this to the documentation on l10n/portable text πŸ™‚
Thanks for sharing! We should probably add this to the documentation on l10n/portable text πŸ™‚

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?