| name | vue-i18n |
| description | Use when configuring internationalization in Vue3 projects, handling multi-language switching, or resolving i18n-related issues. Also use when working with vue-i18n, $t(), t(), locale, fallbackLocale, translate, language switch, i18n setup, or any i18n/translation/localization tasks in Vue applications. |
| metadata | {"author":"DenisZheng"} |
Vue I18n Configuration
Overview
Best practices for internationalization in Vue3 projects using vue-i18n@9 for multi-language support.
When to Use
- Adding i18n support to new Vue3 projects
- Implementing language switching (Chinese/English/Japanese)
- Components not updating after language change
- Needing TypeScript type hints
- Optimizing performance with dynamic language loading
- Handling plurals, dates, numbers, or HTML content
- SSR hydration mismatches
Quick Reference
| Feature | Key Config | Code |
|---|
| Basic Setup | legacy: false | createI18n({ legacy: false, locale: 'zh', messages: {...} }) |
| Language Switch | locale.value | locale.value = 'en' |
| Component Usage | useI18n() | const { t } = useI18n() |
| Persistence | localStorage | localStorage.setItem('locale', locale) |
| Plural | pipe | | "item": "no items | one item | {n} items" |
| Date Format | $d() | $d(date, 'short') |
| Number Format | $n() | $n(1234.56, 'currency') |
Core Pattern
1. Installation
npm install vue-i18n@9
2. Create i18n Instance
import { createI18n } from 'vue-i18n'
import en from './locales/en.json'
import zh from './locales/zh.json'
const i18n = createI18n({
legacy: false,
locale: 'zh',
fallbackLocale: 'en',
messages: { en, zh },
globalInjection: true
})
export default i18n
3. Register in Entry
import i18n from './i18n'
app.use(i18n)
4. Use in Components
<script setup>
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
</script>
<template>
<h1>{{ t('header.title') }}</h1>
<button @click="locale = 'en'">English</button>
</template>
Language Switcher Component
<script setup>
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
const switchLang = (lang) => {
locale.value = lang
localStorage.setItem('locale', lang)
document.documentElement.lang = lang
}
</script>
<template>
<button @click="switchLang('zh')">中文</button>
<button @click="switchLang('en')">English</button>
</template>
Plurals
{
"cart": {
"item": "No items | One item | {n} items"
}
}
{
"cart": {
"item": "无商品 | {n}件商品 | {n}件商品"
}
}
<p>{{ t('cart.item', 5) }}</p>
HTML Content
<i18n-t keypath="message.terms" tag="p">
<template #link>
<a href="/terms">Terms of Service</a>
</template>
</i18n-t>
{ "message": { "terms": "Please accept our {link}" } }
Dynamic Language Loading
export async function loadLanguageAsync(lang) {
if (i18n.global.locale.value === lang) return
if (!i18n.global.messages.value[lang]) {
const messages = await import(`./locales/${lang}.json`)
i18n.global.setLocaleMessage(lang, messages.default)
}
i18n.global.locale.value = lang
}
Common Mistakes
❌ Forgetting legacy: false
const i18n = createI18n({ locale: 'zh' })
const i18n = createI18n({ legacy: false, locale: 'zh' })
❌ Components not reacting to language change
<!-- Wrong: static reference in template -->
<h1>{{ $t('title') }}</h1>
<!-- Correct: use reactive -->
<script setup>
const { t } = useI18n()
</script>
<h1>{{ t('title') }}</h1>
❌ Hardcoded language codes
if (lang === 'zh') { ... }
const supportedLangs = ['zh', 'en', 'ja']
if (supportedLangs.includes(lang)) { ... }
❌ Using wrong plural syntax
"items": "{count} items"
"items": "No items | One item | {n} items"
❌ Missing fallbackLocale
const i18n = createI18n({ locale: 'zh', messages: { zh } })
const i18n = createI18n({ locale: 'zh', fallbackLocale: 'en', messages: { en, zh } })
TypeScript Support
export type MessageSchema = {
header: { title: string; login: string }
home: { welcome: string }
errors: { required: string }
}
const { t } = useI18n<[MessageSchema]>()
const title = t('header.title')
Project Structure
src/
├── i18n/
│ ├── index.js # i18n configuration
│ ├── types.ts # TypeScript types
│ └── locales/
│ ├── en.json
│ └── zh.json
├── components/
│ └── LanguageSwitcher.vue
└── main.js
Converted and distributed by TomeVault — claim your Tome and manage your conversions.