Best way to read translations from singleton?

Hello everybody,
I am learning Directus atm using Astro and the SDK. One thing I can’t get done is reading translations from a collection using Deep or without directly accessing them using the *_translations collections that are auto generated and having them set to read as well.

Question: Is there a better way to read translated content from my globals collections? Can I somehow query the translated content through the “globals” singleton using the deep feature of the SDK?

const globals = await directus.request(readSingleton("globals"));

const content_de = await directus.request(
  readItems("globals_translations", {
    filter: { languages_code: { _eq: "de-DE" } },
  })
);
const content_en = await directus.request(
  readItems("globals_translations", {
    filter: { languages_code: { _eq: "en-US" } },
  })
);
---
<Layout>
  <div>
    <Header title={globals.title} description={globals.description} />
    <Main>
      <p>{content_de[0].content}</p>
      <div>{content_en[0].content}</div>
    </Main>
    <Footer />
  </div>
</Layout>

thanks

Hey there! :waving_hand:

Here are a few ways to solve this, from best to simplest.

Method 1: The Ideal Way (Deep Query)

Your globals collection must have a relational field (likely a “One-to-Many” relationship) that connects it to the globals_translations collection. It’s probably just named translations.
If not, then refer to this on how to set it https://directus.io/docs/configuration/translations

const globals = await directus.request(
  readSingleton('globals', {
    fields: ['*', { translations: ['*'] }], // Ask for all fields + all translation fields
    deep: {
      translations: {
        _filter: {
          languages_code: { _in: ['de-DE', 'en-US'] } // Filter translations inside the main query
        }
      }
    }
  })
);

How to use it in your component:

<Layout>
  <div>
    <Header title={globals.title} description={globals.description} />
    <Main>
      <!-- Find the specific translation object you need -->
      <p>{globals.translations?.find(t => t.languages_code === 'de-DE')?.content}</p>
      <div>{globals.translations?.find(t => t.languages_code === 'en-US')?.content}</div>
    </Main>
    <Footer />
  </div>
</Layout>

Method 2: The Fast Way (Promise.all)

If for some reason the deep query doesn’t work for you, you can still speed up your original approach by firing all your requests at once instead of one-after-the-other using Promise.all() .

// This fires all three requests in parallel, which is much faster
const [globals, content_de, content_en] = await Promise.all([
  directus.request(readSingleton("globals")),
  directus.request(
    readItems("globals_translations", {
      filter: { languages_code: { _eq: "de-DE" } },
    })
  ),
  directus.request(
    readItems("globals_translations", {
      filter: { languages_code: { _eq: "en-US" } },
    })
  )
]);

// content_de and content_en are still arrays, so you'd still access content_de[0].content

My Recommendation

Start with Method 1 (the Deep Query). It’s the most “correct” way to handle this in Directus. It keeps your code clean and minimizes the number of API calls you have to make. You’ll probably find it’s exactly what you were looking for when you asked about the “deep feature”.

Hey Ahmad, thank you for taking the time to help me out!
Helped a lot and I think it now clicked in my brain how requesting and filtering works, using the Directus SDK.

Here’s a way I figured out, using object destructuring, without relying on the *_translations table:

const {
  translations: [{ content: content_en }],
} = await directus.request(
  readSingleton("globals", {
    fields: [{ translations: ["content"] }],
    deep: {
      translations: {
        _filter: {
          languages_code: { _eq: "en-US" },
        },
      },
    },
  })
);
 ´´´