Adding New Pages
This guide shows you how to add a new page to a multilingual Astro project.
Two Approaches for Localization
Choose the approach based on your needs:
🗂️ Pattern A: [...pages].astro (Single File Pattern)
When to use: Simple pages without subpages
Examples: [...index].astro, [...blog].astro, [...contact].astro
import { buildLocalizedStaticPaths } from "@i18n/utils";
// Single-file catch‑all: [...pages].astro
export function getStaticPaths() {
return buildLocalizedStaticPaths("/pages", ["...pages"]);
}
📁 Pattern B: [pages]/[...index].astro (Folder Pattern)
When to use: Pages with additional files (MDX, images, components)
Examples: [about]/[...index].astro, [services]/[...index].astro
Advantages: Organized structure, easier maintenance
import { buildLocalizedStaticPaths } from "@i18n/utils";
// Folder pattern: [pages]/[...index].astro
export function getStaticPaths() {
return buildLocalizedStaticPaths("/pages", ["pages", "...index"]);
}
⚠️ CRITICAL - Synchronization
Ensure any localized segments (e.g.,
pages → strani) exist inroutes.ts.useTranslatedPath()relies on these mappings.
🔄 Flipping default language
You can switch the root language without touching your page files:
- In
src/i18n/ui.ts, set:defaultLang = "sl"(or your target)showDefaultLang = true | false(include prefix for the default language)
- Root becomes
/(whenshowDefaultLang = false) or/{defaultLang}/(whentrue). - All page URLs adapt automatically because
getStaticPaths()usesuseTranslatedPath(). - Verify home, about, pages, and navigation paths.
Tip: Use useTranslatedPath(lang)("/pages") in examples to avoid hard-coded localized segments.
🛠️ Practical Example: Adding “Services” Page
Let’s add a new page /services → /sl/storitve:
Step 1: Create File
src/pages/[services]/[...index].astro
Step 2: Configure getStaticPaths
import { useTranslations, buildLocalizedStaticPaths } from "@i18n/utils";
import Base from "@layouts/Base.astro";
import "@styles/markdown.css";
export function getStaticPaths() {
return buildLocalizedStaticPaths("/services", ["services", "...index"]);
}
const { lang } = Astro.props;
const t = useTranslations(lang);
const { Content, frontmatter } = await import(`./_services-${lang}.mdx`);
---
<Base
title={frontmatter?.title}
meta={{
description: frontmatter?.description,
keywords: frontmatter?.keywords,
}}
>
<section id="md-content">
<Content />
</section>
</Base>
Step 3: Add to routes.ts
export const routes: Record<string, Record<string, string>> = {
sl: {
about: "o-projektu",
blog: "spletni-dnevnik",
pages: "strani",
services: "storitve", // ← Matches "storitve" above
},
};
Step 4: Add to Navigation
const navigationData = [
{
label: "menu.list.services",
href: "/services", // ← English path
children: [],
},
];
Step 5: Create Content Files
_services-en.mdx_services-sl.mdx
Step 6: Add Translations (optional, if not reading from MDX)
In locales/en/services.json:
{
"head": {
"title": "Our Services",
"description": "Professional services we offer"
},
// If needed, add more translations here
"title": "Our Services",
"description": "We provide comprehensive solutions for your business needs."
}
In locales/sl/services.json:
{
"head": {
"title": "Naše storitve",
"description": "Strokovne storitve, ki jih ponujamo"
},
// If needed, add more translations here
"title": "Naše storitve",
"description": "Zagotavljamo celovite rešitve za vaše poslovne potrebe."
}
Add to locales/en/menu.json:
{
"list": {
"services": "Services"
}
}
Add to locales/sl/menu.json:
{
"list": {
"services": "Storitve"
}
}
🎯 Final Result
Assuming defaultLang = "en" and showDefaultLang = false:
| Language | URL | Works |
|---|---|---|
| 🇬🇧 English | /services | ✅ |
| 🇸🇮 Slovenian | /sl/storitve | ✅ |
| 🧭 Navigation | Automatic | ✅ |
| 🔄 Language switcher | Switches language | ✅ |
| 🍞 Breadcrumbs | Shows path | ✅ |
Congratulations! New page successfully added! 🎉