道招

vue多语言的解决方案不只是 vue-i18n,前端+后端完整解决方案

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

vue多语言的解决方案不只是 vue-i18n,前端+后端完整解决方案

网上搜很多vue多语言的,一般都是介绍vue-i18n怎么使用,当然这是不错的,但是我们如果只是讲这个的话,只是解决了静态文字的多语言化。

这一部分我们也简单讲一下

npm install vue-i18n --save安装

// main.js
import VueI18n from 'vue-i18n';
import messages from './i18n';

Vue.use(VueI18n);
const locale = (localStorage.getItem("language") || navigator.language || navigator.browserLanguage).toLowerCase();
为了避免被坑都转成小写。
// 通过选项创建 VueI18n 实例
const i18n = new VueI18n({
  locale, // 设置地区
  messages, // 设置地区信息
});
new Vue({
  router,
  store,
  i18n,
  render: (h) => h(App),
}).$mount('#app');

里面的messages就是我们的多语言数据

//i18n/index.js
export default {
    ['zh-cn']: {
        hello: '你好',
    },
    ['en-us']: {
        hello: 'Hello',
    }
}

这里的zh-cn是和上面的zh-cn对应的.

在.vue文件里面使用时就是这样

<tempalate>
    <div> 
        {{$t('hello')}}
    </div>
</tempalate>

到这里vue-i18n说完了

很多时候我们在处理接口返回、录入的数据也需要支持多语言的。比如电商运营人员是需要提前分别输入商品的中文名和英文名的。 否则会出现这样的(这是一个录入电商运营人员录入品牌信息的页面)

file

是不是多少有点怪啊。 我们是不是需要这种 录入英文

file

录入中文

file

前端怎么实现的? 在没有多语言的情况下,表单绑定的数据是这样的

dataForm = {
    brandName: '',
    sort: 0,
    isDisplay: 1,
}

显然这里的品牌名brandName是需要支持的多语言的,其它的都是数字也不涉及到什么多语言。

我们需要改造下dataForm

dataForm = {
    brandName: {
        ['en-US']: '',
        ['zh-CN']: ''
    },
    sort: 0,
    isDisplay: 1,
}

此时dataForm.brandName不再是字符串了,而是对象了,这样我们就根据key的变化显示对应的值,这样brandName能使用多语言了。

实际使用过程中跟上面的例子还是略有不同的

  1. 某个用户支持哪些语言,提前是不知道的,需要有一个单独提供支持语言的接口返回的,所以我们无法简单的像brandName: {['en-US']: '',['zh-CN']: ''},这样写死的。
  2. 历史数据怎么处理?历史数据都是不支持多语言的啊,总不能自行判断,然后有的brandName是字符串,有的是对象吧,想想都不好处理。如果所有的数据都是统一格式不就好了?这时很自然的想到了数据的归一化。可以参考我昨天写的《从mapState、mapMutations的源码看数据归一化normalize》

首先我们要支持一点,既然开始支持多语言了,那就需要用户指定一个默认语言,历史数据就是那个默认语言的数据。 以上面的例子的后端返回数据为例继续讲。 后端肯定不会再原始表里面加字段,比如en-US-brandName之类的。他们会建立一个多语言的表,专门存储多语言信息,在原始表里面还是存储默认语言信息。

这样如果数据已经存在多语言的会返回这样,默认语言为中文zh-CN

    data: {
        brandName: '品牌XX',
        sort:2,
        isDisplay: 1,
        langMap: {
            'zh-CN': {
                brandName:  '品牌XX',
            },
            'en-US: {
                brandName:  'brandXX',
            }
        }
    }

外层的brandName的值就是该用户的默认语言的值,这样也是为了兼容性考虑的。 历史数据(也就是前端没有提交过多语言信息的)

    data: {
        brandName: '品牌XX',
        sort:2,
        isDisplay: 1,
    }

其实你是多么希望就算原来没有多语言,后端也会这样返回

    data: {
        brandName: '品牌XX',
        sort:2,
        isDisplay: 1,
        langMap: {
            'zh-CN': {
                brandName:  '品牌XX',
            },
        }
    }

