Implementing Multilingual Content using Directus and Next.js
Directus comes with built-in support for creating multilingual content. In this post, you'll learn how to create multilingual content and access it using your Next.js application.
Before You Start
You will need:
- A Directus project with admin access.
- Fundamental understanding of Next.js (and some React.js) concepts.
- Optional but recommended: Familiarity with data modeling in Directus.
Set Up Your Directus Project
To get started, set up a Directus project either using Directus Cloud or by self-hosting it using Docker. Then, follow the steps below:
Create a Collection
Create a new collection called posts with the following fields:
title
(Type: Input)content
(Type: Markdown)slug
(Type: Input)
Edit Public Policy
Next, to allow viewing the post as an unauthenticated user, you will need to modify the public access policy.
To do that, navigate to Settings -> Access Policies -> Public. Under posts
, set a public policy for read
. This will now allow all posts to be read by unauthenticated users.
Configure CORS
You may need set your content security policy to allow your Next.js app to access the Directus instance. For example if you are self-hosting, or in development, and using Docker, then you can do this by adding the following environment variable to your docker-compose.yml
file:
environment:
CONTENT_SECURITY_POLICY_DIRECTIVES__FRAME_SRC: your-website-url
Replace
your-website-url
with your Next.js app's URL and the port. eg. if your app URL is in development ishttp://localhost:3000
, replaceyour-website-url
withlocalhost:3000
.
Set Up Your Next.js Project
Next, create a new Next.js app by running the following command:
npx create-next-app \
directus-next-multilingual \
--js \
--app \
--eslint \
--no-src-dir \
--no-tailwind \
--turbopack \
--import-alias "@/*"
Next, change your terminal's working directory into the newly created project directory and install the Directus SDK into it:
cd directus-next-multilingual
npm i @directus/sdk
Now, open the project directory in your code editor to start building the app. First of all, clear out the CSS in app/globals.css
and replace the code in app/page.js
with the following:
export default function Home() {
return <div />
}
Set up Directus
To make it easy to access the Directus instance through the SDK, you should create a helper file that you can import anywhere in your Next.js app. To do that, create a new directory called lib
in the project directory and save the following code snippet in a file called directus.js
in it:
import { createDirectus, rest, authentication } from '@directus/sdk';
const BACKEND_URL = "http://localhost:8055/"
const client = createDirectus(BACKEND_URL)
.with(authentication("json"))
.with(rest())
export default client;
Important: Because Next.js extends the native fetch API with a force-cache
configuration by default, you may sometimes run into scenarios where Next.js returns stale data. To fix this, update the rest()
composable to add the following option:
.with(
rest({
onRequest: (options) => ({ ...options, cache: 'no-store' }),
})
)
Creating the Posts page
Now that the Directus integration is ready, create the app page that will display a post using its slug. To do that, create a new file at ./app/[slug]/page.js
and save the following content in it:
import { React } from 'react';
import client from '@/lib/directus';
import { readItems } from '@directus/sdk';
export default async function Page({ params: {slug} }) {
try {
const post = await client.request(readItems(
'posts',
{filter: { slug: {_eq: slug}}}
));
console.log(post)
if (!post) {
return null;
}
const { title, content } = post[0];
return (<div>
<div>
<h1>{ title }</h1>
<p>{ content }</p>
</div>
</div>)
} catch (e) {
console.log(e)
return <div>This post does not exist</div>
}
}
Run the app using the npm run dev
command. Now, you can try creating a new posts
record in Directus and try going to http://localhost:3000/<your-slug>
to view it in your Next.js app:
Now, you are ready to set up content translations!
Set Up Content Translations
To set up your Directus instance to allow adding content translations, you will need to add a field to the posts
collection of type Translations while keeping all the default settings.
This will create two new collections in your data models list: languages
and posts_translations
The posts_translations
collection is used to retrieve the translation from Next.js, so you need to make this public by navigating to Settings -> Access Policies -> Public and adding posts_translations
with read
permissions.
Next, open the posts_translations
collection, and add the fields title
and content
with their corresponding types (matching the ones listed above).
Finally, create post content with relevant translations in 3-4 languages (feel free to use Google Translate).
title
: "Chandrayaan: India's Journey in Lunar Exploration"content
:
Chandrayaan is a series of lunar exploration missions developed by the Indian Space Research Organisation (ISRO) to advance India's space capabilities and scientific understanding of the Moon. The program began with Chandrayaan-1, launched in 2008, which was instrumental in confirming the presence of water molecules on the lunar surface. This groundbreaking discovery reshaped our understanding of the Moon’s geology and its potential for future exploration. The spacecraft carried a mix of Indian and international instruments, including NASA’s Moon Mineralogy Mapper, and operated for nearly a year before losing communication.
Building on this success, Chandrayaan-2 was launched in 2019, featuring an orbiter, lander (Vikram), and rover (Pragyan). While the lander failed to achieve a soft landing, the orbiter continues to send valuable data. In 2023, Chandrayaan-3 made history by successfully landing near the Moon’s south pole, making India the first nation to achieve this feat. The mission deployed the Pragyan rover, which conducted in-situ analysis of lunar soil and confirmed the presence of sulfur and other elements. The Chandrayaan program is a testament to India's growing expertise in space exploration and its ambitions for future interplanetary missions.
slug
: "chandrayaan-for-lunar-exploration"
Click on the "Translations" interface and select the language you want to add the translation for. You will find below the translations in German, French and Spanish but you can add as many additional languages as you like.
German Translation
title
: "Chandrayaan: Indiens Reise in die Mondforschung"content
:
Chandrayaan ist eine Reihe von Monderkundungsmissionen, die von der Indian Space Research Organisation (ISRO) entwickelt wurden, um Indiens Weltraumkapazitäten und sein wissenschaftliches Verständnis des Mondes zu verbessern. Das Programm begann mit Chandrayaan-1, das 2008 gestartet wurde und maßgeblich zur Bestätigung der Anwesenheit von Wassermolekülen auf der Mondoberfläche beitrug. Diese bahnbrechende Entdeckung hat unser Verständnis der Geologie des Mondes und seines Potenzials für zukünftige Erkundungen verändert. Die Raumsonde trug eine Mischung aus indischen und internationalen Instrumenten, darunter den Moon Mineralogy Mapper der NASA, und war fast ein Jahr lang in Betrieb, bevor die Kommunikation abbrach.
Aufbauend auf diesem Erfolg wurde Chandrayaan-2 2019 gestartet, bestehend aus einem Orbiter, einem Lander (Vikram) und einem Rover (Pragyan). Während der Lander keine weiche Landung hinbekam, sendet der Orbiter weiterhin wertvolle Daten. Im Jahr 2023 schrieb Chandrayaan-3 Geschichte, indem es erfolgreich in der Nähe des Südpols des Mondes landete, womit Indien die erste Nation war, der dieses Kunststück gelang. Die Mission setzte den Rover Pragyan ein, der vor Ort Analysen des Mondbodens durchführte und das Vorhandensein von Schwefel und anderen Elementen bestätigte. Das Chandrayaan-Programm ist ein Beweis für Indiens wachsende Expertise in der Weltraumforschung und seine Ambitionen für zukünftige interplanetare Missionen.
French Translation
title
: "Chandrayaan : le voyage de l'Inde dans l'exploration lunaire"content
:
Chandrayaan est une série de missions d’exploration lunaire développées par l’Organisation indienne de recherche spatiale (ISRO) pour faire progresser les capacités spatiales de l’Inde et sa compréhension scientifique de la Lune. Le programme a débuté avec Chandrayaan-1, lancé en 2008, qui a permis de confirmer la présence de molécules d’eau à la surface lunaire. Cette découverte révolutionnaire a remodelé notre compréhension de la géologie de la Lune et de son potentiel d’exploration future. Le vaisseau spatial transportait un mélange d’instruments indiens et internationaux, dont le Moon Mineralogy Mapper de la NASA, et a fonctionné pendant près d’un an avant de perdre la communication.
Fort de ce succès, Chandrayaan-2 a été lancé en 2019, avec un orbiteur, un atterrisseur (Vikram) et un rover (Pragyan). Bien que l’atterrisseur n’ait pas réussi à atterrir en douceur, l’orbiteur continue d’envoyer des données précieuses. En 2023, Chandrayaan-3 est entré dans l’histoire en atterrissant avec succès près du pôle sud de la Lune, faisant de l’Inde la première nation à réaliser cet exploit. La mission a déployé le rover Pragyan, qui a procédé à des analyses in situ du sol lunaire et a confirmé la présence de soufre et d'autres éléments. Le programme Chandrayaan témoigne de l'expertise croissante de l'Inde en matière d'exploration spatiale et de ses ambitions pour de futures missions interplanétaires.
Spanish Translation
title
: "Chandrayaan: el viaje de la India hacia la exploración lunar"content
:
Chandrayaan es una serie de misiones de exploración lunar desarrolladas por la Organización de Investigación Espacial de la India (ISRO) para mejorar las capacidades espaciales de la India y la comprensión científica de la Luna. El programa comenzó con Chandrayaan-1, lanzado en 2008, que fue fundamental para confirmar la presencia de moléculas de agua en la superficie lunar. Este descubrimiento revolucionario cambió nuestra comprensión de la geología de la Luna y su potencial para la exploración futura. La nave espacial llevaba una combinación de instrumentos indios e internacionales, incluido el Moon Mineralogy Mapper de la NASA, y funcionó durante casi un año antes de perder la comunicación.
Sobre la base de este éxito, Chandrayaan-2 se lanzó en 2019, con un orbitador, un módulo de aterrizaje (Vikram) y un explorador (Pragyan). Si bien el módulo de aterrizaje no logró un aterrizaje suave, el orbitador continúa enviando datos valiosos. En 2023, Chandrayaan-3 hizo historia al aterrizar con éxito cerca del polo sur de la Luna, convirtiendo a la India en la primera nación en lograr esta hazaña. La misión desplegó el explorador Pragyan, que realizó análisis in situ del suelo lunar y confirmó la presencia de azufre y otros elementos. El programa Chandrayaan es un testimonio de la creciente experiencia de la India en exploración espacial y sus ambiciones para futuras misiones interplanetarias.
Here's how your post will look once you've added all the translations
You will see that the "Translations" column shows the number of translations available for each post.
Now, all you need to do is configure your Next.js app to display these translations based on the language request by the client, and you're all done!
Set Up Language-Based Dynamic Routing
To do that, move the ./app/[slug]/page.js
file to ./app/[lang]/[slug]/page.js
, which adds a slug that allows the user to access one of en-US
, es-ES
, de-DE
, or fr-FR
translations of the content.
After moving the file, replace its contents with the following:
import { React } from 'react';
import client from '@/lib/directus';
import { readItems } from '@directus/sdk';
export default async function Page({ params }) {
const { lang, slug } = await params;
try {
const post = await client.request(readItems(
'posts',
{ filter: { slug: { _eq: slug } } }
)).then((data) => {
if (lang == "en-US")
return data
return client.request(readItems('posts_translations', {
filter: {
posts_id: {
_eq: data[0].id
},
languages_code: {
_eq: lang
}
}
}))
})
if (!post) {
return null;
}
const { title, content } = post[0];
return (<div>
<div>
<h1>{title}</h1>
<p>{content}</p>
</div>
</div>)
} catch (e) {
console.log(e)
return <div>This post does not exist</div>
}
}
This code snippet updates the fetching logic for the post. After fetching the post using it's slug, the app checks if en-US
was the requested language. If not, it queries the posts_translations
collection with the entered lang
value and displays that particular translation.
Make sure you restart the Next.js app after you have saved this file, because adding a new slug to the path of the file while the server is running will result in the server throwing errors.
Now, you can try navigating to the language-specific pages to view the relevant content.
For French, navigate to http://localhost:3000/fr-FR/chandrayaan-for-lunar-exploration to view the French version of the page:
For Spanish, navigate to http://localhost:3000/es-ES/chandrayaan-for-lunar-exploration to view the Spanish version of the page:
For German, navigate to http://localhost:3000/de-DE/chandrayaan-for-lunar-exploration to view the German version of the page:
And finally for US English, navigate to http://localhost:3000/en-US/chandrayaan-for-lunar-exploration to view the US English version of the page:
Summary
In this blog, you learned how to create multilingual content in Directus and access it in your Next.js application. Using Next.js dynamic routing, you learned how to retrieve the same content based on the language requested in URL.