Code前端首页关于Code前端联系我们

什么是Vue2 i18n?

terry 7小时前 阅读数 6 #Vue
文章标签 Vue2;i18n

p>做国际化项目的时候,不少用Vue2开发的同学都会头疼——怎么让网站在不同地区自动切换语言?手动改文字不仅效率低,后期维护也容易乱,其实Vue生态里有专门的i18n工具能解决这个问题,但从安装到实际用起来,很多细节得慢慢理清楚,这篇文章就用问答的方式,把Vue2 i18n从基础到实战的问题一个个说透。

简单说,i18n是「国际化」(Internationalization)的缩写,因为英文里Internationalization有18个字母,所以叫i18n,Vue2里做国际化,主要靠「vue-i18n」这个库(注意哦,Vue3用的是新版本,Vue2得装指定版本@8.x),它的作用很明确:把不同语言的文案集中管理,然后在项目里动态切换展示,比如中文页面点个按钮,瞬间变成英文,背后就是i18n在替换文案、处理语言规则。

为啥Vue2项目要做i18n?

用户体验,想象一下,国外用户打开你的网站,满眼中文根本看不懂,流失率肯定高,做了i18n,不同地区用户进来自动看到母语,体验友好度飙升,然后是业务扩张,要是你想把产品卖到全球,多语言支持是刚需,最后是维护效率,以前改个文案得满项目找硬编码的文字,现在只需要改语言文件里的对应字段,一处修改全项目生效,省老多事儿了,举个例子,做外贸独立站的同学,商品描述、按钮文字这些,用i18n管理起来,后期换市场、加语言都轻松。

Vue2里怎么装i18n依赖?

第一步先装包,因为Vue2和Vue3的i18n版本不兼容,所以得指定版本,打开终端,输入npm install vue-i18n@8(用yarn的话就是yarn add vue-i18n@8),装完后,得在项目里配置,一般在main.js里搞:

先引入Vue和VueI18n:
import Vue from 'vue'
import VueI18n from 'vue-i18n'

然后注册插件:Vue.use(VueI18n)

