Translations
A site can be published in several languages. The first language is the default and
keeps its URLs; every other one is served under its own prefix, such as
/es/, with its own navigation, search, llms.txt and UI
strings. The header gets a language picker, and a page not translated yet stays in
the navigation, marked with the language it is written in.
Configure the languages
languages:
- code: en
label: English
- code: es
label: Español
- code: zh
label: 简体中文Each language accepts:
| Field | Default | Purpose |
|---|---|---|
code |
none, required |
The URL prefix and the file name suffix: lowercase letters, digits and
-, starting with a letter.
|
label |
none, required | The name shown in the language picker. |
locale |
the code |
The tag for <html lang>, hreflang and dates, such as
pt-BR.
|
dir |
rtl for Arabic, Hebrew, Persian, Urdu and a few more |
ltr or rtl, written to
<html dir>.
|
flag |
the locale's region, else the language's usual country |
A two-letter country code for the picker's flag, such as br; one
without a bundled flag shows none.
|
messages |
none | UI strings replacing the built-in ones; see below. |
Without languages the site is a single English one, and nothing below
applies. A code listed twice, an unknown message key, or a section whose prefix sits
under another language's prefix (/es/…) fails the build.
Translate a page
A translation is a file beside its original, named with the language's code before
.html. It is served under the language's prefix and paired with the
original by URL:
- index.html —
/ - index.es.html —
/es/ -
guides
- install.html —
/guides/install/ - install.es.html —
/es/guides/install/
- install.html —
A suffix that names no configured language stays part of the name, so
vite.config.html is still an English page. To keep translations in a
folder of their own, or to name a file freely, set the language in its head instead;
a file already under the language's folder is not prefixed twice:
<meta name="language" content="es" />
<meta name="path" content="/guides/install/" />---
language: es
path: /guides/install/
---
A translation pairs with its original only when both share a URL below the language
prefix, so give a renamed file the same path as its original. A
language the config does not list fails the build.
Translate the config
The site's title, description and banner, a
link's title, and a section's title,
siteTitle and siteDescription take one text for every
language, or a map by language code. A language missing from the map gets the
default language's text:
title:
en: Acme Docs
es: Documentación de Acme
sections:
- title: { en: Guide, es: Guía, zh: 指南 }
prefix: /
- title: Blog
type: blog
prefix: /blog/
Every section and every link with a prefix is mirrored under each
language's prefix: the Spanish blog lives at /es/blog/, with its own
index, tag pages and RSS feed listing the Spanish posts, then the default ones not
translated yet. A changelog section builds its pages in every language, keeping the
release notes as written; those copies point their canonical URL at the default
language's and stay out of the sitemap. A custom section whose
url is a page of the site leads to that page's translation, when the
open language has one.
Pages not translated yet
A language lists every default-language page it has no translation of, so its
navigation keeps the same shape. Such an entry links to the original and carries the
default language's code as a badge, with "Not translated yet" as its tooltip. The
untranslated page is built once, in its own language; search and
llms.txt list only a language's own pages.
The language picker links each language to this page's version in it, else to that
language's home. A language without a home page of its own,
index.es.html, gets a redirect from /es/ to its first
page; so does the default language without an index.html. Hosts that
read _redirects, such as Cloudflare and Netlify, and
htmlpress start
redirect on the server; others fall back to a redirect page.
UI strings
Htmlpress' own strings, such as "Contents", "Previous" and "Edit this page", and the dates, are bundled in English, German, Spanish, French, Japanese, Russian and Chinese, picked by the locale's language. Any of them can be replaced per language:
languages:
- code: en
label: English
messages:
page.edit: Edit on GitHub
- code: pt
label: Português
locale: pt-BR
messages:
toc.title: Nesta página
nav.previous: Anterior
nav.next: Próximo
A language htmlpress does not bundle falls back to English for the strings it does
not set. The keys are the ones in
messages/en.yaml; {name} placeholders such as {date} are filled in.
date.format and date.months shape every date shown to
readers.
What a translated page gets
-
<html lang>and, for right-to-left languages,<html dir="rtl">. -
With
siteset, an hreflang alternate for every language that has the page, plusx-defaultpointing at the default language's version, and anog:locale. -
Its language's search index,
_htmlpress/search.<code>.json, and a Markdown copy andllms.txtunder the language's prefix. -
The
<htmlpress-language>picker, which a layout escape places like any other element; it is removed on a single-language site.
See also
-
Configuration: every key of
htmlpress.yaml. - Article Sections: how prefixes and section matching work.
-
Frontmatter: the page's own metadata,
<meta name="language">included.
Created with ❤ and Htmlpress