Localisation
Seven locales ship with the layer, and every configured string takes three forms.
The theme's own strings — navigation labels, search, the version banner, the 404 —
ship translated in en-GB, en-US, de-DE, es-ES, fr-FR, pt-PT and
pt-BR. A site picks which of them it serves with locales, and
i18n.defaultLocale decides which one is served without a URL prefix.
locales is read at build time: locales decide routes and hreflang, not just
what a component draws, so changing the list needs a rebuild.
i18n's own locales array merges across layers instead of replacing, so
declaring ['de-DE'] there adds nothing and removes nothing — the other six stay
routed, indexed and announced in hreflang. duxt.locales is the key that
actually narrows it.
Every configured string takes three forms
Anything you write into the config — a label, a title, a description — may be a literal, an i18n key, or a record of one string per locale:
label: 'Repository' // literal
label: 'app.nav.repository' // your own key
label: { 'en-GB': 'Repository', 'de-DE': 'Repository' } // per locale
Which one it is, is decided by whether the string is a registered key. So a
single-language site never meets the other two forms, and a site with a handful
of strings in five languages needs no locale files at all — the record form
resolves through the base language, so pt-PT covers pt-BR and en-GB covers
en-US.
Do not reach into the layer's keys
duxt.defaults.* translates the defaults the layer itself ships. Those keys are
internal: renaming one is not a breaking change of the layer, and i18n answers a
missing key by printing the key — so a consumer depending on one would find out
from a reader, not from a build. Use a literal, your own key, or the record form.
Paths and links
Only paths are localised. useDuxtPath() gives the path the documentation is
at, with the locale segment stripped; useDuxtLink() writes one back out as a
link, adding the segment again. An absolute URL, a mail link or a bare hash passes
through untouched. Anything computing a documentation path should go through the
pair rather than reading the route directly.
Translated pages
The interface and the pages are two separate decisions. A site that says nothing serves one tree in every locale — the interface changes language, the Markdown does not — and that is the right shape for most documentation.
locales on a source is what adds the second half:
sources: [{ path: 'docs', locales: ['en-GB', 'de-DE'] }]
The default locale is the tree in path itself, with no folder of its own, so
adding this key never moves a page that is already published. Every other
language is a folder inside it — docs/de-DE/ — or somewhere else entirely; see
Several languages.
/de-DE/guides/deploying and /guides/deploying are the same content path in
two collections. The segment belongs to i18n's routing, never to a collection —
which is why switching language keeps the reader on the same page, and why a
missing translation is answered by one more query rather than by a redirect.
When a page has no translation
The reader gets the nearest language that has it, with a banner saying so, and
the page is left out of the index under noindex with a canonical pointing at
the language that carries it. The chain is the one the layer already applies to
strings:
- the locale itself —
de-DEreadsde-DE - its base language —
de-DEreads adetree, so onept/folder can serve bothpt-PTandpt-BR - a sibling of the same language —
pt-BRreadspt-PTbefore falling out of Portuguese fallbackLocalefrom vue-i18n, the same value a missing string resolves through- the untranslated original
A 404 is deliberately not among them: a gap in a translation is the writer's, and answering it by hiding the page punishes the reader for it.
Writing direction
The active locale also supplies the document direction. Components use logical start and end positions, so navigation, sheets, arrows and page furniture mirror when a consumer adds an RTL locale. Technical material does not blindly mirror: code, commands, paths, API names and other left-to-right syntax retain the direction in which they can be read.
duxt ships no RTL locale of its own today. Direction-aware means a consumer can add one without forking the theme; it is not a claim that one of the seven built-in locales is RTL.