接下来创建i18n实例,配置默认语言和语言包:
const i18n = new VueI18n({
  locale: 'zh', // 默认显示中文
  messages: {
    zh: require('./locales/zh.json'), // 中文文案文件
    en: require('./locales/en.json') // 英文文案文件
  

最后把i18n挂到Vue实例上:
new Vue({
  el: '#app',
  i18n, // 注入到所有组件
  render: h => h(App)

这里得注意locales文件夹,要自己建,里面放zh.json、en.json这些语言文件,比如zh.json长这样:

  "greet": "你好,欢迎回来",
  "button": {
    "submit": "提交",
    "cancel": "取消"
  

英文en.json对应翻译就行,结构得和中文的一样,不然切换的时候会找不到key。

组件里咋用i18n的文案?

在组件的模板里,主要用$t这个方法,比如要显示刚才zh.json里的greet,就写{{ $t('greet') }},如果是嵌套的key,像button.submit,就用{{ $t('button.submit') }}

要是文案里需要HTML标签(比如带链接、样式的文字),得用v-html指令,写成

,但得注意安全,别让用户输入的内容直接渲染,防止XSS攻击。

除了模板,JS里也能拿文案,比如在methods或者computed里,用this.$t('key'),举个例子,点击按钮弹提示:
methods: {
  showAlert() {
    alert(this.$t('alertMsg'))
  

还有种情况,同一个文案在不同地方有细微差别,{name}的个人中心”,可以传变量:{{ $t('userCenter', { name: '小明' }) }},对应的语言文件里要写成"userCenter": "{name}的个人中心",这样变量就能被替换掉。

怎么实现语言切换功能?

核心逻辑是改变i18n实例的locale属性,一般做个语言切换的组件,比如两个按钮,点中文切中文,点英文切英文。

先写切换方法,比如在App.vue里:
methods: {
  changeLang(lang) {
    this.$i18n.locale = lang; // 切换语言
    localStorage.setItem('lang', lang); // 存到本地,下次打开记住选择
  

然后在模板里加按钮:

但用户刷新页面后,得记住上次选的语言,所以初始化i18n的时候,locale要优先读本地存储:
const i18n = new VueI18n({
  locale: localStorage.getItem('lang') || 'zh', // 没存过就默认中文
  messages: { ... }

这样切换后刷新,语言也不会丢,要是做移动端H5,还能结合浏览器的语言偏好自动识别,但一般项目里先做手动切换+本地存储就够了。

多语言里的复数、变量咋处理?

先讲复数,不同语言复数规则不一样,比如英语里,1条消息是“1 item”,2条以上是“3 items”;中文里不管数量多少,都是“3条消息”,vue-i18n支持用MessageFormat语法处理复数。

举个英文的例子,en.json里写:
"messageCount": "{count, plural, one {# item} other {# items}}"
然后在模板里用{{ $t('messageCount', { count: 5 }) }},就会显示“5 items”;如果count是1,就显示“1 item”。

中文的话,不需要区分one和other,所以zh.json里可以简单写:
"messageCount": "{count}条消息"
然后传count变量就行,{{ $t('messageCount', { count: 3 }) }}显示“3条消息”。

变量替换刚才提过,比如欢迎语带用户名,语言文件里写"welcome": "欢迎{name}回来",然后$t('welcome', { name: user.name }),这样就能动态替换name。

UI框架(比如Element UI)的多语言咋整合?

很多项目用Element UI,它本身也有自己的语言包,得把Element的语言和我们自定义的语言包合并,不然切换语言时,Element的组件文字不会变。

第一步,引入Element的语言包,比如中文和英文:
import zhElement from 'element-ui/lib/locale/lang/zh-CN'
import enElement from 'element-ui/lib/locale/lang/en'

然后在i18n的messages里,把Element的语言包和自定义的合并,比如zh.json里除了自己的文案,还要包含Element的:
const i18n = new VueI18n({
  locale: ...,
  messages: {
    zh: {
      ...zhElement, // Element的中文文案
      ...require('./locales/zh.json') // 自己的中文文案
    
    en: {
      ...enElement, // Element的英文文案
      ...require('./locales/en.json') // 自己的英文文案
    
  

还要配置Element的locale,让它跟着vue-i18n走,在main.js里:
import ElementLocale from 'element-ui/lib/locale'
ElementLocale.i18n((key, value) => i18n.t(key, value))

这样一来,Element的组件(比如日期选择器的月份、提示框的按钮文字)就会和我们的自定义文案一起切换语言了,要是用其他UI框架,比如Ant Design Vue,思路差不多,先找对应语言包,再合并配置。

i18n的文案管理有啥技巧?

项目大了,文案特别多,得有方法管理才不会乱。

第一,按模块拆分语言文件,比如把首页、个人中心、商品页的文案分别放到home.json、profile.json、product.json里,然后在main.js里合并到messages:
zh: {
  ...require('./locales/home/zh.json'),
  ...require('./locales/profile/zh.json')

这样找文案的时候,能快速定位到对应模块,也方便多人协作翻译。

第二,用lint工具检查,可以装eslint-plugin-vue-i18n,配置后能检查项目里有没有遗漏的key、重复的key,翻译文件结构是否一致,避免上线后某些语言缺文案。

第三,结合翻译平台,如果团队有专业翻译,把语言文件丢到Crowdin、Transifex这类平台,翻译完再导回来,比手动改效率高多了。

第四,写文案时统一用占位符,比如所有带变量的地方都用{name}这种格式,翻译的时候不会因为结构变化导致显示错误,要是文案里有特殊格式,提前和翻译沟通好,避免翻译后样式乱掉。

常见问题咋解决?

开发过程中总会碰到各种小坑,这里列几个高频问题:

切换语言后,部分组件文字没更新?
原因可能是直接修改了i18n的locale,但是某些组件没触发响应式,要确保用this.$i18n.locale = lang这种方式切换,因为vue-i18n的locale是响应式数据,直接赋值能触发更新,如果是用其他方式(比如直接改实例属性),可能不生效。

想动态加载语言包,减少首屏体积?
比如用户切换到法语,再加载fr.json,可以用动态导入:
methods: {
  async switchToFr() {
    const frMessages = await import('./locales/fr.json')
    this.$i18n.setLocaleMessage('fr', frMessages.default)
    this.$i18n.locale = 'fr'
  

这样法语包只有在切换时才加载,首屏不用背所有语言包。

文案里有HTML标签,显示成纯文本了?
得用v-html指令,比如

,但要确保内容安全,别让用户输入的内容直接渲染,防止XSS攻击。

多语言SEO咋做?
搜索引擎识别页面语言靠html标签的lang属性,所以要动态设置:

这样切换语言后,lang属性也会变,对SEO更友好。

切换语言后,路由参数的语言标识咋处理?
比如网址是/en/about,切换到中文变成/zh/about,可以在切换语言时,同时修改路由的path,用this.$router.push({ path: `/${lang}/about` })这种方式,保持URL和语言对应。

实战案例:给现有Vue2项目加i18n

假设现在有个已经开发一半的Vue2项目,要加多语言,步骤如下:

第一步:装依赖

打开终端,执行npm install vue-i18n@8,确保版本对应Vue2。

第二步:建语言文件目录

在src下新建locales文件夹,里面再建zh.json、en.json(如果有其他语言后续再加),把项目里所有硬编码的中文文案整理到zh.json,按模块分类。
zh.json:

  "home": {
    "title": "首页",
    "subtitle": "这里是首页副标题"
  
  "about": {
    "title": "关于我们",
    "desc": "我们是一家专注于xxx的公司"
  

en.json对应翻译,结构必须和zh.json完全一致。

第三步:配置main.js

引入VueI18n,创建实例,把语言文件导入:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import App from './App.vue'
import router from './router'

Vue.use(VueI18n)

const i18n = new VueI18n({
  locale: localStorage.getItem('lang') || 'zh',
  messages: {
    zh: require('./

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门