
Vue i18n: Complete Internationalization Setup with vue-i18n
From installation to production: configure vue-i18n with Composition API, handle plurals with CLDR rules, use component interpolation, and add smart locale fallback chains.
Install vue-i18n
vue-i18n is the official internationalization plugin for Vue.js. It provides reactive translations, ICU-style pluralization, component interpolation, datetime and number formatting, and both Options API and Composition API support.
npm install vue-i18n@9Configure vue-i18n
Create an i18n instance with createI18n() and register it as a Vue plugin. Define your locale messages, set the default locale, and configure the fallback locale. vue-i18n supports both legacy (Options API) and composition (Composition API) modes.
// src/i18n.ts
import { createI18n } from 'vue-i18n'
import en from './locales/en.json'
import de from './locales/de.json'
const i18n = createI18n({
legacy: false, // Use Composition API mode
locale: 'en', // Default locale
fallbackLocale: 'en', // Fallback locale
messages: { en, de },
})
export default i18n// src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'
const app = createApp(App)
app.use(i18n)
app.mount('#app')Use Translations in Templates
vue-i18n provides the $t() function in templates (Options API) and the t() function from useI18n() (Composition API). Both accept the translation key and optional named/list parameters for interpolation.
// src/locales/en.json
{
"nav": {
"home": "Home",
"about": "About",
"settings": "Settings"
},
"greeting": "Hello, {name}!",
"cart": {
"itemCount": "no items | one item | {count} items"
}
}
// src/locales/de.json
{
"nav": {
"home": "Startseite",
"about": "Über uns",
"settings": "Einstellungen"
},
"greeting": "Hallo, {name}!",
"cart": {
"itemCount": "keine Artikel | ein Artikel | {count} Artikel"
}
}Handle Pluralization
vue-i18n supports pluralization through pipe-separated forms and the $tc() function (legacy) or t() with a count parameter (Composition API). Define plural forms in your locale messages using the pipe separator: 'no items | one item | {count} items'.
<template>
<div>
<!-- Simple translation -->
<h1>{{ $t('nav.home') }}</h1>
<!-- With variables -->
<p>{{ $t('greeting', { name: userName }) }}</p>
<!-- In attributes -->
<input :placeholder="$t('nav.settings')" />
<!-- Composition API -->
<p>{{ greeting }}</p>
</div>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const userName = 'Alice'
const greeting = t('greeting', { name: userName })
</script>Add Locale Fallback Chains
vue-i18n's built-in fallbackLocale only supports a flat list of fallback locales, not per-locale chains. A pt-BR user with a missing key falls back to English instead of pt-PT. vue-i18n-locale-chain adds configurable deep-merge chains so regional users always see the closest available translation.
<template>
<div>
<!-- Pipe-separated plurals -->
<p>{{ $t('cart.itemCount', count) }}</p>
<!-- Named plurals (recommended for complex languages) -->
<p>{{ $t('orders', { n: orderCount }) }}</p>
</div>
</template>
<!-- In your locale file: -->
<!-- "orders": "{n} order | {n} orders" -->Automate Translations
With vue-i18n configured, translate your locale JSON files using AI. From your IDE, ask your AI assistant to translate the source file, or integrate translation into your CI/CD pipeline for fully automated localization.
<template>
<select v-model="locale">
<option v-for="lang in availableLocales" :key="lang" :value="lang">
{{ lang }}
</option>
</select>
</template>
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { locale, availableLocales } = useI18n()
</script>// src/i18n.ts
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
legacy: false,
locale: 'en',
fallbackLocale: 'en',
messages: {},
})
export async function loadLocale(locale: string) {
const messages = await import(`./locales/${locale}.json`)
i18n.global.setLocaleMessage(locale, messages.default)
i18n.global.locale.value = locale
}
export default i18nLocale Fallback Chain Configuration
Configure per-locale fallback chains so regional users see the closest available translation instead of jumping straight to English. vue-i18n supports object-style fallbackLocale for defining chains per locale.
// src/i18n.ts
import { createI18n } from 'vue-i18n'
const i18n = createI18n({
legacy: false,
locale: 'pt-BR',
fallbackLocale: {
'pt-BR': ['pt', 'en'],
'zh-Hant-TW': ['zh-Hant', 'zh', 'en'],
'es-419': ['es', 'en'],
default: ['en'],
},
messages: {
en: { /* ... */ },
pt: { /* ... */ },
'pt-BR': { /* ... */ },
},
})Common Pitfalls
Mixing Legacy and Composition API Modes
Using v-html for Translated Strings
Regional Users See English Instead of Parent Locale
Try i18n Agent Now
Drop your translation file here
JSON, YAML, PO, XML, CSV, Markdown, Properties
or click to browse
Target languages