使用vue-i18n插件实现国际化+json文件国际化

参考:Vue I18nuniapp与vue-i18n实现国际化多语言uni-app 如何语言国际化/多语言处理

1. 一般实现

1.1 main.js

import Vue from 'vue'
import App from './App'
import i18n from './commons/i18n.js'  
import en from './commons/language/en_US.js'
import zh from './commons/language/zh_CN.js'
i18n.registerLocale({en,zh})

Vue.config.productionTip = false

Vue.prototype._i18n = i18n 
App.mpType = 'app'

const app = new Vue({
     i18n,  
    ...App
})
app.$mount()

备注:main.js文件:定义全局函数和变量
(1) i18n.js

module.exports = {
  locale: 'zh', // 默认选择的语言
  locales: {},
  registerLocale (locales) {
    this.locales = locales
  },
  setLocale (code) {
    this.locale = code
    uni.setStorageSync("languageKey",code)
  },
  getLanguage(){
    //return this.locales[this.locale];
    this.locale = uni.getStorageSync("languageKey") || this.locale
    return this.locales[this.locale];
  },
  /**
   * 返回带(或不带)参数的类型的翻译结果
   * @param {string} key, /util/language/en.js 中的键名,如 "curslide"
   * @param {object} data, 传入的参数,如 {num: 123}
   * @returns {string}
   *
   * @desc 如:"activeno": "当前学生{activeno}位",
   *       activeno 为 key,可以输入data {activeno: 15}
   *       返回:"当前学生15位"
   */
  _ (key, data) {
    let locale = this.locale
    let locales = this.locales
    if (locale && locales[locale] && locales[locale][key]) {
      key = locales[locale][key]
    }

    return key
  },
  /**
   * 返回二选一类型的翻译结果
   * @param {string} key, /util/language/en.js 中的键名,如 "curslide"
   * @param {object} data, 传入的参数,如 {first: true} 选择前面的
   * @returns {string}
   *
   * @desc 如:"sendprob": "Send | Check",
   *       sendprob 为 key,可以输入data {first: true}
   *       返回:"Send"
   */
  _b (key, data) {
    let locale = this.locale
    let locales = this.locales
    let hasKey = locale && locales[locale] && locales[locale][key]
    
    if (hasKey) {
      key = locales[locale][key]

      let res = key.split('|')[data.first ? 0 : 1].trim()

      return res
    }
    throw new Error(`语言处理错误${key}`)
  }
}

(2) zh_CN.js

module.exports = {
  //通用
  "currency": {
    'home':'主页',
    "machine":"机器",
    "statistic":"统计",
    "mine": "我的",
    "submit":"提交"
  },
  //主页
  "home": {
    "keyword": "输入关键字",
    "search": "搜索"
  },
  //我的
  "mine":{
    "langSelect": "语言选择",
    "signOut": "退出",
    "confirm": "确定",
    "cancel": "取消"
  }
}

(3) en_US.js

module.exports = {
  //通用
  "currency":{
    'home': 'Home',
    "machine":"Machine",
    "statistic":"Statistic",
    "mine": "Mine",
    "submit":"submit"
  },
  //主页
  "home":{
    "keyword": "please input keyword",
    "search": "search"
  },
  //我的
  "mine":{
    "langSelect": "Language",
    "signOut": "Sign out",
    "confirm": "confirm",
    "cancel": "cancel"
  }

}

1.2 检测系统语言并改变 locale 值

在 app.vue 的 onLaunch 中使用 uni.getSystemInfoSync()得到系统当前语言

onLaunch: function() {
    console.log('App Launch');
    var lan = 'zh'
    try {
        const res = uni.getSystemInfoSync();
        lan = res.language
    } catch (e) {
        console.log('error='+e)
    }
    console.log('lan='+lan); 
    if(lan == 'en') {
        this._i18n.setLocale('en')
    }
    if(lan == 'zh-Hans-CN' || lan=='zh') {
        this._i18n.setLocale('zh')
    }
},

1.3 国际化实现

(1) 页面两种调用方式

<template>
    <view class="uni-content">  
        <text>{{lanObj.keyword}}</text>  
        <text>{{lanObj.search}}</text>  
    </view>  
    <button>{{_i18n.getLanguage().currency.submit}}</button>  
</template>

<script>
export default {
    data() {
        return {
            lanObj : {},
        };
    },
    onLoad:function(){
        this.lanObj = this._i18n.getLanguage().myhome;
    }
}
</script>

<style>

</style>

(2) 底部导航和顶部导航国际化实现

  • 顶部的title,用uni.setNavigationBarTitle动态设置文字
  • 底部tabbar,用uni.setTabBarItem的api动态设置文字
refreshLanguage:function(){
    console.log("当前语言为:"+this._i18n.locale)
    this.lanObj = this._i18n.getLanguage().mine;

    //顶部的title
    uni.setNavigationBarTitle({
        title:this._i18n.getLanguage().mine.editPerson
    })

    //底部tabbar
    uni.setTabBarItem({
        index: 0,
        text: this._i18n.getLanguage().currency.home
    })
    uni.setTabBarItem({
        index: 1,
        text: this._i18n.getLanguage().currency.machine
    })
    uni.setTabBarItem({
        index: 2,
        text: this._i18n.getLanguage().currency.statistic
    })
    uni.setTabBarItem({
        index: 3,
        text: this._i18n.getLanguage().currency.mine
    })
}

