Skip to main content

Module i18n

Module i18n 

Source
Expand description

§Internationalisation (i18n) routing primitives

Provides hreflang link injection, per-locale sitemap generation, and a language switcher HTML helper.

§Overview

The I18nPlugin scans the site output directory for locale-prefixed subdirectories (e.g. /en/, /fr/) and:

  1. Injects <link rel="alternate" hreflang="…"> tags into every HTML page that exists in multiple locales.
  2. Adds an x-default alternate pointing to the default locale.
  3. Generates per-locale sitemaps (sitemap-en.xml, sitemap-fr.xml, …) with xhtml:link alternates.

The injection is idempotent — pages that already contain hreflang links are skipped.

§Pairing pages across locales

Before anything can be injected, the plugin has to decide which pages in different locales are translations of one another. It builds a matrix of key -> {locale -> path} and treats every page sharing a key as one document.

A page’s key is its translation_key front-matter value when it declares one, and its locale-relative path otherwise:

---
title: "À propos"
translation_key: "about"
---

Path matching alone cannot pair /about/ with /fr/a-propos/ — the paths differ, so each is a singleton and neither receives any hreflang at all. Because that failure is silent, it is easy to ship. A shared translation_key pairs them regardless of slug.

Pages without a key keep pairing by path, so a site with no translation_key anywhere produces exactly the matrix it produced before the field existed.

The value is read from the front-matter sidecars written by crate::frontmatter::emit_sidecars, because the plugin runs after compilation and can no longer see the source front matter.

§Where the default locale lives

The default locale may occupy the site root, with only the other locales taking a URL segment (/about/ alongside /fr/a-propos/) — the default in Hugo, Astro and Next.js. This is detected, not configured — the root locale is used when the default locale has no output directory of its own and HTML exists outside the other locale directories.

§Reciprocity

Each alternate link is labelled with the resolved language of the document it points at, not with the bare locale directory name. Labelling by directory lets the two halves of a pair disagree — an English page calling its Hindi alternate hi while the Hindi page calls itself hi-IN — which fails Google’s reciprocity requirement and the hreflang audit gate with it. An authored locale code is preserved byte-for-byte (zh-tw stays zh-tw); a resolved language replaces it only on a genuine front-matter override.

Structs§

I18nConfig
Parsed [i18n] configuration section.
I18nPlugin
I18n plugin that injects hreflang links and generates per-locale sitemaps.

Enums§

UrlPrefixStrategy
Strategy for constructing locale-specific URLs.

Functions§

generate_lang_switcher_html
Generates an HTML snippet for a language switcher navigation.
negotiate_locale
Given a list of preferred locales (from Accept-Language) and a list of available locales (directories on disk), returns the best match.
parse_accept_language
Parses an Accept-Language header value into a sorted list of locale preferences (highest quality first).