什么是 i18n
i18n 是 internationalization(国际化)的缩写。首尾字母之间共有 18 个字符,因此简写为 i18n。与之对应的还有 L10n(Localization,本地化)。
通俗点说,就是实现多语言切换。让不同母语的用户能看懂界面上的文字。我们最常用的组合是中文简体(zh_CN)与英文(en_US),当然也可以根据需要扩展繁体或其他语言。
建议在项目启动阶段就规划好国际化方案,后期改造成本较高,越早接入越顺畅。
环境准备与安装
首先打开终端进入前端项目目录。开发工具方面,VSCode 在前端领域更为常用。
cd web
使用包管理器安装 vue-i18n。如果你习惯用 npm:
npm install vue-i18n
若使用 pnpm,命令如下,启动速度通常更快:
pnpm add vue-i18n
yarn 用户则执行:
yarn add vue-i18n
构建语言资源文件
接下来创建语言包结构。在 src 目录下新建 locales 文件夹,并在其中放置对应语言的 JSON 文件。
注意:i18n.js 文件应与 locales 文件夹同级,都位于 src 根目录下。建议先折叠 src 下的子文件夹再新建,避免层级混乱。
以支持简体中文和英文为例,创建 zh-CN.json 和 en-US.json。
编写翻译内容
在 zh-CN.json 中写入中文文案:
{
"common": {
"confirm": "确定",
"cancel": "取消",
"pleaseEnterUsernameAndPassword": "请输入账号和密码",
"loginSuccess": "登录成功",
"loginFail": "登录失败"
},
"loginPage": {
"title": "XX 管理系统",
"userLogin": "用户登录",
"username": "账号",
"password": "密码",
"usernamePlaceholder": "请输入账号",
"passwordPlaceholder": "请输入密码",
"languageLabel": "语言",
"loginButton": "登录",
"text1": "如有疑问,请联系技术人员以提供支持。"
}
}
键名命名建议采用驼峰式,首字母小写,无空格和下划线。常见错误是在最后一个属性后多加了逗号,JSON 解析会报错,务必检查格式。
同理,在 en-US.json 中填入对应的英文翻译:
{
"common": {
"confirm": "Confirm",
"cancel": "Cancel",
"pleaseEnterUsernameAndPassword": "Please enter username and password",
"loginSuccess": "Login success",
"loginFail": "Login fail"
},
"loginPage": {
"title": "XX Management System",
"userLogin": "User Login",
"username": "Username",
"password": "Password",
"usernamePlaceholder": "Please enter username",
"passwordPlaceholder": "Please enter password",
"languageLabel": "Language",
"loginButton": "Login",
"text1": "If you have any questions, please contact technical support for assistance."
}
}
初始化 i18n 实例
在 src 目录下创建 i18n.js 文件,引入 Vue I18n 并配置默认语言策略:
// src/i18n.js
import { createI18n } from 'vue-i18n'
import zhCN from './locales/zh-CN.json'
import enUS from './locales/en-US.json'
// 从本地存储读取用户之前设置的语言,如果没有则使用浏览器语言或默认中文
const savedLocale = localStorage.getItem('user-locale')
const browserLocale = navigator.language || 'zh-CN'
// 判断浏览器语言是否是英文,否则使用中文
const defaultLocale = savedLocale || (browserLocale.startsWith('en') ? 'en-US' : 'zh-CN')
const i18n = createI18n({
legacy: false,
locale: defaultLocale,
fallbackLocale: 'zh-CN',
messages: {
'zh-CN': zhCN,
'en-US': enUS
}
})
// 提供一个方法用于切换语言并持久化
export function setLocale(locale) {
i18n.global.locale.value = locale
localStorage.setItem('user-locale', locale)
}
export default i18n
legacy 设置为 false 是为了配合 Composition API 模式。fallbackLocale 确保当当前语言包缺少某个翻译时,回退到中文,避免显示 key 字符串。
组件中使用国际化
引入 API
在需要转换的 Vue 单文件组件中,于 <script setup> 顶部引入 useI18n:
<script setup>
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
// 你的其他代码
</script>
模板调用
在模板中涉及文案的地方,将静态文本替换为 $t() 函数调用。参数格式为 模块名。字段名,中间用英文点连接。
例如登录页面的标题:
<h1>{{ $t('loginPage.title') }}</h1>
完整的登录界面示例如下:
<template>
<div>
<img src="@/assets/Logo.png" alt="logo">
<h1>{{ $t('loginPage.title') }}</h1>
<h2>{{ $t('loginPage.userLogin') }}</h2>
<!-- 账号输入框 -->
<div>
<div>{{ $t('loginPage.username') }}</div>
<input type="text" v-model="loginForm.username" :placeholder="$t('loginPage.usernamePlaceholder')">
</div>
<!-- 密码输入框 -->
<div>
<div>{{ $t('loginPage.password') }}</div>
<input :type="passwordVisible ? 'text' : 'password'" v-model="loginForm.password" :placeholder="$t('loginPage.passwordPlaceholder')">
</div>
<!-- 语言选择 -->
<div>
<div>{{ $t('loginPage.languageLabel') }}</div>
<select v-model="currentLanguage" @change="changeLanguage">
<option value="zh-CN">简体中文</option>
<option value="en-US">English</option>
</select>
</div>
<button @click="debouncedLogin">{{ $t('loginPage.loginButton') }}</button>
<p>{{ $t('loginPage.text1') }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { setLocale } from '@/i18n';
const { t } = useI18n();
const currentLanguage = ref('zh-CN');
function changeLanguage() {
setLocale(currentLanguage.value);
}
</script>
这里通过 select 绑定 currentLanguage,切换时调用 setLocale 更新全局语言并保存到 localStorage,下次访问自动记忆偏好。
效果展示
配置完逻辑与样式后,即可看到中英文界面无缝切换的效果。