(3) Input 框里的placeholder内容国际化

<input type="text" :placeholder="_i18n.getLanguage().home.search"></input>

(4) 列表数据国际化

<template>
    <view class="uni-flex uni-column" style="width: 100%;height: 100%;">
        <view class="flex-twice uni-flex justify-center">
            <view class="cu-list grid col-3 no-border" style="width: 100%;">
                <view class="cu-item" v-for="(item,index) in cuIconList" :key="index">
                    <view :class="['cuIcon-' + item.cuIcon,'text-' + item.color]"></view>
                    <text>{{item.name}}</text>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
export default {
    data() {
        return {
            lanObj : {},
            cuIconList: [
                {
                    url:'machineManage',
                    cuIcon: 'cardboardfill',
                    color: 'olive',
                    name: this._i18n.getLanguage().mine.machineCenter
                }, {
                    url:'userManage',
                    cuIcon: 'friendfill',
                    color: 'blue',
                    name: this._i18n.getLanguage().mine.employeeCenter
                }, {
                    url:'edgeSettings',
                    cuIcon: 'settingsfill',
                    color: 'yellow',
                    name: this._i18n.getLanguage().mine.edgeSetting
                }, {
                    url:'ota',
                    cuIcon: 'upload',
                    color: 'yellow',
                    name: this._i18n.getLanguage().mine.firmwareUpgrade
                }, {
                    url:'log',
                    cuIcon: 'form',
                    color: 'blue',
                    name: this._i18n.getLanguage().mine.logView
                }, {
                    url:'userModify',
                    cuIcon: 'peoplefill',
                    color: 'olive',
                    name: this._i18n.getLanguage().mine.personalInformation
                }
            ],
        }
    },
    methods: {
        refreshLanguage:function(){
            this.lanObj = this._i18n.getLanguage().home;
            this.cuIconList[0].name = this._i18n.getLanguage().mine.machineCenter;
            this.cuIconList[1].name = this._i18n.getLanguage().mine.employeeCenter;
            this.cuIconList[2].name = this._i18n.getLanguage().mine.edgeSetting;
            this.cuIconList[3].name = this._i18n.getLanguage().mine.firmwareUpgrade;
            this.cuIconList[4].name = this._i18n.getLanguage().mine.logView;
            this.cuIconList[5].name = this._i18n.getLanguage().mine.personalInformation;
        }
    },
    onLoad:function(){
        
    },
    onShow:function(){
        this.refreshLanguage();
    }
}
</script>

<style>

</style>

  • 情形一:切换语言后国际化失败(数据列表定义为字符串数组)
<template>
    <view>
        <view class="bar-nav" style="margin-top: 55px;padding-bottom: 5px;">
            <view class="nav-item" :class="index==TabCur? 'nav-text nav-cur':''" v-for="(item,index) in tabNav" :key="index" @tap="tabSelect" :data-id="index">
                {{item}}
            </view>
        </view>
    </view>
</template>

<script>
export default {
    data() {
        return {
            lanObj:{},
            TabCur: 0,
            tabNav: [this._i18n.getLanguage().device.machine,this._i18n.getLanguage().device.repeater]
        }
    },
    methods: {
        refreshLanguage:function(){
            this.lanObj = this._i18n.getLanguage().device;
            this.tabNav[0] = this.lanObj.machine;
            this.tabNav[1] = this.lanObj.repeater;
        },
        tabSelect(e) {
            this.TabCur = e.currentTarget.dataset.id;
        }
    },
    onLoad() {
        
    },
    onShow:function(){
        this.refreshLanguage()
    }
}
</script>

<style scoped lang="scss">

</style>

  • 情形二:切换语言后国际化成功(数据列表定义为对象数组)
<template>
    <view>
        <view class="bar-nav" style="margin-top: 55px;padding-bottom: 5px;">
            <view class="nav-item" :class="index==TabCur? 'nav-text nav-cur':''" v-for="(item,index) in tabNav" :key="index" @tap="tabSelect" :data-id="index">
                {{item.name}}
            </view>
        </view>
    </view>
</template>

<script>
export default {
    data() {
        return {
            lanObj:{},
            TabCur: 0,
            // tabNav: [this._i18n.getLanguage().device.machine,this._i18n.getLanguage().device.repeater],
            tabNav: [
                {
                    "id":0,
                    "name":this._i18n.getLanguage().device.machine
                },
                {
                    "id":1,
                    "name":this._i18n.getLanguage().device.repeater,
                }
            ]
        }
    },
    methods: {
        refreshLanguage:function(){
            this.lanObj = this._i18n.getLanguage().device;
            // this.tabNav[0] = this.lanObj.machine;
            // this.tabNav[1] = this.lanObj.repeater;
            this.tabNav[0].name = this.lanObj.machine;
            this.tabNav[1].name = this.lanObj.repeater;
        },
        tabSelect(e) {
            this.TabCur = e.currentTarget.dataset.id;
        }
    },
    onLoad() {
        
    },
    onShow:function(){
        this.refreshLanguage()
    }
}
</script>

