content/tutorials/1.getting-started/implementing-multilingual-content-using-directus-and-astro.md
Directus comes with built-in support for creating multilingual content. In this tutorial, you'll learn how to create multilingual content and access it using your Astro application.
You will need:
Create a new collection called posts with the following fields:
title (Type: Input)slug (Type: Input)content (Type: Markdown)To make your posts publicly accessible, navigate to Settings -> Access Policies -> Public. Then, under the posts section, set a public policy for Read.
For more details on how to set up access control and permissions, read the access control documentation.
To enable multilingual support, start by adding a field named translations to the posts collection. Set its type to Translations, which will automatically generate two new collections: languages and posts_translations. Don't forget to allow Read access for the Public policy for these collections as well.
posts_translations collection, and add the fields title and content with their corresponding types.Next, ensure that the Public policy allows Read access for both the languages and posts_translations collections.
Once the posts_translations collection is created, add the title and content fields, defining their corresponding data types.
Finally, add some content to the posts collection with the appropriate translations in three languages.
Clicking the Toggle split view to show the various translations of the content side by side.
Create a new Astro project by running the command:
npx create-astro@latest astro-multilang
When prompted, select the following configurations:
How would you like to start your new project? A basic, minimal starter (recommended)
Install dependencies? (recommended) Yes
Initialize a new git repository? (optional) No
Navigate into the project directory and install the Directus SDK by running the command:
npm install @directus/sdk
Run the command npm run dev to start the development server and you should see the Astro project running on http://localhost:4321/ in your browser.
First, create a .env file in the root of your project and add the following environment variables:
DIRECTUS_URL=https://your-directus-project-url.com
In the src directory, create a new directory called lib, and inside the directory, create a file called directus.ts. Add the following code to the file:
/// <reference types="vite/client" />
import { createDirectus, rest, readItems } from '@directus/sdk';
const DIRECTUS_URL = import.meta.env.DIRECTUS_URL;
const client = createDirectus(DIRECTUS_URL).with(rest());
export async function fetchPosts(lang: string) {
return await client.request(
readItems("posts", {
fields: ["slug", { translations: ["*", "languages_code"] }],
deep: {
translations: {
_filter: { languages_code: { _eq: lang } },
},
},
})
);
}
export default client;
The code above:
fetchPosts that fetches posts based on the language passed as an argument.You will use the fetchPosts function to fetch posts later in this tutorial.
Let's set up dynamic routing based on the language selected by the user making sure that whenever a user navigates to a post, the content is displayed in the selected language.
Before you do that, delete the Welcome.astro component in the components directory and the index.astro file in the pages directory as you do not need it for this tutorial.
In the Layout.astro file in the layouts directory, update it to include a navigation menu:
---
const { lang } =Astro.props
---
<!doctype html>
<html lang={lang}>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>Astro Basics</title>
</head>
<body>
<nav>
<a href="/en-US/">English</a> |
<a href="/de-DE/">Deutsch</a> |
<a href="/es-ES/"> Espanol</a>
</nav>
<slot />
</body>
</html>
<style>
html,
body {
margin: 0;
width: 100%;
height: 100%;
}
</style>
Next, let's list all posts in the selected language and display the post content in the selected language.
In the pages directory, create a new directory called [lang], and inside the directory, create a file called index.astro with the content:
---
import Layout from "../../layouts/Layout.astro";
import { fetchPosts } from "../../../lib/directus";
const { lang } = Astro.params;
export function getStaticPaths() {
const supportedLanguages = ["en-US", "de-DE", "es-ES"];
return supportedLanguages.map((lang) => ({ params: { lang } }));
}
// Fetch posts for the selected language
const posts = await fetchPosts(lang);
---
<Layout lang={lang}>
<h1>Blog Posts in {lang}</h1>
<ul>
{posts.map((post) => {
const t = post.translations[0];
return (
<li>
<a href={`/${lang}/${post.slug}/`}>{t?.title}</a>
</li>
);
})}
</ul>
</Layout>
The code above gets the current lang the user is trying to access from the Astro.params object and fetches all posts in the selected language.
Since this is happening using the getStaticPaths function, Astro will generate static pages for each language and list all posts in the selected language.
Navigate to http://localhost:4321/de-DE/ and you will be provided you with a UI that looks like this:
Inside of the [lang] directory, create a new file called [slug].astro with the content:
---
import Layout from "../../layouts/Layout.astro";
import { fetchPosts } from "../../lib/directus";
export async function getStaticPaths() {
const supportedLanguages = ["en-US", "de-DE", "es-ES"];
// Fetch all posts from Directus for each language
const posts = await Promise.all(
supportedLanguages.map((lang) =>
fetchPosts(lang).then((posts) =>
posts.map((post) => ({ params: { lang, slug: post.slug }, props: post }))
)
)
);
// Flatten the array to return all language + slug combinations
return posts.flat();
}
const { lang, slug } = Astro.params;
const post = Astro.props;
const t = post.translations[0]; // Get the correct translation
---
<Layout lang={lang}>
<h1>{t?.title}</h1>
<div set:html={t?.content} />
</Layout>
The code above:
Navigate to http://localhost:4321/de-DE/rabbit-facts/ would provide you with a UI that looks like this:
Switching to a different languages would display the content in the selected language:
That's it! You have successfully implemented multilingual content using Directus and Astro.
In this tutorial, you learned how to create multilingual content in Directus and access it using your Astro application. You also learned how to set up language-based dynamic routing to display content in the selected language.
By following the steps outlined, you now have a solid foundation for building multilingual websites. You can expand this further by adding more languages, customizing the navigation menu, and enhancing the user experience with additional features like language switchers or automatic language detection.