i18n

Astro's Built-In Localized Routing

i18n

Astro has a built-in i18n module — locale routing, fallback, and helpers for building localized URLs.

4 min read Level 2/5 #astro#i18n#localization
What you'll learn
  • Configure locales and the default locale
  • Use locale-prefixed routes
  • Generate localized URLs

Astro ships an i18n module that handles locale-prefixed URLs, fallbacks, and localized link helpers. Configure once in astro.config.mjs.

Configure

import { defineConfig } from "astro/config";

export default defineConfig({
  i18n: {
    defaultLocale: "en",
    locales: ["en", "es", "fr"],
    routing: {
      prefixDefaultLocale: false,    // / for en, /es and /fr for others
      // fallback options below as needed
    },
    fallback: { fr: "en", es: "en" },
  },
});

/about serves English. /es/about and /fr/about serve those locales.

File Layout

Place locale-specific pages under matching folders:

src/pages/
├── about.astro              → /about (default locale)
├── es/
│   └── about.astro          → /es/about
└── fr/
    └── about.astro          → /fr/about

Reading the Current Locale

---
import { getLocaleByPath } from "astro:i18n";
const locale = getLocaleByPath(Astro.url.pathname) ?? "en";
---

<html lang={locale}>...</html>

Generating Localized URLs

---
import { getRelativeLocaleUrl, getAbsoluteLocaleUrl } from "astro:i18n";

const aboutFr = getRelativeLocaleUrl("fr", "/about");   // "/fr/about"
const home    = getRelativeLocaleUrl("en", "/");        // "/"
---

<a href={aboutFr}>À propos</a>

These helpers compute the right URL for each locale based on your routing config — so changing prefixDefaultLocale doesn’t break every link.

Fallback

fallback: { es: "en" } says: if a Spanish page doesn’t exist, serve the English version at the Spanish URL. Useful while translation is in progress.

Browser Language Detection

Use Astro.preferredLocale in server mode to redirect users to their preferred locale on first visit. Persist their choice with a cookie afterward.

Content Collections + i18n

For larger sites, store localized content in collections with a lang field on each entry, and query by locale:

---
const posts = await getCollection("blog", p => p.data.lang === locale);
---

Up Next

SEO basics — meta tags, OG images, sitemap.

SEO and Meta →