Internationalization (i18n)
Multi-language documentation with locale-specific translations, RTL support, and language switching
Last updated: March 15, 2026
MinimalDoc supports internationalization (i18n) for building documentation in multiple languages. Translations are stored separately from shared content, with automatic fallback to the default locale when translations are missing.
Configuration
Enable i18n in your config.yaml:
i18n:
enabled: true
default_locale: "en"
fallback: "en"
hide_default_locale: true
show_untranslated: true
locales:
- code: "en"
name: "English"
direction: "ltr"
- code: "fr"
name: "Français"
direction: "ltr"
- code: "ar"
name: "العربية"
direction: "rtl"
flag: "🇸🇦"
selector:
position: "header"
show_flags: false
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | false |
Enable multi-language documentation |
default_locale |
string | "en" |
Default locale code |
fallback |
string | "en" |
Fallback locale for missing translations |
hide_default_locale |
boolean | true |
Omit locale prefix from URLs for default locale |
show_untranslated |
boolean | true |
Show fallback content with warning when translation missing |
locales |
array | [] |
List of locale definitions |
selector.position |
string | "header" |
Locale selector position: header or sidebar |
selector.show_flags |
boolean | false |
Show flag icons in selector |
Locale Definition
Each locale in the locales array supports:
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | Yes | Locale code (e.g., en, fr, de, zh-CN) |
name |
string | Yes | Display name (e.g., English, Français) |
direction |
string | No | Text direction: ltr (default) or rtl |
flag |
string | No | Optional flag emoji or icon |
Directory Structure
Shared Content
All pages in your docs/ directory serve as the default locale content. These are shared across all locales unless overridden by a translation.
Translation Files
Create locale-specific translations in the __translations__/ directory:
docs/
getting-started/
install.md # Default (English) content
config.md # Default content
features/
search.md # Default content
__translations__/
fr/
getting-started/
install.md # French translation
config.md # French translation
features/
search.md # French translation
de/
getting-started/
install.md # German translation (partial)
Translation files must match the path and filename of the original content. If a translation file exists, it replaces the default content for that locale. Missing translation files fall back to the default locale content.
URL Structure
With hide_default_locale: true (default):
/docs/getting-started/ # Default locale (en)
/fr/docs/getting-started/ # French
/de/docs/getting-started/ # German
/ar/docs/getting-started/ # Arabic
With hide_default_locale: false:
/en/docs/getting-started/ # English (explicit)
/fr/docs/getting-started/ # French
/de/docs/getting-started/ # German
RTL Support
For right-to-left languages (Arabic, Hebrew, Persian), set direction: "rtl" in the locale definition:
locales:
- code: "ar"
name: "العربية"
direction: "rtl"
- code: "he"
name: "עברית"
direction: "rtl"
MinimalDoc automatically:
- Sets the
dir="rtl"attribute on the HTML element - Applies RTL-specific CSS rules for layout mirroring
- Adjusts navigation and sidebar positioning
Fallback Behavior
When a page is not translated for a locale:
- If
show_untranslated: true, the fallback locale content is displayed with a visual indicator - If
show_untranslated: false, the page is omitted from that locale’s navigation
The fallback chain is: requested locale → fallback locale → default_locale.
Version Integration
i18n works with multi-version documentation. The URL structure combines both:
/fr/v2/docs/getting-started/ # French, version 2
/de/v1/docs/getting-started/ # German, version 1
When both versioning and i18n are enabled:
- Default locale + default version:
/docs/... - Default locale + other version:
/v1/docs/... - Other locale + default version:
/fr/docs/... - Other locale + other version:
/fr/v1/docs/...
Locale Selector
A dropdown selector allows users to switch languages:
- Displays the current locale name (and flag if configured)
- Lists all available locales
- Persists selection in localStorage
- Redirects to the same page in the selected locale (or locale root if page unavailable)
Position options:
| Position | Description |
|---|---|
header |
Selector appears in the site header |
sidebar |
Selector appears in the sidebar navigation |
Build Output
When i18n is enabled, the build generates:
public/
docs/ # Default locale pages
fr/
docs/ # French pages
de/
docs/ # German pages
locales.json # Locale metadata for JS
The locales.json file contains metadata for client-side locale switching:
{
"current": "en",
"default": "en",
"hideDefaultLocale": true,
"locales": [
{"code": "en", "name": "English", "direction": "ltr", "active": true},
{"code": "fr", "name": "Français", "direction": "ltr", "active": false}
]
}
Translation Workflow
- Write documentation in your default locale
- Create
__translations__/{locale}/directories for each target locale - Copy files you want to translate, maintaining the same path structure
- Translate the content while keeping the same frontmatter structure
- Build the site to generate all locale variations
Untranslated pages automatically use fallback content, so you can translate incrementally.