Fix: The Provided Locale Does Not Exist in Astro

Error message:
The provided locale does not exist.
Internationalization 2025-01-25

What Causes This Error?

This error occurs when you use a locale that isn’t defined in your i18n.locales configuration. All locales used in your site must be declared in the Astro config.

The Problem

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],  // Only en and es configured
  },
});
---
// ❌ Using 'fr' which isn't in locales
import { getRelativeLocaleUrl } from 'astro:i18n';
const url = getRelativeLocaleUrl('fr', '/about');
---

The Fix

Add Locale to Config

// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr'],  // ✅ Add 'fr'
  },
});

Or Use Configured Locale

---
import { getRelativeLocaleUrl } from 'astro:i18n';
// ✅ Use a configured locale
const url = getRelativeLocaleUrl('es', '/about');
---

Common Scenarios

Basic i18n Setup

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr', 'de'],
    routing: {
      prefixDefaultLocale: false,
    },
  },
});

Using Locale Codes

// With region codes
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'en-US', 'en-GB', 'es', 'es-MX'],
  },
});
---
// ✅ Must match exactly
getRelativeLocaleUrl('en-US', '/about');  // OK
getRelativeLocaleUrl('en-us', '/about');  // ❌ Case matters!
---

Custom Locale Paths

export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: [
      'en',
      {
        path: 'spanish',  // URL will use /spanish/
        codes: ['es', 'es-ES'],
      },
    ],
  },
});

Dynamic Locale Detection

---
import { getRelativeLocaleUrl } from 'astro:i18n';

// ✅ Validate locale before using
const validLocales = ['en', 'es', 'fr'];
const requestedLocale = Astro.params.locale;

const locale = validLocales.includes(requestedLocale)
  ? requestedLocale
  : 'en';

const url = getRelativeLocaleUrl(locale, '/about');
---

Locale in Routes

src/pages/
├── index.astro          # Default locale (en)
├── es/
│   └── index.astro      # Spanish
└── fr/
    └── index.astro      # French - must be in config!

Get Available Locales

---
// Access configured locales
const locales = Astro.currentLocale;
const preferredLocale = Astro.preferredLocale;
const preferredLocaleList = Astro.preferredLocaleList;
---

Translation Helpers

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

// ✅ Build locale-aware URLs
const currentLocale = Astro.currentLocale || 'en';
const aboutUrl = getRelativeLocaleUrl(currentLocale, '/about');
---

<a href={aboutUrl}>About</a>

Fallback Locale

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr'],
    fallback: {
      fr: 'en',  // Fall back to English for French
    },
  },
});

TypeScript Safety

// src/i18n.ts
export const locales = ['en', 'es', 'fr'] as const;
export type Locale = typeof locales[number];

export function isValidLocale(locale: string): locale is Locale {
  return locales.includes(locale as Locale);
}
---
import { isValidLocale } from '../i18n';

const locale = Astro.params.locale;
if (!isValidLocale(locale)) {
  return Astro.redirect('/404');
}
---

Quick Checklist

  • All locales must be in i18n.locales array
  • Locale codes are case-sensitive
  • Match exact format (en vs en-US)
  • Validate dynamic locales before use
  • Create page folders for each locale