# vue-international-project **Repository Path**: codeResp/vue-international-project ## Basic Information - **Project Name**: vue-international-project - **Description**: vue2.x + vue-i18n@7.x 实现项目国际化 - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-02-17 - **Last Updated**: 2022-02-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 使用 vue-i18n 完成国际化 国际化,就是你的项目有国外客户.你要根据用户处在的地理位置,在你的项目中显示当地的语言.仅此而已. 比如: + 中国人,项目里显示中文. + 日本人,项目里显示日文. + 美国人,项目里显示英文. + .... 使用`vue-i18n`来解决这个问题,极其简单. --- ### vue 使用 vue-i18n 来处理国际化问题. + step 1. 安装 `vue-i18n` 库 ```shell npm i vue-i18n@7 --save # 这里安装 7 版本是基于 vue2 项目. ``` + step 2. 配置 `vue-i18n` 库. ```javascript import VueI18n from 'vue-i18n' Vue.use(VueI18n) // 插件注册 // 创建 VueI18n 实例 const vueI18n = new VueI18n({ locale: 'zh', messages: { zh: { login: '登录', register: '注册', changeLanguage: '切换语言' }, en: { login: 'login', reigster: 'register', changeLangugae: '切换语言' } } }) new Vue({ ..., i18n, // 根组件实例挂在. }).$mount('#app') ``` + step 3 在你需要切换语言的组件中,使用 `$t` 函数调用即可. ```JavaScript {{$('login')}} {{$('register')}} {{$('changeLangugae')}} ``` 基本效果如下  `vue-i18n` 这个库解决国际化的 API 十分简单. 但有几个点让我们注意: + this.$i18n.locale='xx' 在修改了配置后,页面自动刷新,所以这一块是响应式的. + 内部是使用当前组件实例的 `vm.$forceUpdate()` 来实现的. --- ## 自己实现一个国际化工具. 在了解了 `vue-i18n` 的基本原理后,自己实现一个 `i18n` 的轮子也很简单. 基本实现步骤如下: + 实现一个 Vue 的插件. `MyI18n` 是一个构造函数(`new MyI18n()`)也是一个插件函数(`Vue.use(MyI18n)`). + 当 `MyI18n` 作为插件或者构造函数调用时,分别处理有对应的处理逻辑. + 当 `MyI18n` 作为构造函数时,需要创建一个实例,实例主要记录用户传递的 `messages` 以及 `locale` 属性. + 由于后期在调用 `myi18n.locale` 时,需要更新界面,所以,将 locale 定义成响应式的属性. + 在调用 `this.$myi18n.locale=newvalue` 需要在 `locale` 的 `setter` 里面调用 `vm.$forceUpdate()`来更新视图. + 当 `MyI18n` 作为插件时候. + 在 `Vue.prototype` 上挂在 `$tt` 方法,由于返回`key`对应的国际化值(这个不需要是响应式). + 此时,由于 `$tt`是在模板中使用的,我们需要在调用此此函数的时候,将当前组件实例传入(`{{$tt('login',vm)}}`) 实现代码如下: ```javascript import Vue from 'vue' export default function MyI18n (config) { // 如果是 new 调用 if (this instanceof MyI18n) { // 将 locale 属性设置成响应式,在 setter 的时候,拿到 vm 实例,调用 vm.$forceUpdate() 去更新视图. this.defineLocaleReactive(config.locale) // 单独记录 messages this.messages = config.messages Vue.prototype.$myi18n = this // 记录当前实例,全局只有一个 } else { // 传递 Vue.prototype.$tt = function (keychain, vm) { // 链式获取当前属性的值. const value = getValueByKeychain(Vue.prototype.$myi18n.messages[Vue.prototype.$myi18n.locale], keychain) // 在模板中记录当前的组件实例对象 Vue.prototype.$myi18n_vm = vm // 返回链式调用的结果,在界面显示(这一步不需要响应式) return value } } } MyI18n.prototype.defineLocaleReactive = function (locale) { Object.defineProperty(this, 'locale', { get () { return locale }, set (v) { locale = v // 当调用 this.$myi18n.locale 时,需要更新视图. updateView() } }) } let updateView = function () { // 视图更新 Vue.prototype.$myi18n_vm.$forceUpdate() } // 支持链式属性值获取 (a.b.c.d) function getValueByKeychain (object, keychain) { const keys = keychain.split('.') let finallyValue = object for (let i = 0; i < keys.length; i++) { finallyValue = finallyValue[keys[i]] } return finallyValue } ``` 使用 ```javascript import MyI18n from './MyI18n' Vue.use(MyI18n) new MyI18n({ locale: 'zh', messages: { zh: { login: '登录', register: '注册', changeLanguage: '切换语言' }, en: { login: 'login', register: 'register', changeLanguage: 'changeLanguage' } } }) // console.log(Vue.prototype.$myi18n); ``` 在组件中使用: ```javascript MyI18n 测试 {{ $tt("login", vm) }} {{ $tt("register", vm) }} {{ $tt("changeLanguage", vm) }} ``` 效果如下:  [码云地址](https://gitee.com/codeResp/vue-international-project.git)