Layers and domains
A Nuxt layer can carry the i18n config and the locales/ folder for several apps, and each app adds or overrides what it needs. This page shows that, and how one build serves several domains.
Share config and translations
// base/nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-i18n-micro'],
i18n: {
locales: [
{ code: 'en', iso: 'en-US' },
{ code: 'de', iso: 'de-DE' },
{ code: 'fr', iso: 'fr-FR' },
],
defaultLocale: 'en',
},
})
// shop/nuxt.config.ts
export default defineNuxtConfig({
extends: ['../base'], // a layer directory or package, not a nuxt.config file
i18n: {
locales: [
{ code: 'es', iso: 'es-ES' }, // added
{ code: 'fr', disabled: true }, // the base layer's fr, switched off here
],
},
})
- Config: scalar options in the app replace the layer's.
localesarrays from all layers are combined, and entries with the samecodemerge into one with the app's fields winning, so an app can add a locale or set fields such asdisabled: trueon an inherited one. - Translations:
locales/of every layer are merged key by key, layer first and app last, so a key inshop/locales/en.jsonoverrides the same key inbase/locales/en.json. Page files (locales/pages/<page>/) merge the same way. - Pages:
$defineI18nRouteis read from the pages of every layer.
To merge folders that are not part of a layer, list them in additionalTranslationDirs.
Multiple domains
One build serves every domain. List each locale with its domain; baseDefault makes it the default of that host:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-i18n-micro'],
i18n: {
strategy: 'prefix_except_default',
defaultLocale: 'en',
locales: [
{ code: 'en', iso: 'en-US', baseUrl: 'https://example.com', baseDefault: true },
{ code: 'de', iso: 'de-DE', baseUrl: 'https://example.de', baseDefault: true },
{ code: 'nl', iso: 'nl-NL', baseUrl: 'https://example.de' },
{ code: 'fr', iso: 'fr-FR' },
],
},
})
Point both domains at the same server. The request's host decides the rest:
- Default: the host's
baseDefaultlocale. Without one, the build default if the host serves it, else the host's first locale. - Served locales: the locales of that host, plus every locale with no
baseUrl. Onexample.dethat isde,nlandfr. - Locales of other domains are link targets.
$localePath,$localeRoute,$switchLocalePath,<i18n-switcher>andhreflanggive absolute URLs on theirbaseUrl, and$switchLocalenavigates there. On this host their URLs are a 404, and a cookie orAccept-Languagecannot pick them. - A link to another domain goes through
$localePathor<i18n-link>:<NuxtLink :to="$localePath('/contact', 'de')">,<i18n-link :to="$localeRoute('/contact', 'de')">. The router takes no absolute object, so<NuxtLink :to="$localeRoute(...)">androuter.push($localeRoute(...))stay on this origin. Onlocalhostor a preview host every locale with abaseUrlis such a link, the current one too. In code usenavigateTo($localePath('/contact', 'de'), { external: true }), or$switchRoute. - Any other host gets the build config, with every
baseUrllocale as a link target. Nothing from the request is echoed: canonical andhreflangusemetaBaseUrl, else the build default'sbaseUrl(a default with nobaseUrlneedsmetaBaseUrlorsite.url, see SEO). - Payload files in
public/are static: any host returns any locale's file. Per-domain generate publishes only that domain's.
example.de under each strategy, with de: '/kontakt' as a custom path of contact:
| Strategy | / | Default locale's page | Other URLs |
|---|---|---|---|
prefix_except_default | de | /kontakt | /de/kontakt and /en/contact are a 404, /contact redirects to /kontakt |
prefix_and_default | de | /kontakt and /de/kontakt, links use /kontakt | /en/contact and /contact are a 404 |
prefix | redirects to /de | /de/kontakt | /kontakt redirects to /de/kontakt, /en/contact is a 404 |
no_prefix | de | /kontakt | a custom path of a locale on another domain is a 404 |
Under prefix a link from another domain keeps the prefix, since the unprefixed URL would only redirect. Under no_prefix a link to another domain lands on that host's default locale: the URL cannot name a second one.
Things to know:
- Behind a proxy the host comes from
Host. If the proxy puts the public host inX-Forwarded-Hostinstead, settrustForwardedHost, and only when the proxy overwrites that header. A proxy that sends neither cannot serve a domain build. See Behind a proxy or CDN. app.baseURLbelongs inbaseUrltoo:baseUrl: 'https://example.de/shop'withapp.baseURL: '/shop'.- Hosts match exactly.
www.example.deis another host: redirect it at the edge, or set thatbaseUrlon the locale. Only one host per locale. - Caches must key on the host. A CDN normally does. Nitro's route cache keys on the path, so in a domain build the module adds
hosttocache.variesof everyswrandcacherule, andx-forwarded-hostwithtrustForwardedHost. A rule withcache: falsestays as written.isris the platform's cache: check that it keys on the host. - Custom paths of two host defaults must not collide. The unprefixed records share one router, so
/xcannot be one page onexample.deand another onexample.com. - Prerendered pages: a
prerender: trueroute rule innuxt buildrenders once, with no host, and the file answers every domain. Leave pages that differ per domain to the server, or generate per domain. noPrefixRedirectgoes by the locale of the host and the visitor, on every host.hashMode: the host picks the render as above, links to another domain carry the route in the hash (https://example.com/#/contact).ssr: false: the browser reads the domain fromlocation.host, so a host with no server still resolves.- Runtime overrides apply first. A runtime
disabledLocalesholds on every host, with one exception: underprefix_except_defaultandprefix_and_defaultthe default of a host stays enabled on its host, as its pages are the unprefixed records. Underprefixandno_prefixthe host falls to the next locale it serves. A runtimedefaultLocaleapplies to unknown hosts only.
For a static site, generate once per domain.
One app per domain
A shared layer with one small app per domain still works, when the domains need different pages or modules. Each app sets its own defaultLocale on top of the same locales list. A locale on another domain is a 404 in that app, as above.
Choosing the locale in code
For a single instance answering every domain with the request's own origin in SEO tags, see SEO; to choose the locale from the host in code, see Custom locale detection.