If you've tried to build a multilingual site with Astro, you know the pain.

Astro is incredible for static sites. Fast, flexible, developer-friendly. But the moment you need two or more languages, things get complicated quickly.

You end up with duplicated page files, hardcoded locale prefixes, manual slug management, and a growing pile of workarounds that make your codebase harder to maintain with every new page.

We hit this wall building otro.digital, a fully bilingual English/Spanish site with translated URLs, a knowledge base, blog, case studies, and dozens of pages. Existing i18n solutions either didn't work with Astro 5's new Content Layer API, required dynamic rendering (killing the static performance advantage), or simply didn't handle translated URL slugs.

So we built our own. And today, we're releasing it as an open-source package: astro-i18n-next.

What It Does

astro-i18n-next is a complete internationalization integration for Astro 5 static sites. One createI18n() call in your Astro config, and you get:

Translated URL Routing

Your English /about/ page automatically becomes /es/sobre/: no catch-all routes, no duplicated files, no manual path wiring. Define slug translations right in your page files:

// src/pages/about.astro
export const slugs = { es: 'sobre' };

The integration discovers these at build time and generates all the locale-prefixed routes for you.

A Single Virtual Import

Instead of importing helpers from five different files, everything comes from one place:

import { t, localePath, switchLocalePath } from 'virtual:i18n';

t() for translations (powered by i18next), localePath() for building locale-aware URLs, switchLocalePath() for language switchers. Clean, predictable, no boilerplate.

Multilingual Markdown

Write both languages in a single markdown file using simple locale markers:

---
title:
  en: "Getting Started"
  es: "Primeros pasos"
---

Your English content here.

<!-- locale:es -->

Tu contenido en español aquí.

This works with Astro 5's Content Layer API through a custom loader. One file per piece of content, not two. Your content stays together and stays in sync.

Content Collection Slug Translation

For content collections (blog posts, knowledge base articles, case studies), define translated slugs in frontmatter:

slugs:
  en: "email-marketing-fundamentals"
  es: "fundamentos-email-marketing"

The integration builds slug maps automatically and localePath() uses them to generate correct URLs everywhere: index pages, navigation, breadcrumbs, language switchers.

i18next Under the Hood

Full i18next integration with dot-notation keys, fallback chains, and plugin support. If you've used i18next before, it works exactly the way you'd expect. If you haven't, the defaults are sensible and the learning curve is gentle.

Fully Static, Zero Runtime Cost

Everything resolves at build time. No client-side JavaScript for routing. No runtime locale detection on static pages. Your multilingual site is just as fast as a single-language Astro site.

Why We Open-Sourced It

We built this for ourselves, but the problems it solves aren't unique to us.

Every agency and developer building multilingual Astro sites is hitting the same walls: messy file duplication, broken slug translation, content collections that don't play well with i18n, manual hreflang management.

We'd rather contribute a solid solution to the ecosystem than watch everyone reinvent the same workarounds.

The package is MIT licensed, published on npm as @otrodigital/astro-i18n-next, and comes with full documentation covering everything from installation to advanced use cases.

Getting Started

Install the package and its peer dependency:

npm install @otrodigital/astro-i18n-next i18next

Add it to your Astro config:

import { createI18n } from '@otrodigital/astro-i18n-next';

const i18n = createI18n({
  defaultLocale: 'en',
  locales: ['en', 'es'],
  translations: {
    en: { /* ... */ },
    es: { /* ... */ },
  },
});

export default defineConfig({
  integrations: [i18n.integration()],
});

That's it. The documentation site walks you through everything else: translated routes, multilingual content, language switchers, SEO tags, and more.

What's Next

We're actively using this on our own production sites, so it will keep evolving based on real-world needs. On the roadmap:

  • Dynamic route injection: automatic locale variants for [...slug] routes without file duplication
  • Enhanced content loader: support for MDX and richer frontmatter schemas
  • Community feedback: if you're building multilingual Astro sites, we want to hear what's missing

The package is on GitHub. Issues, PRs, and feedback are welcome.

The Bottom Line

i18n shouldn't be the hardest part of building a multilingual site. With Astro handling the static rendering and astro-i18n-next handling the localization, you can focus on what actually matters: creating great content in every language.

Read the docs →

View the source on GitHub →

Install from npm →

Have questions or want help setting up i18n for your Astro project? Start a conversation →