i18n #
国际化处理其实是比较简单的,我们只需要准备各个语言下的对应描述,然后根据当前的语言使用该语言下的描述即可。
那么我们就需要一个变量来记录当前的语言。这个变量要求:
- 公用;
- 同步更新;
- 能触发watch/computed的重新计算;
我们可以使用vuex来辅助。
当前语言存入vuex中 #
const state = {
// 当前语言
language: ''
}
const mutations = {
setLanguage: (state, val) => {
state.language = val
}
}
const actions = {
}
export default {
namespaced: true,
state,
actions,
mutations
}
不同的语言版本描述 #
为了便于管理与维护,我们一般有一个模块用来维护所有的语言描述,我们可以命名为i18n。比如:
zh_cn.js
// zh_cn.js
export default {
name: 'nPro 国际化',
location: '中国 深圳',
desc: '国际化允许用户自行切换到不同的语言环境。实现国际化的方式有很多,在nPro中,我们提供了全端兼用的一种方式(nvue/vue下通用)。\n\n看具体的代码或者文档,您可以了解和学习如何实现国际化。\n\nnPro是uniapp生态下非常非常难得与优秀的组件库、工具库,她不仅提供了大量优秀的组件,许多设计精美的模版。她更是唯一一个精心于质量、效率和精品,并追求各端开发统一的开发利器。\n\nnPro中的每一个组件都能在nvue页面中使用,同样是一套代码,但却拥有了更高的性能。让我们为nPro喝彩。\n\nnPro追求精品,且设计灵活,高度可扩展与适配。在动画、皮肤、效率、质量上都是上乘之作。让我们一起为nPro欢呼。\n\nnPro也将继续努力,去实现更多的特效、动画和功能,让uniapp在页面实现上,变得无所不能,让开发复杂的交互效果变得更加简单。让我们一起去探索更多的可能,一起来支持nPro,让我们为nPro加油!',
recommend: '为你推荐',
more: '更多'
}
eng.js
export default {
name: 'nPro International',
location: 'ShenZhen China',
desc: 'International helps the app to fit users from languages. We have many ways to achieve it. In nPro, we choose the way fitting nvue and vue.\n\nReview the code or doc, you could learn how to make an i18n-app.\n\nnPro is absolutely the most excellent in uniapp. Excellent components and wonderful modules, all of these make the nPro a high-quality and high-efficiency helper.\n\nComponents in nPro can fit both nvue and vue. Code once, you get not only all platform, but with excellent quality. Let us cheer for nPro.\n\nnPro aspire excellence, and it is high-designable. nPro is excellent in animation, quality, and efficiency. Let us cheer for nPro.\n\nnPro will keep working to achieve more special effects, animation and functions. nPro will keep working to make uniapp possible for all kinds pages, make complicated into simple. Let\'s try nPro! Let\'s cheer for nPro!',
recommend: 'recommend',
more: 'more'
}
在这里面,我们定义了不同语言下的字段描述。需要注意的是,这些描述的字段在不同语言下都是一致的。比如,中文下key是name,那么英文下也是name。
接下来,我们只管使用就行。
提取当前语言下的对应字段描述 #
首先,我们需要根据不同的语言和当前的字段,取出对应的描述:
/**
* i18n示范
* 您需要根据您的项目需要引入合适的语言
*/
import zhLang from './zh_cn.js'
import engLang from './eng.js'
export default function $t(name, lang) {
if (!name) return ''
let items = zhLang
switch (lang) {
case 'eng':
items = engLang
break
defaut:
break
}
return items[name]
}
接下来,我们直接在需要的地方调用这个函数即可:
<template>
<view class="n-bg-page">
<image src="/static/house2.jpeg" style="width: 750rpx;height: 780rpx;" mode="aspectFill"></image>
<n-drawer :hasOverlay="false" standout="window-!638rpx" height="window-!status-!nav">
<view :class="['n-bg-inverse'+theme]" style="height: 78rpx;border-top-right-radius: 78rpx;border-top-left-radius: 78rpx;"></view>
<n-list :bgType="'inverse'+theme" :down="null" :up="null" height="window-!status-!nav-!60rpx-!78rpx">
<n-list-cell>
<view class="n-flex-row n-align-center n-justify-between" style="margin-left: 60rpx;margin-right: 60rpx;">
<text :class="['n-color-text'+theme, 'n-weight-9']" style="font-size: 42rpx;" @click="toChangeLang">{{title}}</text>
<n-icon name="love-solid" type="error" iconStyle="font-size:52rpx;" @iconClicked="toChangeLang"></n-icon>
</view>
<view class="n-flex-row n-align-center" style="margin-top: 12rpx;margin-left: 60rpx;">
<n-icon name="map" :type="'second'+theme" size="base"></n-icon>
<text :class="['n-color-second'+theme, 'n-size-base', 'n-lh-base']" style="margin-left: 12rpx;">{{location}}</text>
</view>
<view class="n-flex-row n-align-center" style="margin-left: 60rpx;margin-top: 12rpx;">
<n-rate :value="5"></n-rate>
<text :class="['n-color-second'+theme, 'n-size-ll', 'n-weight-7', 'n-lh-ll']" style="margin-left: 12rpx;">5</text>
</view>
</n-list-cell>
<n-list-cell>
<view style="height: 36rpx;"></view>
<view style="margin-left: 60rpx;">
<text :class="['n-color-second'+theme, 'n-size-base', 'n-lh-base']" style="width: 630rpx;">{{desc}}</text>
</view>
</n-list-cell>
<n-list-cell>
<view style="height: 52rpx;"></view>
<view class="n-flex-row n-align-center" style="margin-left:60rpx;">
<n-avatars :items="members" label="avatar"></n-avatars>
<text :class="['n-color-second'+theme, 'n-size-s', 'n-lh-s']" style="margin-left: 16rpx;">+520</text>
</view>
</n-list-cell>
<n-list-cell>
<view style="height: 36rpx;"></view>
<view class="n-flex-row n-align-center n-justify-between" style="height: 62rpx;padding-left: 60rpx;padding-right: 60rpx;">
<text class="n-color-primary n-size-ll n-weight-7" @click="toChangeTheme">{{recommend}}</text>
<text class="n-color-primary-opacity n-size-ss n-weight-7" @click="toChangeTheme">{{more}}</text>
</view>
<view style="height: 36rpx;"></view>
</n-list-cell>
<n-list-cell v-for="(row,idx) in chunkPhotos" :key="idx">
<view class="n-flex-row n-wrap-nowrap" style="margin-left: 36rpx;">
<image v-for="(img,ixx) in row" :key="ixx" :src="img.cover" mode="aspectFill" style="margin-right: 20rpx;margin-bottom: 20rpx;width: 330rpx;height: 534rpx;border-radius: 16rpx;"></image>
</view>
</n-list-cell>
<n-list-cell>
<n-height height="x"></n-height>
</n-list-cell>
</n-list>
</n-drawer>
<n-navbar bgType="none" :fixed="true" :isSeize="false" :lefts="leftIcons" :rights="rightIcons" @leftAction="navLeftAction" @rightAction="navRightAction"></n-navbar>
</view>
</template>
<script>
import {mapGetters} from 'vuex'
import navHelper from '@/service/navHelper.js'
import {arrayChunk} from '@/nPro/utils/utils.js'
import $t from '@/i18n/index.js'
export default {
mixins: [navHelper],
data() {
return {
rightIcons: [{icon: 'elipsis', iconStyle: 'font-size:26px;'}],
photos: [
{cover: '/static/sea.jpeg', title: '透明化', desc: '得益于nPro的可扩展性,您可以在nPro中随意增删主题,比如透明化的主题。我们这里就示范了如何增加透明化的主题。'},
{cover: '/static/house1.jpeg', title: '抽屉', desc: 'nPro应该是市场上最具功能实用性的组件,市面上很多优秀与复杂的设计我们都有提供。可跟手的抽屉就是一大特色。'},
{cover: '/static/house2.jpeg', title: '设计', desc: 'nPro设计精美,里面的大多数单独的页面,就足以让您物超所值,更何况您还有一群共同学习与进步的朋友。'},
{cover: '/static/snow.jpeg', title: '换肤', desc: 'nPro的主题设计绝对是一大亮点,在规范和高效的同时,还允许您不断扩展,比如实现一键换肤。'},
],
members: [{avatar: '/static/caiman.jpeg'}, {avatar: '/static/logo-dark.png'}, {avatar: '/static/caiman.jpeg'}, {avatar: '/static/girl1.jpeg'}]
}
},
computed: {
...mapGetters(['theme', 'language']),
chunkPhotos() {
return arrayChunk(this.photos, 2)
},
title() {
return $t('name', this.language)
},
location() {
return $t('location', this.language)
},
desc() {
return $t('desc', this.language)
},
recommend() {
return $t('recommend', this.language)
},
more() {
return $t('more', this.language)
}
},
methods: {
navRightAction(i) {
},
toChangeTheme() {
if (this.theme) {
this.$store.commit("theme/setTheme", '')
} else {
this.$store.commit("theme/setTheme", '_dark')
}
},
toChangeLang() {
if (this.language) {
this.$store.commit("i18n/setLanguage", '')
} else {
this.$store.commit("i18n/setLanguage", 'eng')
}
}
}
}
</script>
<style lang="scss" scoped>
</style>