Skip to content

MultiLanguage Support — 2. Consuming Multilingual Content from Content Island with Vanilla TypeScript

00:00 / 00:00

Consuming Content (Vanilla)

Instead of using a framework like Astro, Nuxt, or Next, we’ll work with plain TypeScript. This keeps the example simple and avoids requiring prior knowledge of any specific ecosystem.


1. Creating the project

First, create an empty folder, for example: myproducts

Initialize a Vite project:

npm create vite@latest .

Clean up the default code (like the logo and CSS), and leave a basic HTML file.

Install the project dependencies:

npm install

Now install the Content Island API client:

npm install @content-island/api-client

2. Defining the data model

We’ll consume the products we previously created in Content Island. To do this, define the model interface:

./src/model.ts

import type { Media } from "@content-island/api-client";

export interface Product {
  id: string;
  language: "en" | "es";
  name: string;
  description: string;
  price?: number;
  image: Media;
}

Let’s refactor the language field into a separate type:

import type { Media } from "@content-island/api-client";

+ export type Language = "en" | "es";

export interface Product {
  id: string;
-  language: "en" | "es";
+  language: Language;
  name: string;
  description: string;
  price?: number;
  image: Media;
}

3. Initializing the client

Create a file to configure the Content Island client.

./api.ts

import { createClient } from "@content-island/api-client";

const client = createClient({
  accessToken: "your_api_token_here", // Replace with your actual token
});

Important: In a real project, the API token should be stored securely, such as in environment variables.

Import the model:

import { createClient } from "@content-island/api-client";
+ import type { Product, Language } from "./model";

4. Fetching content

Create a function to fetch products. Without multilingual support, it would look like this:

./api.ts

export const getProducts = async (): Promise<Product[]> => {
  const response = await client.getContentList<Product>({
    contentType: "Product",
  });
  return response;
};

But since we're using multiple languages, we update the function to receive a language code:

- export const getProducts = async (): Promise<Product[]> => {
+ export const getProducts = async (language: Language): Promise<Product[]> => {
  const response = await client.getContentList<Product>({
    contentType: "Product",
+   language,
  });
  return response;
};

5. Displaying the products

Since we’re using vanilla TypeScript, rendering the products in the browser is a bit more manual than with frameworks like Astro, Nuxt, or Next. But don’t worry—it’s easy to follow and we’ll go step by step.

./main.ts

import "./style.css";
import type { Language } from "./model";
import { getProducts } from "./api";

const displayProducts = async (language: Language) => {
  const products = await getProducts(language);

  const appContainer = document.getElementById("app");
  if (!appContainer) {
    console.error("App container (#app) not found in the DOM.");
    return;
  }

  let productsContainer = document.getElementById("products");
  if (!productsContainer) {
    productsContainer = document.createElement("div");
    productsContainer.id = "products";
    appContainer.appendChild(productsContainer);
  }

  productsContainer.innerHTML = "";

  products.forEach((product) => {
    const productElement = document.createElement("div");
    productElement.innerHTML = `
      <img src="${product.image.url}" alt="${product.name}" style="max-width:300px" />
      <h2>${product.name}</h2>
      <p>${product.description}</p>
      <small>Price: ${product.price}</small>
    `;
    productsContainer.appendChild(productElement);
  });
};

Call it at the end of main.ts:

./main.ts
Add at the end of the file

displayProducts("en"); // Change to "es" to see products in Spanish

Run the project:

npm run dev

You should now see the list of products in the browser—in this case in English. You could switch to Spanish by changing the code, but ideally, users should be able to select the language through the UI.


6. Adding a language selector

Let’s allow the user to choose the language from the interface.

We’ll create a language selector that appears at the top and updates the displayed products based on the selected language.

./main.ts

const setupLanguageSelector = () => {
  const appContainer = document.getElementById("app");
  if (!appContainer) {
    console.error("App container (#app) not found.");
    return;
  }

  const languageSelector = document.createElement("select");
  languageSelector.id = "language-selector";
  languageSelector.innerHTML = `
    <option value="en">English</option>
    <option value="es">Español</option>
  `;

  languageSelector.addEventListener("change", (event) => {
    const selectedLanguage = (event.target as HTMLSelectElement)
      .value as Language;
    displayProducts(selectedLanguage);
  });

  appContainer.prepend(languageSelector);
};

And call it along with displayProducts:

setupLanguageSelector();
displayProducts("en");

Result

If everything is set up correctly, you’ll see a list of products when you run the project. Switching the language from the selector will update the displayed content automatically.

In this guide, we’ve seen a simple and direct way to consume multilingual content from Content Island using plain TypeScript without any frameworks.