Multi-Language

Add translations to your site with filename-based i18n — per-language URLs, RSS, sitemaps, and discovery files.

Overview

page uses a filename-based translation system. It's fully backward compatible — single-language sites work identically with no configuration.

How It Works

Default language content uses plain filenames:

content/posts/hello-world.md     → /posts/hello-world
content/pages/about.md           → /about

Translations add a language suffix before the extension:

content/posts/hello-world.es.md  → /es/posts/hello-world
content/pages/about.es.md        → /es/about

Items with the same slug across languages are automatically linked as translations.

Configuration

Enable multi-language support by adding language sections to page.toml:

[site]
language = "en"
title = "My Site"

[languages.es]
title = "Mi Sitio"
description = "Un sitio web estático"

[languages.fr]
title = "Mon Site"
description = "Un site web statique"

Each language can override title and description. The default language is set in [site].language.

Creating Translations

Use the --lang flag with page new:

page new post "Hello World"             # English (default)
page new post "Hola Mundo" --lang es    # Spanish translation

Or create files manually — the language suffix must match a configured language code:

about.md      → English (default)
about.es.md   → Spanish
about.fr.md   → French
about.xx.md   → Ignored (xx not configured)

Per-Language Output

When multi-language is enabled, page generates per-language versions of:

OutputDefault languageOther languages
Index pagedist/index.htmldist/{lang}/index.html
RSS feeddist/feed.xmldist/{lang}/feed.xml
LLM discoverydist/llms.txtdist/{lang}/llms.txt
Search indexdist/search-index.jsondist/{lang}/search-index.json
Sitemapdist/sitemap.xml (all languages, with alternates)

URL Structure

Non-default languages get a /{lang}/ prefix:

/posts/hello-world          # English
/es/posts/hello-world       # Spanish
/fr/posts/hello-world       # French

hreflang Tags

All bundled themes automatically emit <link rel="alternate" hreflang="..."> tags when translations exist, helping search engines serve the right language.

Language Switcher

Bundled themes include a language switcher UI when translations is non-empty. It shows links to all available translations of the current page.

Template Variables

VariableDescription
{{ lang }}Current page language code
{{ translations }}Array of {lang, url} for available translations
{{ site.language }}Default site language

Use in templates:

{% if translations %}
<nav class="lang-switcher">
  {% for t in translations %}
    {% if t.lang == lang %}
      <strong>{{ t.lang }}</strong>
    {% else %}
      <a href="{{ t.url }}">{{ t.lang }}</a>
    {% endif %}
  {% endfor %}
</nav>
{% endif %}