Skip to content

i18n Kit

v0.4.12UtilitiesVue

A reusable Vue 3 localization plugin that wraps vue-i18n and provides a ready-to-use integration layer — set up once, reuse across every project.

i18n Kit
Get started →
npm install vue-i18n-kit@latest vue vue-i18n
01 — Purpose

When you'd reach for this

A missing translation key doesn't break the build or throw a console error — it just shows the user a raw identifier instead of text, and the first person to notice is usually the user, not the developer. vue-i18n-kit checks every locale for completeness right at build time, before it ever gets that far.

"1 file" and "5 files" are different forms, and not just in Russian

English has one plural form, Russian has three, Arabic has six — the grammatically correct form is picked automatically for each language instead of one string with a number dropped in.

A translator doesn't need to read code to fix a typo

A typo in a button's text can be fixed by someone who's never opened a code editor — right in the browser, with a table of keys and a live preview, no repository access required.

A new language shouldn't slow the site down for everyone else

A user in Germany shouldn't have to download a Japanese translation just because the site supports 12 languages — each locale loads separately, and only when it's actually needed.

Translation is needed where there's no component to reach it from

An error message in an HTTP interceptor, text in a state store, a check inside a router guard — translation stays available in exactly the places where the usual way of reaching it from inside a component won't work.

Different client releases are built from one codebase

Each client gets its own set of copy on top of one shared base — some strings are identical everywhere, some are overridden for a specific brand. The shared dictionary can be safely merged into each client's files: missing strings get added, while anything already overridden for a brand stays untouched instead of getting clobbered by mistake.

Nothing should be missing right before a release

A developer adds a new screen and forgets to translate it into three of the five languages — that's catchable with one command that compares every locale against the reference and reports which keys are missing and which aren't used anywhere anymore.

02 — Features

At a glance

Lazy locale loading and a simple API

Lazy locale loading and a simple API

Load locales via dynamic imports — only the active language is loaded, others are fetched on demand. Two translation methods: t() for simple strings with interpolation and tm() for ICU pluralisation with correct forms for any language (including Arabic).

Composables for locale, formatting, and metadata

Composables for locale, formatting, and metadata

useLocale provides access to the current language, its metadata (flag, display name), and switching with a loading indicator. useAvailableLocales returns a list of all registered locales. useFormat wraps Intl for formatting dates, numbers, and currencies using the active locale.

Vite plugins: check, inline, namespaces, and editor

Vite plugins: check, inline, namespaces, and editor

The check plugin validates all locales against a reference for missing or extra keys at build time and in HMR. The inline plugin bakes JSON into the bundle, while the namespace plugin automatically splits locales into chunks with lazy loading. The dev plugin adds a translation inspector with in‑UI editing.

CLI for translation management and type generation

CLI for translation management and type generation

Interactive initialisation, adding new locales, completeness checks, removing unused keys, merging with a shared base, XLIFF/PO export/import, and stale translation tracking. The TranslationKey type generation provides autocomplete and compile‑time key checking in all composables.

Web editor, machine translation, and flexible settings

Web editor, machine translation, and flexible settings

A built‑in browser editor with a key table, filters, group operations, and live preview. Automatic translation of missing strings via LibreTranslate or DeepL. Support for a base dictionary, key locking, validation rules, and ignore lists for fine‑tuning to your project.

A service outside components, with reliable fallbacks

A service outside components, with reliable fallbacks

Access translations from code outside components — stores, router guards, HTTP interceptors — through the plugin’s service, available without setup(). Subscribe to locale changes via onLocaleChange. The selected locale persists across visits, and a missing translation falls back to a reserve language.

03 — Quick example

See how it works

Locales load on demand, the chosen language remembers itself

messages() is a dynamic import, so only the active language ships in the bundle. persistLocale: true remembers the user's choice across visits — no manual localStorage code.

main.ts
import { createApp } from 'vue'
import { createVueI18nPlugin } from 'vue-i18n-kit'
import App from './App.vue'

const app = createApp(App)

app.use(
  createVueI18nPlugin({
    defaultLocale: 'en',
    fallbackLocale: 'en',
    locales: {
      en: {
        messages: () => import('./locales/en.json'),
        meta: { display: 'English', flag: '🇬🇧' },
      },
      ru: {
        messages: () => import('./locales/ru.json'),
        meta: { display: 'Русский', flag: '🇷🇺' },
      },
    },
    persistLocale: true,
  }),
)

app.mount('#app')

Dates, numbers, and currency adapt themselves to the language

formatDate/formatNumber/formatCurrency wrap the native Intl APIs, follow the active locale, and re-render themselves the moment it switches — no hand-rolled per-language formatting.

format.ts
import { useFormat } from 'vue-i18n-kit'

const { formatDate, formatNumber, formatCurrency } = useFormat()

formatDate(new Date(), { dateStyle: 'long' }) // '28 марта 2026 г.'  (ru)
formatNumber(1_234_567.89) // '1 234 567,89'     (ru)
formatCurrency(1999.99, 'EUR') // '1 999,99 €'       (ru)

// Switch the active locale and every formatter re-renders itself — no
// manual re-formatting, no separate en/ru number-formatting code paths.

Pluralization that actually handles Russian

One ICU template, and Intl.PluralRules picks the right form — one/few/many/other — instead of a hand-rolled if/else chain per number.

pluralize.ts
import { useT } from 'vue-i18n-kit'

const { tm } = useT()

// locale: "{points} {points, plural, one {рубль} few {рубля} many {рублей} other {рублей}}"
tm('balance', { points: 1 }) // → '1 рубль'
tm('balance', { points: 3 }) // → '3 рубля'
tm('balance', { points: 21 }) // → '21 рубль'
tm('balance', { points: 25 }) // → '25 рублей'

// Same template, four different real Russian plural forms — driven by
// Intl.PluralRules under the hood, not a hand-rolled if/else chain.

A forgotten translation breaks the build, not production

The Vite plugin diffs every locale against the reference one on every save and on build — a missing key surfaces in seconds, not after a user complaint.

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

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

// Runs on every locale-file save (HMR) and again at build start:
//
// [vue-i18n-kit] Incomplete translations detected (reference: "en"):
//   Locale "ru":
//     Missing keys (2):
//       - buttons.cancel
//       - profile.title