Querying references inside a Portable text field in Sanity
I understand you're trying to project into a Portable Text field that uses field-level translation, where you need to access references (like image assets) within the translated content blocks.
The key is to use the array projection operator [] immediately after your coalesce expression. This tells GROQ to iterate over each element in the array and apply the projection to each block:
"content": coalesce(content[$lang], content.en)[] {
...,
_type == "pageImage" => {
...,
"alt": coalesce(alt[$lang], alt.en),
"imageBlock": imageBlock {
"asset": asset->url,
"dimensions": asset->metadata.dimensions
}
}
}The [] operator is what enables you to then use conditional projections (the => operator) and dereference operations (->) within each block.
Here's a more complete example that handles different block types:
"content": coalesce(content[$lang], content.en)[] {
_type != "pageImage" => @,
_type == "pageImage" => {
_type,
_key,
"alt": coalesce(alt[$lang], alt.en),
"imageBlock": imageBlock {
"asset": asset->url,
"dimensions": asset->metadata.dimensions
}
}
}In this pattern:
- The
@operator (identity operator from GROQ's pipeline components) passes through non-pageImage blocks unchanged - pageImage blocks get the special projection with language fallback and reference dereferencing
- The
asset->urlsyntax works because you're inside the projection context where the reference operator can resolve
The array projection operator [] is part of GROQ's pipeline architecture, where operations are chained together to transform data. The coalesce() function returns the first non-null value, and when followed by [], that value (which should be an array) is projected element-by-element.
Important note: While this approach works, the Sanity documentation on localization recommends against using field-level translation for Portable Text fields, as it can quickly consume attribute limits and create complex data structures. Document-level localization is generally preferred for Portable Text content.
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.