Vue 3 接入 vue-i18n 完整教程(零基础版)
手把手教程,面向完全没接触过国际化 的初学者。
每一步都会解释"为什么这么做",跟着做即可把国际化接入任意 Vue 3 项目。
一、什么是国际化(i18n)?
i18n = internationalization(international 有 18 个字母,首尾 i、n 加上 18 就写成 i18n)。
简单说:同一套代码,根据不同语言显示不同文字。
| 语言 | 显示 |
|---|---|
| 中文 | 首页 |
| 英文 | Home |
| 日语 | ホーム |
vue-i18n 是 Vue 官方推荐的国际化插件,它帮你做三件事:
- 把页面上所有文字集中存到"语言包"里,不在代码里写死。
- 用一个 key(钥匙)来取文字,而不是直接写文字。
- 切换语言时,页面所有文字自动跟着变。
二、从零接入的 6 个步骤
第 1 步:安装依赖
bash
npm install vue-i18n
# 或使用 pnpm
pnpm add vue-i18n
# 或使用 yarn
yarn add vue-i18n
装完打开 package.json,在 dependencies 里能看到 "vue-i18n": "^11.4.8"。
第 2 步:创建语言包文件
语言包就是一个普通对象,里面存了"中文"和"英文"各怎么说。
先建目录 src/i18n/locales/,然后新建 src/i18n/locales/zh-CN.ts:
ts
export default {
nav: {
home: '首页',
about: '关于',
},
about: {
title: '关于页面',
},
}
再新建 src/i18n/locales/en-US.ts:
ts
export default {
nav: {
home: 'Home',
about: 'About',
},
about: {
title: 'About Page',
},
}
关键理解:
- 两个文件的结构一模一样 ,只是值不同。key(
nav.home)是"钥匙",值是"不同语言下的说法"。 - 代码里永远只写
$t('nav.home')这个 key,绝不写死文字。这样以后改文案不用翻代码。
第 3 步:创建 i18n 实例
新建 src/i18n/index.ts,这是整个国际化的"心脏":
ts
import { createI18n } from 'vue-i18n'
import zhCN from './locales/zh-CN'
import enUS from './locales/en-US'
const i18n = createI18n({
legacy: false, // 开启 Composition API 模式(Vue3 推荐)
locale: 'zh-CN', // 默认语言
fallbackLocale: 'en-US', // 找不到 key 时兜底用英文,避免白屏
messages: {
'zh-CN': zhCN,
'en-US': enUS,
},
})
export default i18n
逐个解释配置项:
legacy: false:Vue3 里必须关掉旧模式,才能在<script setup>里用useI18n()。locale:当前语言,切换语言就是改它。fallbackLocale:兜底语言。比如中文包漏了一个 key,就自动显示英文,页面不会空白。messages:把所有语言包都注册进来,一个 key 对应一个文件。
第 4 步:注册到应用入口
打开 src/main.ts,把 i18n 装进 Vue 应用里:
ts
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n' // ① 导入
const app = createApp(App)
app.use(i18n) // ② 注册,模板里才能用 $t()
app.mount('#app')
不注册的话,模板里
$t()是不可用的。app.use()就是告诉 Vue:"我有个插件,请全局启用它"。
第 5 步:在组件里用 $t() 替换写死的文字
模板里使用(最常用),以导航链接为例:
vue
<!-- 之前(写死) -->
<RouterLink to="/">Home</RouterLink>
<!-- 之后(国际化) -->
<RouterLink to="/">{{ $t('nav.home') }}</RouterLink>
脚本里使用,比如要在 JS 逻辑里拿翻译:
ts
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
const title = t('nav.home') // 当前语言是中文时返回 '首页'
带参数的翻译 (文字里有动态内容),在语言包里用 {xxx} 占位:
ts
// 语言包里
hello: { desc: '你已成功使用 {tech1} + {tech2} 创建了一个项目。' }
// 模板里传入具体值
{{ $t('hello.desc', { tech1: 'Vite', tech2: 'Vue 3' }) }}
// 输出:你已成功使用 Vite + Vue 3 创建了一个项目。
规律: 看到页面上有写死的文字,就照抄这个三步走------
① 在语言包里加一个 key;② 在模板里替换成
$t('key');③ 确保每个语言包都有这个 key。
第 6 步:做语言切换
语言切换的本质 = 改变 locale 的值,改完页面自动重渲染。
可以封装一个切换函数,同时做三件事(更新语言 + 记住选择 + 同步给浏览器):
ts
export function setLocale(locale: string) {
i18n.global.locale.value = locale // 1. 真正切换语言
localStorage.setItem('app-locale', locale) // 2. 记住用户选择
document.documentElement.lang = locale // 3. 同步给浏览器
}
-
下拉框里有什么语言,由
SUPPORT_LOCALES数组决定。 -
想支持"用户刷新后语言不变",就在创建 i18n 时读取
localStorage:tsconst saved = localStorage.getItem('app-locale')
三、自己动手试试
启动开发服务器后,你会看到:
- 页面右上角有语言下拉框,切换中英文,整个页面文字立刻变化。
- 刷新页面,语言保持不变(被 localStorage 记住了)。
- 无痕窗口打开,若代码里加了浏览器语言检测,会自动跟随。
练习任务:
- 在某一个页面上新加一句话,并完成中英文两个语言包的 key。
- 把页面里剩下的英文段落全部抽到语言包。
四、新手常犯的错误
| 错误 | 正确做法 |
|---|---|
| 只改了一个语言包,另一个忘了 → 另一个语言的用户看到空白 | 两个语言包同时加,key 结构保持一致 |
代码里写死 '欢迎' + name 拼接 |
用插值 $t('welcome', { name }) |
| 一个 key 只在一个语言包里有 | 所有语言包必须有相同 key,靠 fallbackLocale 兜底是最后手段 |
key 命名随意,比如 'hello'、'page1' |
按页面/模块组织:nav.home、about.title |
忘了在 main.ts 里 app.use(i18n) |
模板 $t() 会报错不可用 |
| 把整段含 HTML 链接的文字塞进语言包 | 链接文字单独抽 key,模板里用 <a> 标签包住 $t() |
五、遇到报错怎么办
- 模板里
$t is not defined:说明没注册,检查main.ts的app.use(i18n)。 - 页面出现 key 原文(如
nav.home):说明这个 key 在当前语言包里不存在,检查拼写或补上翻译。 - 切换没反应 :确认用的是
locale.value(ref 取值要.value),不是直接赋值。 - 类型报错 :运行类型检查命令(如
npm run type-check),看具体哪个文件的哪个 key 对不上。
记住一句话
代码里不写死任何文字,全部通过 key 从语言包取。
改文案 = 改语言包;加语言 = 加一个语言包文件。这就是国际化的全部精髓。