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 chrome 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.

Was this page helpful?