哈哈,每一个强大的前端都是被产品、后端、设计师、测试逼出来的

前端就要这么强。

我们可以根据接口拿到数据后,自己判断是否有langMap,如果没有,我们就直接将数据归一化变成含有langMap的。 然后我们需要根据langMap再次处理数据,最终变成

data(){
    return {
        dataForm = {
            brandName: {
                ['en-US']: 'brandXX',
                ['zh-CN']: '品牌XX'
            },
            sort: 0,
            isDisplay: 1,
        },
        languageList:[{
            languageCode: 'zh-CN',
            language: '简体中文'
        },{
            languageCode: 'en-US',
            language: 'Englist'
        }]
    };
},
<template>
    <section>
        <el-radio-group
                class="lang-select"
                :value="currentLang"
                size="small"
              >
                <el-radio-button
                  v-for="(item, index) in languageList"
                  :key="'lang' + index"
                  :class="currentLang === item.languageCode ? 'active' : ''"
                  :label="item.languageCode"
                  @click.native="currentLang = item.languageCode"
                >
                  {{ item.language }}
                </el-radio-button>
        </el-radio-group>

        <el-form :model="dataForm">
            <el-form-item :label="$t('brand_name')" prop="brandName">
                <el-input
                v-model.trim="(dataForm.brandName || {})[currentLang]"
                maxlength="50"
                ></el-input>
            </el-form-item>
            <el-form-item :label="$t('sort')" prop="sort">
                <el-input
                v-model.trim="dataForm.sort"
                ></el-input>
            </el-form-item>
            <el-form-item
                    :label="$t('display_is_or_no')"
                    prop="isDisplay"
                  >
                    <el-radio-group v-model="dataForm.isDisplay">
                      <el-radio :label="1">{{ $t("yes") }}</el-radio>
                      <el-radio :label="0">{{ $t(no") }}</el-radio>
                    </el-radio-group>
                  </el-form-item>
        </el-form>
    </section>
</template>

这里的上半部分就是多语言选择器那一部分了,通过点击切换当前语言currentLang,下面的v-model.trim="(dataForm.brandName || {})[currentLang]"这里的品牌名的值也就会切换对应的key显示对应的文字了。

更新时间:
上一篇:pixel 3A (XL ) android P root教程Magisk下一篇:vue单元测试vuex,mutation,尤其是actions、getters怎么测?让你像使用vuex一样测试vuex

相关文章

vue发送请求是应该在mounted还是在created生命周期

一个经常会被问到的问题: 为什么不在 created 里去发ajax? created 可是比 mounted 更早调用啊,更早调用意味着更早返回结果,那样性能不是更高? 首先,一 阅读更多…

vue实现自定义组件的v-model双向数据绑定

一般来说我们用v-model是在input中 常见用法如下 &lt;input type="text" v-model="username"&gt; 用户名:{{username}} 其 阅读更多…

Vue2.6.10源码分析(一)vue项目怎么神奇的跑起来的

先看index.html的代码吧 &lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; &lt;meta 阅读更多…

用个数组来理解vue的diff算法(一)

原文地址: 道招网 的 用个数组来理解vue的diff算法(一) Vue使用的diff算法,我相信用vue的估计都听过,并且看到源码的也不在少数。 先对下面的代码做下说明: 由于这里用 阅读更多…

vue内置组件keep-alive源码解析

很简单,我们直接看vue的源码即可。 keep-alive 组件支持三个属性。 props: { include: patternTypes, exclude: patter 阅读更多…

命令式组件Message、Dialog的主流写法分析

这里还是以element-ui为例,那我们就看看里面的Message。 它的dom结构什么的就写在node-modules/element-ui/packages/notification/src/ 阅读更多…

关注道招网公众帐号
友情链接
消息推送
道招网关注互联网,分享IT资讯,前沿科技、编程技术,是否允许文章更新后推送通知消息。
允许
不用了