Skip to content
duxt

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.

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.

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.

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:

  1. the locale itself — de-DE reads de-DE
  2. its base language — de-DE reads a de tree, so one pt/ folder can serve both pt-PT and pt-BR
  3. a sibling of the same language — pt-BR reads pt-PT before falling out of Portuguese
  4. fallbackLocale from vue-i18n, the same value a missing string resolves through
  5. 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.

Was this page helpful?