Skip to content

Astro i18n — Internationalization and Multi-Language Sites

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Astro i18n. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn Astro i18n: configure multi-language support, translate routes, manage locale-specific content, and implement language switching for global audiences.

In this lesson, you'll set up Internationalization in Astro, create locale-specific routes, translate content, and build a language switcher component.

What You'll Learn

How to configure i18n routing, create locale-specific pages, manage translations, implement language switching, and handle SEO for multi-language sites.

Why It Matters

Internationalization expands your audience to non-English speakers. Proper i18n setup ensures search engines index each language version correctly.

Real-World Use

DodaTech serves tutorials in English, Spanish, and French using Astro's i18n routing, with separate routes for each locale.

flowchart LR
    A[URL Request] --> B{Locale Detection}
    B -->|/en/| C[English Content]
    B -->|/es/| D[Spanish Content]
    B -->|/fr/| E[French Content]
    style B fill:#ff5a03,color:#fff

Setting Up Locales

Create locale-specific content directories:

src/pages/
  en/
    index.astro
    about.astro
  es/
    index.astro
    about.astro
  fr/
    index.astro
    about.astro

Configure i18n in astro.config.mjs:

import { defineConfig } from "astro/config";

export default defineConfig({
  i18n: {
    defaultLocale: "en",
    locales: ["en", "es", "fr"],
    fallback: {
      es: "en",
      fr: "en",
    },
  },
});

Language Switcher

Create a language switcher component:

---
const { currentLocale } = Astro.props;
const locales = [
  { code: "en", label: "English" },
  { code: "es", label: "Espanol" },
  { code: "fr", label: "Francais" },
];
---
<nav>
  {locales.map(locale => (
    <a
      href={`/${locale.code}${Astro.url.pathname.replace(/^\/[a-z]{2}/, "")}`}
      class={locale.code === currentLocale ? "active" : ""}
    >
      {locale.label}
    </a>
  ))}
</nav>

Translating Content

Use a translation helper:

// src/i18n/translations.ts
const translations = {
  en: { welcome: "Welcome", about: "About Us" },
  es: { welcome: "Bienvenido", about: "Sobre Nosotros" },
  fr: { welcome: "Bienvenue", about: "A Propos" },
};

export function t(locale: string, key: string): string {
  return translations[locale]?.[key] ?? translations["en"][key];
}

Usage in a page:

---
import { t } from "../i18n/translations";
const locale = Astro.params.locale || "en";
---
<h1>{t(locale, "welcome")}</h1>

RTL Support

Add right-to-left support for Arabic, Hebrew, and other RTL languages:

// astro.config.mjs
i18n: {
  defaultLocale: "en",
  locales: ["en", "ar", "he"],
  routing: {
    prefixDefaultLocale: true,
    rtl: ["ar", "he"],
  },
},

Apply RTL styling:

<html dir={rtlLocales.includes(locale) ? "rtl" : "ltr"} lang={locale}>

SEO for i18n

Add hreflang tags for multi-language SEO:

<head>
  <link rel="alternate" hreflang="en" href="https://example.com/en/about/" />
  <link rel="alternate" hreflang="es" href="https://example.com/es/about/" />
  <link rel="alternate" hreflang="x-default" href="https://example.com/about/" />
</head>

Common Mistakes

  1. Not setting defaultLocale: Without a default locale, Astro doesn't know which language to serve for unprefixed URLs.
  2. Missing fallback translations: When a translation key is missing, the fallback locale's value should be used.
  3. Ignoring RTL layout: Arabic and Hebrew text needs right-to-left alignment. Update CSS for RTL locales.
  4. Not prefixing the default locale: hreflang tags work best when every locale has a separate URL, including the default.
  5. Forgetting canonical URLs: Each language version should link to itself as canonical to avoid duplicate content issues.

Practice Questions

  1. How do you configure default locale in Astro? Answer: Set defaultLocale in the i18n section of astro.config.mjs.

  2. What is the purpose of hreflang tags? Answer: They tell search engines which language versions of a page exist, preventing duplicate content penalties.

  3. How do you handle missing translations? Answer: Fall back to the default locale's translation. Configure fallback in the i18n config.

  4. Why prefix the default locale URL? Answer: It ensures every page version has a unique URL, which is required for proper hreflang implementation.

Challenge

Build a three-language site (English, Spanish, French) with a language switcher, fallback translations, and proper hreflang tags in the page head.

Mini Project

Create a multi-language documentation site with two locales. Each locale has its own content collection. Implement a language switcher that preserves the current page path when switching languages.

FAQ

Can I translate content collections per locale?

: Yes. Create separate content collection directories per locale (e.g., src/content/en/blog/, src/content/es/blog/).

How do I detect the user's preferred language?

: Check the Accept-Language header on the server or use navigator.language on the client.

Does Astro support automated translation workflows?

: Not built-in. Use external translation services and manage locale files manually or with a CMS.

Can I use i18n with SSR?

: Yes. i18n works with both static and SSR modes.

What's Next

Learn about Astro Deployment for deploying your Astro site to production hosting platforms.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro