Skip to content

Vite Plugins

Vite plugin — Translation completeness check

Checks all locale JSON files against a reference locale and reports any missing or extra keys. Runs at buildStart and on every locale file save during development (HMR).

ts
// vite.config.ts
import { vueI18nCheckPlugin } from 'vue-i18n-kit/vite'

export default defineConfig({
  plugins: [
    vue(),
    vueI18nCheckPlugin({
      localesDir: 'src/locales',
      defaultLocale: 'en',
      failOnMissing: true,
    }),
  ],
})

Options

OptionTypeDefaultDescription
localesDirstring'src/locales'Directory containing locale JSON files, relative to Vite project root.
defaultLocalestringfirst file alphabeticallyLocale used as the reference when comparing keys.
failOnMissingbooleanfalseWhen true, missing keys abort the build with an error.

Example output

[vue-i18n-kit] Incomplete translations detected (reference: "en"):
  Locale "ru":
    Missing keys (2):
      - buttons.cancel
      - profile.title
  Locale "de":
    Missing keys (1):
      - profile.title
    Extra keys (1):
      + legacy.old_key

Vite plugin — Inline translations

vueI18nInlinePlugin bakes all locale JSON files into the production bundle at build time via a virtual module. There are no runtime HTTP requests — the translations are a plain JavaScript object embedded in the bundle.

Ideal for: SSR apps, offline-capable PWAs, small projects where bundle size matters less than loading latency.

ts
// vite.config.ts
import { vueI18nInlinePlugin } from 'vue-i18n-kit/vite'

export default defineConfig({
  plugins: [
    vue(),
    vueI18nInlinePlugin({
      locales: {
        en: 'src/locales/en.json',
        ru: 'src/locales/ru.json',
        de: 'src/locales/de.json',
      },
    }),
  ],
})

Usage in your app

ts
import inlineLocales from 'virtual:vue-i18n-kit/locales'

app.use(
  createVueI18nPlugin({
    defaultLocale: 'en',
    locales: {
      en: { messages: inlineLocales.en, meta: { display: 'English' } },
      ru: { messages: inlineLocales.ru, meta: { display: 'Русский' } },
    },
  }),
)

TypeScript — add to env.d.ts or vite-env.d.ts:

ts
declare module 'virtual:vue-i18n-kit/locales' {
  const locales: Record<string, Record<string, unknown>>
  export default locales
}

Vite plugin — Namespace code splitting

vueI18nNamespacePlugin scans a directory of split locale files and generates the virtual module virtual:vue-i18n-namespaces. The module exports a locales object ready to pass to createVueI18nPlugin — each locale entry includes per-namespace dynamic import() calls so Vite code-splits them automatically.

ts
// vite.config.ts
import { vueI18nNamespacePlugin } from 'vue-i18n-kit/vite'

export default defineConfig({
  plugins: [
    vue(),
    vueI18nNamespacePlugin({
      dir: 'src/locales/split',
      locales: {
        en: { meta: { display: 'English', flag: '🇬🇧' }, eagerNamespaces: ['common'] },
        ru: { meta: { display: 'Русский', flag: '🇷🇺' }, eagerNamespaces: ['common'] },
      },
    }),
  ],
})

Usage in your app

ts
import { locales } from 'virtual:vue-i18n-namespaces'

app.use(createVueI18nPlugin({ defaultLocale: 'en', locales }))

Namespaces not in eagerNamespaces are loaded lazily with useNamespace():

ts
const { isLoading } = useNamespace('dashboard')
// or several at once:
const { isLoading } = useNamespace(['dashboard', 'charts'])

Options

OptionTypeDefaultDescription
dirstring'src/locales/split'Directory containing locale subdirectories (<dir>/<locale>/<namespace>.json).
localesRecord<string, { meta?, eagerNamespaces? }>{}Per-locale config. Locales found in the directory but not listed here are included automatically.

HMR: when any namespace JSON file inside dir changes, Vite invalidates and reloads the virtual module automatically.

Vite plugin — In-context translation editor (dev only)

vueI18nDevPlugin injects a floating editor overlay into your running application during development. Translated strings can be wrapped with the <I18nInspect> component to show a pencil icon on hover; clicking it opens an inline popup for editing that key.

The plugin is a complete no-op during production builds.

ts
// vite.config.ts
import { vueI18nDevPlugin } from 'vue-i18n-kit/vite'

export default defineConfig({
  plugins: [
    vue(),
    vueI18nDevPlugin(), // uiUrl is set automatically by vue-i18n-kit dev
  ],
})

Start both servers with one command:

bash
npx vue-i18n-kit dev

This auto-detects scripts.dev from package.json, starts both Vite and the locale editor UI in parallel, and passes I18N_KIT_UI_URL to vueI18nDevPlugin automatically.

Auto-wrap (default)

By default vueI18nDevPlugin automatically rewrites Vue SFC templates at dev time. Every {{ t('key') }}, {{ tm('key') }}, and {{ $t('key') }} interpolation is wrapped with <I18nInspect>no manual markup needed.

vue
<!-- Source as written -->
<template>
  <p>{{ t('nav.home') }}</p>
</template>

<!-- What Vite actually compiles in dev mode -->
<template>
  <p>
    <I18nInspect i18n-key="nav.home">{{ t('nav.home') }}</I18nInspect>
  </p>
</template>

Set autoWrap: false to use explicit <I18nInspect i18n-key="…"> markup or the v-i18n-inspect directive instead.

Dynamic keys — v-i18n-inspect directive

For runtime keys (variables, computed values, loop indices) use the directive which attaches hover behaviour to the existing element without adding a wrapper node:

vue
<span v-i18n-inspect="activeKey">{{ t(activeKey) }}</span>
<span v-i18n-inspect="`items.${item.id}`">{{ t(`items.${item.id}`) }}</span>

Options

OptionTypeDefaultDescription
uiUrlstringI18N_KIT_UI_URL env or 'http://localhost:4173'URL of the running vue-i18n-kit ui server.
autoWrapbooleantrueAutomatically wrap t() / tm() / $t() interpolations with <I18nInspect> at dev time.
wrapFunctionsstring[]['t', 'tm', '$t']Function names to look for when autoWrap is enabled.
iframeWidthstring'480px'Width of the right-side iframe editor panel.