# Appendix A: Internationalization Guide

Course: [Astro](https://www.devtutorials.ai/learn/astro) · Section: Appendix
Source: https://www.devtutorials.ai/learn/astro/appendix/i18n-guide

> Build an Astro site in more than one language: locale folders, the i18n config, translation dictionaries, getRelativeLocaleUrl(), hreflang and fallbacks.

## Appendix A: Internationalization (i18n) Guide

- **Internationalization** (often written **i18n**: "i", 18 letters, "n") means making a site work in more than one language.
- Asha wants her journal in **English** and **Tamil**.
- Astro gives you three things: a folder per language, an `i18n` block in the config, and URL helpers in `astro:i18n`.

**Simple lesson:** one folder per language, an `i18n` config block, and helpers to build the right links.

## Step 1: A Folder per Language

```text
src/pages/
├── index.astro          → /        (English, the default)
├── about.astro          → /about
└── ta/
    ├── index.astro      → /ta/     (Tamil)
    └── about.astro      → /ta/about
```

- The default language can live at the root (`/about`) or in its own folder (`/en/about`).
- Each other language gets a folder named with its **language code**: `ta`, `hi`, `fr`.

## Step 2: The i18n Config

```js
// astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  i18n: {
    locales: ["en", "ta"],
    defaultLocale: "en",
    routing: {
      prefixDefaultLocale: false, // English at /about, Tamil at /ta/about
    },
  },
});
```

- `locales`: every language the site has.
- `defaultLocale`: the main language.
- `prefixDefaultLocale: true` puts English under `/en/` too.
- Optional `fallback: { ta: "en" }` shows the English page when a Tamil page is missing.

## Step 3: Translations and Links

- Keep the words for each language in one dictionary file.
- Build links with `getRelativeLocaleUrl(locale, path)` from `astro:i18n`. It adds the language folder only when needed.
- Set `<html lang={locale}>` on every page, so screen readers and search engines know the language.

Press **▶ Run**. Switch between **English** and **தமிழ்**. The menu text and links change with the language.

    <head><meta charset="utf-8" /><title>{t.home}</title></head>
    <body>
      <nav>
        <a href={getRelativeLocaleUrl(lang, "")}>{t.home}</a> ·
        <a href={getRelativeLocaleUrl(lang, "about")}>{t.about}</a> |
        <a href={getRelativeLocaleUrl("en", path)}>English</a> ·
        <a href={getRelativeLocaleUrl("ta", path)}>தமிழ்</a>
      </nav>
      <slot />
    </body>
</html>
`,
    "src/pages/index.astro": `---
---

<Base lang="en" path=""><h1>{ui.en.hello}</h1></Base>
`,
    "src/pages/about.astro": `---
---

<Base lang="en" path="about"><h1>About Asha</h1></Base>
`,
    "src/pages/ta/index.astro": `---
---

<Base lang="ta" path=""><h1>{ui.ta.hello}</h1></Base>
`,
    "src/pages/ta/about.astro": `---
---

<Base lang="ta" path="about"><h1>ஆஷாவைப் பற்றி</h1></Base>
`,
  }}
/>

- **[JS]** In `ui.js`, leave out `as const` and the `Lang` type. In the layout, leave out `interface Props` and `type Lang`.

Content collections work well for translated posts: put them in `src/content/posts/en/` and `src/content/posts/ta/`, and filter with `getCollection("posts", (p) => p.id.startsWith("ta/"))`.

## More i18n Tools

<div className="tscroll">

| Tool | What it does |
|---|---|
| `Astro.currentLocale` | The language of the current page, from its URL |
| `Astro.preferredLocale` | The visitor's browser language, if the site has it (on-demand pages) |
| `getAbsoluteLocaleUrl(locale, path)` | A full URL with `site`, for canonical and `hreflang` links |
| `getRelativeLocaleUrlList(path)` | The same page in every language, for a language switcher |
| `routing: "manual"` | Turn off automatic routing and write your own middleware |

</div>

- Add `hreflang` links in the `<head>`, so search engines show the right language:
  `<link rel="alternate" hreflang="ta" href="https://asha.dev/ta/about" />`.

Do not translate with automatic tools alone. Ask a native speaker to check, especially buttons and error messages.

i18n is about more than words: dates, numbers and money also change. Use `Intl.DateTimeFormat("ta-IN")` and `toLocaleString("ta-IN")`.

## Common mistakes

<div className="tscroll">

| Mistake | Correct idea |
|---|---|
| Hard-coded `/about` links on Tamil pages | Use `getRelativeLocaleUrl("ta", "about")` |
| `<html lang="en">` on every page | Set `lang` from the page's locale |
| Text spread across many components | Keep each language's words in one dictionary |
| No fallback for missing pages | Add `fallback: { ta: "en" }` or translate every page |

</div>