<style scoped lang="scss">

</style>

1.4 语言切换

<template>
    <view class="center">
        <view class="center-list">
            <navigator url="about" hover-class="navigator-hover">
                <view class="center-list-item">
                    <text class="list-text">{{lanObj.languageSettings}}</text>
                    <picker style="width: 300upx;" @change="bindPickerChange" :value="index" :range="array" range-key="name">
                        <view class="uni-input picker-view">{{array[index].name}}</view>
                    </picker>
                </view>
            </navigator>
        </view>
    </view>
</template>

<script>
export default {
    data() {
        return {
            lanObj : {},
            index: 0,
            array: [{name:'中文'},{name: 'English'}],
        }
    },
    onLoad() {
        this.refreshPageLanguage();
    },
    methods: {
        refreshPageLanguage:function(){
            // console.log("当前语言为:"+this._i18n.locale)
            // console.log(JSON.stringify(this._i18n.locales))
            this.lanObj = this._i18n.getLanguage().myhome;
        },
        bindPickerChange: function(e) {
            console.log('picker发送选择改变,携带值为:' + e.detail.value)
            this.index = e.detail.value
            if(this.index == 0){
                this._i18n.setLocale('zh')
            }else if(this.index == 1){
                this._i18n.setLocale('en')
            }
            this.refreshPageLanguage();
        }
    }
}
</script>

<style>

</style>

2. json文件国际化

思路:直接提供翻译的json,然后以一种格式命名,例如 data_zhCN.json,data_enUS.json。然后根据当前使用的语言来加载对应的json文件。

(1) zh.js

{
    "dataOfLocalZh": {
        "pingParms": [{
            "id": "P1",
            "name": "起缝速度",
            "type":"slider",
            "value": "2000",
            "min":"1000",
            "max":"8000",
            "step":"10"
        }, {
            "id": "P2",
            "name": "自由缝最高速度(全局最高限速)",
            "type":"slider",
            "value": "200000",
            "min":"10000",
            "max":"250000",
            "step":"50"
        }],
        "baoParms": [{
            "id": "P1",
            "name": "最高转速",
            "type":"slider",
            "value": "6000",
            "min":"500",
            "max":"6000",
            "step":"100"
        }, {
            "id": "P3",
            "name": "起缝速度",
            "type":"slider",
            "value": "500",
            "min":"500",
            "max":"6000",
            "step":"100"
        }]
    }
}

(2) en.js

{
    "dataOfLocalZh": {
        "pingParms": [{
            "id": "P1",
            "name": "Seating speed",
            "type":"slider",
            "value": "2000",
            "min":"1000",
            "max":"8000",
            "step":"10"
        }, {
            "id": "P2",
            "name": "Free seam maximum speed (global maximum speed limit)",
            "type":"slider",
            "value": "200000",
            "min":"10000",
            "max":"250000",
            "step":"50"
        }],
        "baoParms": [{
            "id": "P1",
            "name": "Maximum speed",
            "type":"slider",
            "value": "6000",
            "min":"500",
            "max":"6000",
            "step":"100"
        }, {
            "id": "P3",
            "name": "Seating speed",
            "type":"slider",
            "value": "500",
            "min":"500",
            "max":"6000",
            "step":"100"
        }]
        
    }
}

(3) test.vue

<view v-if="machineParms.length > 0" class="container-right">
    <view class="item" v-for="(item,index) in machineParms" :key="index">
        <view>{{item.name}}</view>
        <view v-if="item.type == 'slider' || item.type == 'radio'" @click="showModel(item)">
            {{item.value}}
        </view>
        <view v-if="item.type == 'switch'">
            <switch :checked="item.checked" @change="switchChange" color="#04be02" :data-id="item.id"/>
        </view>
    </view>
</view>

<script>
//import  { dataOfLocal } from '@/common/data.json';
import  { dataOfLocalZh } from '@/common/data/zh.json';
import  { dataOfLocalEn } from '@/common/data/en.json';
export default {
    data() {
        return {
            cate:"6",
            machineParms:[],
        }
    },
    methods: {
        getLocalData(){
            console.log(dataOfLocal);
            if(this.cate=="6"){
                // this.machineParms = dataOfLocal.pingParms;
                if(this._i18n.getLanguage == "zh"){
                    this.machineParms = dataOfLocalZh.pingParms;
                }else{
                    this.machineParms = dataOfLocalEn.pingParms;
                }
            } else if(this.cate=="7"){
                // this.machineParms = dataOfLocal.baoParms;
                if(this._i18n.getLanguage == "zh"){
                    this.machineParms = dataOfLocalZh.baoParms;
                }else{
                    this.machineParms = dataOfLocalEn.baoParms;
                }
            }

    }

}
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,961评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,444评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,009评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,082评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,101评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,271评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,738评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,395评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,539评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,434评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,481评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,160评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,749评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,816评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,038评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,548评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,140评论 2 341