@comvi/nuxt
The Nuxt module (Nuxt ^3 || ^4) that wires @comvi/vue into an app:
auto-imported composables, locale routing, SSR loading and a <T> component. The composables
have their own reference.
Exports
Section titled “Exports”@comvi/nuxt: the module (default export); typesNuxtI18nOptions,ModuleOptions,LocaleObject,LocalePrefixMode,LocaleCookieConfig,LocaleCookieOptions,LocaleDetectionConfig,LocaleDetectionSource,ResolveAcceptLanguage,ResolvedLocaleCookie,ResolvedLocaleDetection,NuxtInstanceFactory,NuxtInstanceFactoryOptions,NuxtServerInstance,NuxtServerLoaderInstance,NuxtI18nSetup,NuxtI18nSetupContext,NuxtI18nSetupNuxtApp,NuxtI18nSetupEvent,NuxtI18nSetupRuntimeConfig,NuxtDefaultTranslationParams,RegisteredNuxtInstance,ComviNuxtInstanceRegistry,ResolvedNuxtInstance,CheckedNuxtI18nSetup,ResolvedRoutingConfig,NuxtI18nRuntimeConfig,NuxtI18nPrivateRuntimeConfig, andI18n,MessagesMap,I18nLoaderApi,LoaderFn,TranslationKeys,TranslationParams,TranslationResultfrom core.@comvi/nuxt/i18n:defineComviI18n,createI18n,icuCompiler,loader,attachLoader,plugins,definePlugin,devtools; typeNuxtInstanceFactory.@comvi/nuxt/setup:defineComviSetup.- Auto-imported in
server/:useTranslation,loadMessages,getRequestI18n,getServerRuntimeConfig; their typesUseTranslationOptions,UseTranslationResult,ServerI18n,ServerTranslationFunction,LoadMessagesOptions,MessagesMap,ComviServerRuntimeConfig; for an explicit annotation import from the declaring file,@comvi/nuxt/runtime/server/utils/useTranslation,…/utils/loadMessagesor…/utils/runtime-config(the directory is not an export). - Components:
<T>,<NuxtLinkLocale>; template global$t.
Module options
Section titled “Module options”| Option | Type | Default | Meaning |
|---|---|---|---|
locales |
(string | LocaleObject)[] |
[] |
Supported locales; LocaleObject is { code, name?, dir?, iso? }. An empty list warns at build time |
defaultLocale |
string |
'en' |
Locale when none is detected |
localePrefix |
'always' | 'as-needed' | 'never' |
'as-needed' |
URL prefix mode: as-needed prefixes every locale but the default, always prefixes all, never none |
messages |
I18nOptions['messages'] |
none | Inline catalogs, forwarded through public runtime config into every i18n instance |
head |
boolean |
true |
Write <html lang> and <html dir> from the active locale, on the server and on every client switch; lang is the locale object’s iso or its code, dir its declared dir or the language’s direction. false leaves <html> to you |
apiKey |
string |
none | Forwarded as i18n.apiKey; set it through private runtimeConfig.comvi.apiKey (NUXT_COMVI_API_KEY) |
defaultNs |
string |
'default' |
Default namespace |
ns |
string[] |
none | Namespaces init() loads, core’s ns; omitted, only defaultNs loads. Forwarded into every constructed instance and into the factory’s options |
fallbackLocale |
string | string[] |
defaultLocale |
Fallback chain |
defaultParams |
Record<string, string | number | boolean> |
none | JSON-serializable interpolation defaults; locale, ns, fallback, markers are rejected |
icu |
boolean |
false |
Use icuCompiler. With a comvi.i18n.ts file it arrives as compiler, the last key of the factory’s options |
i18nModule |
string |
./comvi.i18n.* |
Path to the factory module, when the file is not at the convention path. Unset, the module looks for ./comvi.i18n.* under srcDir, then rootDir, and logs the path it found; a set path that does not resolve fails the build. Next’s config option names a module that exports an instance, this one names a module that exports a factory |
setup |
string |
./comvi.setup.* |
Path to the setup hook file |
localeCookie |
false | string | LocaleCookieOptions |
'i18n_locale' |
The locale cookie: a name, its attributes, or false to persist nothing |
localeDetection |
false | LocaleDetectionConfig |
{ order: ['query', 'cookie', 'accept-language'] } |
Where the locale comes from after the URL path; false leaves the path alone in charge |
basicHtmlTags |
string[] |
none | Tags rendered without a handler; forwarded as tagInterpolation to the app plugin and to the Nitro per-request instance alike |
Every option lives under the comvi key in nuxt.config.ts. localeCookie and localeDetection are the two options @comvi/next’s createMiddleware
takes, with the same values and defaults; only the default cookie name differs. A key inside either that the schema does not know fails the build, naming the key
and what to write instead, as in [@comvi/nuxt] `comvi.localeDetection.cookieName` is not an option: use `comvi.localeCookie.name`.;
the same check runs over runtimeConfig.public.comvi, with that prefix in the message.
LocaleCookieOptions
Section titled “LocaleCookieOptions”| Option | Type | Default | Meaning |
|---|---|---|---|
name |
string |
'i18n_locale' |
Cookie name |
maxAge |
number |
31536000 |
Lifetime in seconds, one year |
secure |
boolean |
true, off in development |
Secure flag; nuxt dev drops it so localhost over HTTP keeps the cookie |
sameSite |
'lax' | 'strict' | 'none' |
'lax' |
SameSite attribute |
domain |
string |
none, the current domain only | Send the cookie to this domain and its subdomains |
LocaleDetectionConfig
Section titled “LocaleDetectionConfig”| Option | Type | Default | Meaning |
|---|---|---|---|
order |
Array<'query' | 'cookie' | 'header' | 'accept-language'> |
['query', 'cookie', 'accept-language'] |
Sources after the URL path; query and header do nothing until queryParam and headerName are set; header and accept-language are read on the server only; an unknown entry is refused at build time, and the middleware ignores one that reaches it |
queryParam |
string |
none | Query parameter read for 'query' ('lang' reads ?lang=de); values outside locales are ignored |
headerName |
string |
none | Request header read for 'header', matched case-insensitively |
resolveAcceptLanguage |
(acceptLanguage, locales, defaultLocale) => string | undefined |
built-in matcher | Replaces the Accept-Language matcher; copied into the build as source, so it must be self-contained, with no import or variable from nuxt.config |
The route middleware skips /_nuxt*, /api and /api/* and resolves the locale in this order: the path prefix, then
localeDetection.order, then defaultLocale. Under as-needed a prefixless non-root path is the
default locale’s URL, decided after any query source that leads the order and before the rest;
/ is too only on a navigation from the same page under a locale prefix (/de to /), otherwise
localeDetection.order decides it and a non-default locale redirects to its prefixed root.
export default defineNuxtConfig({ modules: ['@comvi/nuxt'], comvi: { defaultLocale: 'en', locales: ['en', 'de'], localeCookie: { name: 'locale', sameSite: 'strict' }, localeDetection: { order: ['query', 'cookie', 'accept-language'], queryParam: 'lang' }, },});| Mode | Default locale URL | Other locale URL |
|---|---|---|
as-needed |
/about |
/de/about |
always |
/en/about |
/de/about |
never |
/about |
/about |
Routes are cloned at build time as /{locale}{path} named {name}___{locale}; under
always the unprefixed originals are removed and a page with a [locale] param is dropped; under
never pages are left as they are.
export default defineNuxtConfig({ modules: ['@comvi/nuxt'], comvi: { defaultLocale: 'en', locales: [ { code: 'en', name: 'English' }, { code: 'de', name: 'Deutsch' }, ], messages: { en: { nav: { home: 'Home' } }, de: { nav: { home: 'Startseite' } } }, },});Composing the i18n instance
Section titled “Composing the i18n instance”With no comvi.i18n.ts file the module builds a bare instance, plus compiler: icuCompiler when
icu is true. Every other capability comes from that file.
The comvi.i18n.ts factory
Section titled “The comvi.i18n.ts factory”type NuxtInstanceFactory<C = WrapperI18nInstance, D = {}> = (options: NuxtInstanceFactoryOptions<D>) => C
type NuxtInstanceFactoryOptions<D> = { locale: string; fallbackLocale?: string | string[]; defaultNs?: string; ns?: string[]; // comvi.ns verbatim devMode?: boolean; apiKey?: string; messages?: I18nOptions['messages']; compiler?: MessageCompiler; // icuCompiler when comvi.icu is true, last key tagInterpolation?: { basicHtmlTags?: string[] }; // both instances ssrLocale?: string; // client plugin call only} & (keyof D extends never ? {} : { defaultParams: D })Default-export a factory that returns a new core instance from createI18n on every call, never
a VueI18n. The module calls it once for the client and once per server request; in development
the module’s generated code throws when the factory returns an instance it already returned. The
Nitro per-request instance receives locale, fallbackLocale, defaultNs, ns, devMode,
apiKey, messages, tagInterpolation and defaultParams; only ssrLocale is client-only.
defineComviI18n(factory)
Section titled “defineComviI18n(factory)”function defineComviI18n<C extends WrapperI18nInstance<D>, D = {}>( factory: (options: NuxtInstanceFactoryOptions<D>) => C,): (options: NuxtInstanceFactoryOptions<D>) => Cimport { createI18n, defineComviI18n, loader } from '@comvi/nuxt/i18n';
export default defineComviI18n((options) => createI18n(options).use( loader({ en: () => import('./locales/en.json'), de: () => import('./locales/de.json'), }), ),);From @comvi/nuxt/i18n. It types options and returns the factory unchanged, so the composed instance’s
type still reaches the setup hook. A factory written as (options) => … with satisfies NuxtInstanceFactory,
or a plain function typed with NuxtInstanceFactoryOptions from @comvi/nuxt, is the same thing spelled longer.
Server utilities
Section titled “Server utilities”function useTranslation(event: H3Event, options?: UseTranslationOptions): Promise<UseTranslationResult>function loadMessages(event: H3Event, locale: string, options?: { namespaces?: string[] }): Promise<MessagesMap>function getRequestI18n(event: H3Event, locale: string): Promise<NuxtServerInstance>function getServerRuntimeConfig(event?: H3Event): ComviServerRuntimeConfig
interface UseTranslationOptions { ns?: string; // scopes t(); an empty string counts as not given locale?: string; // overrides detection}interface UseTranslationResult { t: ServerTranslationFunction; locale: string; hasTranslation: (key: string, opts?: { locale?: string; ns?: string }) => boolean;}type ServerI18n = UseTranslationResult // the name @comvi/next uses for the same shapetype NuxtServerInstance<D = {}> = WrapperI18nInstance<D>type NuxtServerLoaderInstance<D = {}> = WrapperI18nInstance<D> & I18nLoaderApitype MessagesMap = Record<string, Record<string, TranslationValue>> // @comvi/core's, re-exported by @comvi/nuxt| Utility | Meaning |
|---|---|
useTranslation(event, options?) |
Request-scoped t, locale and hasTranslation. Locale precedence: options.locale, a locale prefix on the request path, then localeDetection.order (the query parameter, the cookie, a configured header, Accept-Language), then defaultLocale. A prefixless path is not read as the default locale here, because an API route carries no prefix to omit |
loadMessages(event, locale, options?) |
Loads namespaces (default [defaultNs]) and returns a map keyed "locale:namespace"; warns once per instance when it has no loader and nothing is cached |
getRequestI18n(event, locale) |
The request-scoped instance |
getServerRuntimeConfig(event?) |
Public and private Comvi runtime config together |
loadMessages() and useTranslation() load the locale you pass and every locale in the
instance’s fallbackLocale chain, for each namespace asked for, the same contract as the
@comvi/next helpers. A pair that fails to load is reported through loadError and onError,
attempted once per request, and left out of the map; the call still resolves.
One instance is built per request and per locale and destroyed after the response, so calling
useTranslation() or loadMessages() afterwards throws.
useTranslation(event, options?)
Section titled “useTranslation(event, options?)”export default defineEventHandler(async (event) => { const { t, locale } = await useTranslation(event, { ns: 'api' }); return { message: t('hello'), locale };});Setup hook
Section titled “Setup hook”type NuxtI18nSetup<C extends WrapperI18nInstance = ResolvedNuxtInstance> = (context: NuxtI18nSetupContext<C>) => void | Promise<void>
interface NuxtI18nSetupContext<C> { i18n: VueI18n<{}, C> | C; // VueI18n in the app plugin, the core instance in server utilities core: C; // the core instance on both runtimes runtime: 'client' | 'server'; nuxtApp?: NuxtI18nSetupNuxtApp; event?: NuxtI18nSetupEvent; runtimeConfig?: NuxtI18nSetupRuntimeConfig;}function defineComviSetup(setup: NuxtI18nSetup): NuxtI18nSetupcomvi.setup default-exports a hook that runs before init() on the app plugin and on each request
instance. ResolvedNuxtInstance is read from the factory’s return type at build time, so a hook with
no type argument compiles only against the capabilities the factory composed.
import { defineComviSetup } from '@comvi/nuxt/setup';
export default defineComviSetup(({ core, runtimeConfig }) => { core.setFallbackLocale(runtimeConfig?.public?.comvi?.fallbackLocale ?? 'en');});Components
Section titled “Components”<T> is @comvi/vue’s <T>, auto-imported. <NuxtLinkLocale> takes every <NuxtLink> prop plus:
| Prop | Type | Default | Meaning |
|---|---|---|---|
to |
string | Record<string, unknown> |
required | Prefixed through useLocalePath(); external, mailto:, query-only and hash-only targets pass through |
locale |
string |
current locale | Locale for this link |
$t(key, params?), $tRaw and $i18n are available in every template.
Runtime config
Section titled “Runtime config”interface NuxtI18nRuntimeConfig { // useRuntimeConfig().public.comvi comvi: { locales: string[]; localeObjects: Record<string, LocaleObject>; defaultLocale: string; localePrefix: LocalePrefixMode; head?: boolean; messages?: I18nOptions['messages']; defaultNs: string; ns?: string[]; fallbackLocale: string | string[]; defaultParams?: NuxtDefaultTranslationParams; basicHtmlTags?: string[]; localeCookie: ResolvedLocaleCookie | false; // every default applied localeDetection: ResolvedLocaleDetection | false; // without resolveAcceptLanguage, which travels as source };}interface NuxtI18nPrivateRuntimeConfig { comvi: { apiKey?: string } } // server-onlyinterface ResolvedRoutingConfig { // useAppConfig().comvi.routing locales: readonly string[]; localeObjects: Record<string, LocaleObject>; defaultLocale: string; localePrefix: LocalePrefixMode; cookieName: string | false; // false when localeCookie is false}Read next
Section titled “Read next”@comvi/nuxtcomposables:useI18n, the capability pair, the routing composables,useLocaleHeadanduseRouteConfig.- Nuxt: the guide: the module,
comvi.i18n.tsand the worked setups. @comvi/vue: theVueI18nclass the module wires in.