@comvi/vue
The Vue 3 binding. A VueI18n wraps a @comvi/core instance in Vue
reactivity and is the plugin you pass to app.use().
Exports
Section titled “Exports”- Values:
createI18n,createI18nFromCore,VueI18n,T,useI18n,useI18nLoader,useI18nPlugins,I18N_INJECTION_KEY,loader,attachLoader,plugins,definePlugin,icuCompiler,devtools. - Types:
VueI18nOptions,VueI18nCoreOptions,AnyVueI18n,I18nInstance(alias ofVueI18n),UseInstanceIdentityError,UseI18nReturn,UseI18nLoaderReturn,UseI18nPluginsReturn,ComponentMap,DevtoolsOptions,I18n, every@comvi/coretype.
There is no TProps type; @comvi/core/tags is not re-exported.
createI18n(options)
Section titled “createI18n(options)”function createI18n<D>(options: VueI18nOptions<D>): VueI18n<D, I18n<D>>
type VueI18nOptions<D> = I18nOptions<D> & { ssrLocale?: string }Builds a core i18n instance and wraps it. VueI18nOptions is every core
I18nOptions plus:
| Option | Type | Default | Meaning |
|---|---|---|---|
ssrLocale |
string |
none | The locale the server rendered with. It paints on the first render when that locale’s catalogs are already available, inline or loaded earlier; with createI18nFromCore on an instance that still has to load them, the switch lands when the load completes |
import { createI18n, loader, plugins } from '@comvi/vue';
export const i18n = createI18n({ locale: 'en', ssrLocale: 'en' }) .use(loader({ en: () => import('./locales/en.json') })) .use(plugins());createI18nFromCore(core, options?)
Section titled “createI18nFromCore(core, options?)”function createI18nFromCore<D, C extends WrapperI18nInstance<D>>(core: C, options?: VueI18nCoreOptions): VueI18n<D, C>
interface VueI18nCoreOptions { ssrLocale?: string }Wraps an instance built elsewhere, keeping its exact type as core. It constructs nothing
itself.
import { createI18n as createCore } from '@comvi/core';import { createI18nFromCore, loader } from '@comvi/vue';
const core = createCore({ locale: 'en' }).use(loader({ en: () => import('./locales/en.json') }));
export const i18n = createI18nFromCore(core, { ssrLocale: 'en' });VueI18n
Section titled “VueI18n”Reactive state
Section titled “Reactive state”| Member | Type |
|---|---|
core |
C, the wrapped i18n instance, readonly |
locale |
Ref<string> getter; the setter takes a string |
isLoading, isInitializing, isInitialized |
Readonly<Ref<boolean>> |
cacheRevision |
Readonly<Ref<number>> |
dir |
ComputedRef<'ltr' | 'rtl'> |
messagesCache |
ComputedRef<ReadonlyMap<string, FlattenedMessages>> |
defaultParams |
ComputedRef<DefaultParamsSnapshot<D>> |
loadedLocales, activeNamespaces |
ComputedRef<string[]> |
defaultNamespace |
ComputedRef<string> |
Methods
Section titled “Methods”t(key, params?): stringtRaw(key, params?): TranslationResultsetLocale(locale: string): Promise<void>hasTranslation(key: string, opts?: { locale?: string; namespace?: string; checkFallbacks?: boolean }): ComputedRef<boolean>hasLocale(locale: string, namespace?: string): ComputedRef<boolean>hasTranslationNow(key: string, opts?): booleanhasLocaleNow(locale: string, namespace?: string): booleanuse<T extends WrapperI18nInstance<D>>(installer: (core: C) => T): VueI18n<D, T>init(): Promise<this>destroy(): Promise<void>install(app: App): void| Method | Meaning |
|---|---|
setLocale(l) |
Resolves once the translations loaded |
hasTranslation, hasLocale |
Allocate a computed(); call inside setup() or an effectScope |
hasTranslationNow, hasLocaleNow |
Plain booleans, safe anywhere |
use(installer) |
Runs installer(this.core) and returns the same wrapper, retyped. An installer returning another object throws with code: 'E_USE_INSTANCE_IDENTITY'. Compose before app.use(i18n); a later .use warns once in development |
init() |
Initializes the wrapped instance |
destroy() |
Resolves once plugin cleanups finished; a cleanup rejection goes to onError with source 'plugin-cleanup'; repeat calls return the same promise |
install(app) |
Idempotent per app. Starts init() fire-and-forget, provides the instance under I18N_INJECTION_KEY and registers $t, $tRaw, $i18n. On the server, await i18n.init() before renderToString |
The .use() deadline is app.use(i18n), because install starts init() and init() drains
the plugin queue once. A plugin queued after that waits for the next init(), which never
comes in a normal app.
Pass-throughs to the wrapped instance: addMessages, clearMessages, on,
setFallbackLocale, setDefaultParams, reportError, formatNumber, formatDate,
formatCurrency, formatRelativeTime. Put .use() on the wrapper, not on .core: the latter
runs the installer but leaves the static type of core unchanged.
useI18n(ns?)
Section titled “useI18n(ns?)”function useI18n<D extends DefaultTranslationParams = {}, NS extends string | undefined = undefined>(ns?: NS): UseI18nReturn<D, NS>Throws when app.use(i18n) did not run.
| Returned | Type | Meaning |
|---|---|---|
t |
NamespaceBoundTranslateFn<NS, D, string> |
Translate; scoped to ns |
tRaw |
NamespaceBoundTranslateFn<NS, D, TranslationResult> |
Rich-text half |
locale |
Ref<string> |
Assigning .value switches without a promise |
setLocale |
(locale: string) => Promise<void> |
Resolves once loaded |
messagesCache |
ComputedRef<ReadonlyMap<string, FlattenedMessages>> |
Reactive cache view |
cacheRevision |
Readonly<Ref<number>> |
Messages-cache revision; config changes have their own tracking |
isLoading, isInitializing, isInitialized |
Readonly<Ref<boolean>> |
Loading flags |
dir |
ComputedRef<'ltr' | 'rtl'> |
Text direction |
addMessages, setFallbackLocale, setDefaultParams, clearMessages |
as on the instance | Mutations |
defaultParams |
ComputedRef<DefaultParamsSnapshot<D>> |
Shallow snapshot |
loadedLocales, activeNamespaces |
ComputedRef<string[]> |
Reactive lists |
defaultNamespace |
ComputedRef<string> |
Reactive default namespace |
hasTranslation, hasLocale |
(…) => ComputedRef<boolean> |
Reactive checks; call in setup() |
formatNumber, formatDate, formatCurrency, formatRelativeTime |
bound, trailing locale? |
Formatters |
on, reportError |
as on the instance | Events and errors |
destroy |
() => Promise<void> |
Tear down the wrapper |
<script setup lang="ts">import { useI18n } from '@comvi/vue';
const { t, locale, setLocale } = useI18n();</script>
<template> <button @click="setLocale(locale === 'en' ? 'de' : 'en')"> {{ t('greeting', { name: 'Alice' }) }} </button></template>Capability composables
Section titled “Capability composables”function useI18nLoader(): UseI18nLoaderReturn // AcquiredLoaderApifunction useI18nPlugins(): UseI18nPluginsReturn // AcquiredPluginsApiuseI18nLoader() returns addActiveNamespace, addActiveNamespaces, removeActiveNamespace,
removeActiveNamespaces, reloadMessages, onLoadError. useI18nPlugins() returns
onMissingKey. Each throws, in development and production, when the injected instance lacks the
capability. Cached per instance.
<script setup lang="ts">import { onMounted } from 'vue';import { useI18n, useI18nLoader } from '@comvi/vue';
const { t } = useI18n('dashboard');const { addActiveNamespace } = useI18nLoader();
onMounted(() => void addActiveNamespace('dashboard'));</script>
<template> <h1>{{ t('page.title') }}</h1></template>Renders a translation with <tag> markup without v-html. Named slots and components are
both tag handlers; components wins a name collision.
| Prop | Type | Meaning |
|---|---|---|
i18nKey |
string |
Required |
params |
Record<string, unknown> |
Interpolation params; any undeclared attribute is a param too and wins a collision |
ns, locale, fallback |
string |
Overrides; fallback wins over the default slot |
markers |
boolean |
false turns the in-context editor’s markers off for this element when they cause a problem; it is then not editable in context |
components |
ComponentMap |
Tag name to a tag name, a component, or { tag | component, props }; tag wins |
| default slot | Rendered when the key is missing, no fallback was given and onMissingKey returned nothing |
Write direct params in camelCase. class, style and listeners on <T> become params, so put
them on a wrapping element. A slot handler that throws is reported as
reportError(error, { source: 'translation', tagName }) and degrades to <span> with the
children, on the server and the client alike; a component in components that throws is not caught.
<script setup lang="ts">import { T } from '@comvi/vue';</script>
<template> <T i18nKey="legal.tos"> <template #link="{ children }"> <a href="/terms">{{ children }}</a> </template> </T> <T i18nKey="notice" :components="{ bold: 'strong' }" /> <T i18nKey="maybe.missing">Default fallback text</T></template>Options API globals
Section titled “Options API globals”install(app) registers $t(key, params?), $tRaw(key, params?) and $i18n, typed
AnyVueI18n, which erases D and the type of core.
I18N_INJECTION_KEY
Section titled “I18N_INJECTION_KEY”const I18N_INJECTION_KEY: InjectionKey<AnyVueI18n>What install(app) provides under. inject(I18N_INJECTION_KEY) gives the wrapper with a
capability-free core, so composing from inside a component is a type error.
Read next
Section titled “Read next”- Vue: setup, loading, plurals, tags and typing for a Vue 3 app.
@comvi/nuxt: module options, the setup hook and server helpers.@comvi/core: the i18n instance, the capabilities and every type.