Understanding the use of the _translations query in internationalisation plugin readme

4 replies
Last updated: Jul 6, 2023
I do see this query inside the document internationalisation plugin readme, but I don’t get the _translations query. Why should I use that, if I already get all translations when adding language == $language

// All `lesson` documents of a single language
*[_type == "lesson" && language == $language]{
  title,
  slug,
  language,
  // Get the translations metadata
  // And resolve the `value` reference field in each array item
  "_translations": *[_type == "translation.metadata" && references(^._id)].translations[].value->{
    title,
    slug,
    language
  },
}

AI Update

The _translations query serves a different purpose than your base query with language == $language. Here's why you need it:

Your initial query *[_type == "lesson" && language == $language] only fetches documents in one specific language. The _translations part is what gives you access to all the other language versions of that same content.

Think of it this way:

  • The base query finds all lessons in, say, English ($language = "en")
  • The _translations subquery then looks up and includes the Spanish, French, German, etc. versions of each lesson

The Document Internationalization plugin creates separate documents for each language version, linked together through a special translation.metadata document. The query pattern you're seeing:

"_translations": *[_type == "translation.metadata" && references(^._id)].translations[].value->

Does three things:

  1. Finds the metadata document that references the current lesson (references(^._id))
  2. Gets all translation references from that metadata document (.translations[])
  3. Resolves those references to get the actual translated documents (.value->)

Why is this useful? It lets you build language switchers, show "Available in: EN, ES, FR" indicators, or prefetch alternate language versions for better UX. Without the _translations query, you'd only have the English lessons with no way to know which other languages exist or how to link to them.

So you're not replacing language == $language with _translations – you're using both together. The first filters to your current language, the second connects you to all the alternatives.

The language param is getting you a single translation. The
_translations
projection is getting all other translations’ title, slug, and language.
That is not how I see it is working. Whenever I use
*[_type == "lesson" && language == $language]
it will returns me the fully translated document since it created a separate document for each language. This is how the plugin works right now. So this is where my confusion comes from.
user M
Could you clarify this? Sorry for pinging you.

All is working btw, but the docs seems a bit strange to me.
I am struggling with this as well.
Still about to figure out how correctly call the correct translation for a dataset that has a separate language-field (like lesson) rather than a 'staged approach' via the document-internationalization-array plugin (e.g. 'course'). How to practically pass through the $language param into the groq query to only show the lessons in a specific language instead of obtaining runtime errors due to $language.

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?