Configuration
Learn more about i18n configuration.
Goal: Add Italian support in 4 steps (~15 minutes).

Update src/i18n/ui.ts
Add the language to the languages object:
export const languages = { fr: { name: 'Français', flag: '🇫🇷' }, de: { name: 'Deutsch', flag: '🇩🇪' }, it: { name: 'Italiano', flag: '🇮🇹' },} as const;Add all translations to the ui object:
export const ui = { fr: { /* French translations */ }, de: { /* German translations */ }, it: { 'nav.home': 'Home', 'nav.work': 'I nostri lavori', 'nav.about': 'Informazioni', 'nav.contact': 'Contattaci', 'business.name': 'La tua azienda', 'business.tagline': 'Il tagline della tua azienda', 'site.title': 'Titolo del tuo sito', 'site.description': 'Descrizione del tuo sito per SEO', 'author.name': 'Tu Numero', 'author.email': 'tu@email.com', 'theme.toggle': 'Cambia argomento', // ... copy all other keys from FR or DE },} as const;Update astro.config.mjs
Add the locale to the Astro configuration:
i18n: { defaultLocale: "fr", locales: ["fr", "de", "it"], routing: { prefixDefaultLocale: false, },},Create Page Folder
Create src/pages/it/index.astro:
---import BaseLayout from "../../layouts/BaseLayout.astro";import Header from "../../components/Header.astro";import Landing from "../../components/Landing.astro";---
<BaseLayout> <Header /> <Landing /></BaseLayout>Test
Start your dev server and visit:
http://localhost:4321/it/✅ Success indicators:
/it/lang="it" attributeThe BaseLayout.astro checks if the current locale exists in the languages object:
const lang: Language = (currentLocale && currentLocale in languages) ? currentLocale as Language : defaultLang;No hardcoded checks! If you add a language to ui.ts, it’s automatically supported.
The middleware.ts redirects based on the languages object:
if (preferredLang in languages && preferredLang !== defaultLang) { return redirect(`/${preferredLang}/`);}Fully scalable - Any language you add will be auto-detected from the browser.
The LanguageSelector.astro imports from ui.ts:
import { languages } from "@/i18n/ui";It automatically displays all available languages with their flags.
The easiest way is to:
ui.tsMake sure to include all these keys (copy from existing languages):
nav.*business.*portfolio.*owner.*contact.*site.*author.*Some values like author.email and author.phone should be the same across all languages (unless you have different contact info per region).
src/├── i18n/│ ├── ui.ts ← Add language here (Step 1)│ └── utils.ts ← No changes needed (dynamic)├── layouts/│ └── BaseLayout.astro ← No changes needed (dynamic)├── middleware.ts ← No changes needed (dynamic)├── pages/│ ├── index.astro ← French (default)│ ├── de/│ │ └── index.astro│ └── it/ ← Create this (Step 3)│ └── index.astro└── astro.config.mjs ← Add locale (Step 2)// 1. src/i18n/ui.tsexport const languages = { fr: { name: 'Français', flag: '🇫🇷' }, de: { name: 'Deutsch', flag: '🇩🇪' }, es: { name: 'Español', flag: '🇪🇸' },} as const;
export const ui = { fr: { // ... French translations }, de: { // ... German translations }, es: { 'nav.home': 'Inicio', 'nav.work': 'Nuestros Trabajos', 'nav.about': 'Acerca de', 'nav.contact': 'Contacto', // ... rest of translations },} as const;// 2. astro.config.mjslocales: ["fr", "de", "es"],3. Create: src/pages/es/index.astro4. Test at: http://localhost:4321/es/Check that it’s added to the languages object in ui.ts with the as const modifier.
Verify all translation keys exist in the ui object for that language.
Clear your browser cache or test in incognito. The middleware caches the accept-language header.
Make sure you have the as const on both the languages and ui objects in ui.ts.
Configuration
Learn more about i18n configuration.
Customization
Customize content and components.
Styling
Style your multilingual site.