如何简单地在vue3中实现i18n

2021-04-27176

闲扯

  vue3 出来好一段时间了,我一直也没怎么用,因为公司项目一开始用的 vue2。迫于前端太卷,要时刻学习,跟进时代,最近着手用 vue3+vite 写一个练手项目。先不透露项目是啥,后面会开源的。   刚开始写 vue3 时也是处处不顺,因为思维还停留在 vue2 上,慢慢习惯了也还不错。个人感觉 vue3 学习了 React 的优点,把响应式这块完全丢给用户了。   习惯了 vue 全家桶一把梭,且没写过 React 的人可能有点适应不过来。

简介

  不用第三方 i18n 是因为我觉得 i18n 应该是一个很简单的,自己实现的功能sticker

  目标:更改语言后,所有的 $i18n() 均要同步更改

<template>
	<span>{{ $i18n('articles') }}</span>
</template>

这个博客项目的 i18n 都是我自己写的,因为基于 vue2,就简单地在 Vue.prototype 上加一个函数就行了:

const i18n = [
  {
    name: '中文',
    default: true,
    values: {
      articles: '文章',
      // ... ...
    }
  },{
    name: 'English',
    values: {
      articles: 'Articles',
      // ... ...
    }
  }
]
Vue.prototype.$i18n = function (value){
  const langs = i18n.find(v=>v.name===this.$store.state.lang)||i18n.find(v=>!!v.default)
  return langs.values[value]!==undefined?langs.values[value]:value
}

vue3 实现

  在 vue3 中,其实已经不需要用 vuex 了,vue3 提供的 refreactivecomputedprovideinject 已经够用了,而且很轻量。   于是乎,我就想着能不能把之前项目的 i18n 转到 vue3 上来。简单写了下,确实实现了,但不知性能如何,下面贴代码和注释:

/**
 * main.ts
 */
import { createApp, ref } from 'vue';
import {defaultLang} from "./i18n";

// 给app加一个全局ref属性:lang
const app = createApp(App);
app.config.globalProperties.$lang = ref(localStorage.getItem("lang")||defaultLang)
// ... ...
/**
 * i18n.ts
 * 这个挺简单的,就是单纯i18n的实现
 */
 import { computed } from 'vue'

export const langMap = [
    {
        name: '中文',
        values: {
          articles: '文章',
          // ... ...
        }
    },{
        name: 'English',
        values: {
          articles: 'Articles',
          // ... ...
        }
    },
]

export const defaultLang = "中文"

export default function (val: string){
    return computed(()=>{
        const lang = langMap.find(v=>v.name===this.$lang.value);
        if (lang){
            return lang.values[val]
        }
        return val
    }).value // 返回 computed().value
}

  由于 i18n 基本所有地方都会用到,所以我干脆把它放到 mixin 里了。这样的话,所有 vue 组件都会有一个 $i18n 方法,而且这个方法返回的是一个 computed(xxx).value,所以它会自动更新。

/**
 * i18n-mixin.ts
 */
import i18n from '../i18n'

export default {
    // ... ...
    methods:{
        // this 会传到 i18n
        $i18n: i18n
    }
}

  ** 说明:** 需要在所有 vue 里把这个 mixin 手动引入 (即 mixins: [i18nMixin]),这是目前已知的缺点。(更新:深入学习 vue3 后,发现有更好的方法,使用 composition api 实现 i18n 模块化解耦)

评论