本文正在参与「金石方案 . 分割6万现金大奖」
接上篇 《项目创立与初始装备》 继续搭建咱们的后台项目。
由于项目是给设在新加坡、马来西亚的海外自提站运用的后台,所以国际化的装备必不可少。需求切换言语的内容首要分为两部分:
- 咱们自己增加的案牍内容,需求用到 vue-i18n-next;
- naive ui 的组件,能够运用
n-config-provider
装备。
vue-i18n-next
装置
vue3 中运用 i18n 需求装置的是 vue-i18n v9 的版别:
npm install vue-i18n@9
装备 i18n
创立 srclangindex.ts,运用 createI18n
创立 i18n 实例:
// srclangindex.ts
import { createI18n } from 'vue-i18n'
import { LANG_VALUE } from '@/common/enum'
import zhHans from './zh-Hans'
import en from './en'
const i18n = createI18n({
legacy: false,
locale: getLanguage(),
messages: {
[LANG_VALUE.Zh]: zhHans,
[LANG_VALUE.En]: en
}
})
export default i18n
下面对传入 createI18n()
的装备目标做些阐明:
-
legacy:默以为
true
,但假如运用的是 Composition API 则需求界说为false
,否则会报类似下面的错误:
-
locale:当时要展示的言语。值为之前用户的言语挑选,从浏览器缓存中读取。假如缓存中没有数据,则通过
navigator.language
获取浏览器运用的言语:
// srclangindex.ts
import { localCache } from '@/utils'
export function getLanguage() {
const chooseLanguage = localCache.getItem(LANGUAGE)
if (chooseLanguage) return chooseLanguage
// 假如没有挑选言语
const language = navigator.language.toLowerCase()
const locales = [LANG_VALUE.En, LANG_VALUE.Zh]
for (const locale of locales) {
if (language.indexOf(locale) > -1) {
return locale
}
}
return LANG_VALUE.Zh
}
由于 locale
值在多个文件中有运用到,所以我运用了 ts 新增类型 enum(枚举类型)来保存:
// srccommonenum.ts
export enum LANG_VALUE {
En = 'en',
Zh = 'zh-Hans'
}
- messages:不同言语对应的翻译文件:
中文翻译包:
// srclangzh-Hans.ts
export default {
baoguochuku: '包裹出库',
sousuo: '查找'
}
英文翻译包:
// srclangen.ts
export default {
baoguochuku: 'Outbound',
sousuo: 'Search'
}
在 main.ts 引进
// srcmain.ts,省略其它代码
import i18n from './lang/index'
app.use(i18n)
在文件中运用
vue 文件
- 在
<script lang="ts" setup>
中运用
下面以侧边导航菜单中,对每条导航的称号的装备为例。从 vue-i18n 中导入 useI18n
,然后进行调用生成 i18n
实例,再从里边解构得到 t
办法,在第 6 行进行运用 —— t(route.meta.title)
,route.meta.title
是我在路由里装备的内容,其值就是在言语翻译文件中界说的那些 key,比如 'baoguochuku'
等:
<!-- srccomponentsNavigationNavigation.vue,省略其它代码 -->
<script lang="ts" setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const menuOptions: MenuOption[] = modulesRoutes.map(route => ({
label: () => t(route.meta.title),
// ...
}))
</script>
这儿注意下 label 的值得写成 getter 的形式,假如是写成 label: t(route.meta.title)
这样直接赋值,则切换言语时是没有作用的。
- 在
<template>
中运用
运用办法与之前在 vue2 中一样:
<template>
<n-button>
<slot name="submitBtnText">{{ $t('sousuo') }}</slot>
</n-button>
</template>
这儿之所以能够直接运用 $t
是由于有个叫做 globalInjection
的装备项默以为 true
,帮咱们大局注入了 $t
办法,假如设置为 false
:
// srclangindex.ts
const i18n = createI18n({
// ...
globalInjection: false
})
则会报错:
ts 文件
在 ts 文件中,则需求引进咱们之前在 srclangindex.ts 装备生成的 i18n
实例,然后通过 i18n.global.t()
来界说案牍:
// srcservicerequestindex.ts
import i18n from '@/lang'
if (!axios.isCancel(error)) {
dialog.error({
title: i18n.global.t('tishi'),
// ...
})
}
至此,项目里咱们自己增加的内容的国际化就装备完成了,接下来是对 naive ui 组件的国际化装备。
naive ui 组件
关于 naive ui 的组件,默许情况下均为英语,假如想改为中文,需求在根组件 srcApp.vue 中运用 n-config-provider 对言语进行装备,将用于设置大局言语的 locale
设为从 naive ui 导入的zhCN
,设置大局日期言语的 date-locale
为从 naive ui 导入的 dateZhCN
:
<!-- srcApp.vue -->
<script setup lang="ts">
import { storeToRefs } from 'pinia'
import useAppStore from '@/stores/app'
const appStore = useAppStore()
const { locale, dateLocale } = storeToRefs(appStore)
</script>
<template>
<n-config-provider
:locale="locale"
:date-locale="dateLocale"
>
<RouterView />
</n-config-provider>
</template>
locale
和 dateLocale
作为由 pinia 管理的 getter 界说在 srcstoresapp.ts:
// srcstoresapp.ts
import { defineStore } from 'pinia'
import { zhCN, dateZhCN } from 'naive-ui'
import { LANG_VALUE } from '@/common/enum'
import { getLanguage } from '@/lang'
interface IAppState {
language: string
// ...
}
const useAppStore = defineStore('app', {
state: (): IAppState => ({
language: getLanguage(),
// ...
}),
getters: {
locale(state) {
switch (state.language) {
case LANG_VALUE.En:
return null
case LANG_VALUE.Zh:
return zhCN
default:
break
}
},
dateLocale(state) {
switch (state.language) {
case LANG_VALUE.En:
return null
case LANG_VALUE.Zh:
return dateZhCN
default:
break
}
}
},
// ...
})
export default useAppStore
当 language
为 'en'
时,locale
和 dateLocale
就为 null
;当 language
为 'zh-Hans'
时,locale
和 dateLocale
就为 zhCN
和 dateZhCN
。而 language
的值由前面现已介绍过了的 getLanguage()
获取,首先是从浏览器缓存读取用户之前的挑选,而用户是通过下面封装的组件进行言语挑选的。
切换言语控件
我挑选结合运用 naive ui 的 Popselect(弹出挑选)和 Icon(图标)组件来实现切换言语的控件:
<!-- srccomponentsLangSelectLangSelect.vue -->
<template>
<div class="lang-select">
<n-popselect
v-model:value="value"
:options="options"
trigger="click"
@update:value="handleUpdateValue"
>
<n-icon>
<Language />
</n-icon>
</n-popselect>
</div>
</template>
value
和 options
界说如下:
<!-- srccomponentsLangSelectLangSelect.vue -->
<script lang="ts" setup>
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import useAppStore from '@/stores/app'
import { LANG_VALUE } from '@/common/enum'
import type { SelectOption, SelectGroupOption } from 'naive-ui'
const ENGLISH = 'English'
const ZHONG_WEN = '中文'
// 获取当时言语
const appStore = useAppStore()
const { language } = storeToRefs(appStore)
// 弹出挑选 Popselect
type valueType = string | null
const value = ref<valueType>(getValue())
function getValue() {
switch (language.value) {
case LANG_VALUE.En:
return ENGLISH
case LANG_VALUE.Zh:
return ZHONG_WEN
default:
return ZHONG_WEN
}
}
const options: Array<SelectOption | SelectGroupOption> = [
{
label: ENGLISH,
value: ENGLISH
},
{
label: ZHONG_WEN,
value: ZHONG_WEN
}
]
</script>
选项 options
就两个:'English'
或 ‘中文'
。value
的默许值根据存储在 pinia 的 appStore
的 state language
决议。这儿第 13 行运用 pinia 供给的 storeToRefs
处理是为了在解构获取 language
时保留其呼应式,其有用 vue3 的 toRefs
也能够。
切换时触发的 handleUpdateValue
界说如下:
<!-- srccomponentsLangSelectLangSelect.vue -->
<script lang="ts" setup>
import { setLocale } from '@/lang'
let lang: langType
function handleUpdateValue(value: valueType) {
switch (value) {
case ENGLISH:
lang = LANG_VALUE.En
break
case ZHONG_WEN:
lang = LANG_VALUE.Zh
break
default:
break
}
setLocale(lang)
}
</script>
将切换后的 value 传给界说于 srclangindex.ts(也就是前面装备 i18n 的文件) 的 setLocale()
处理:
// srclangindex.ts
export function setLocale(lang: langType) {
// 获取当时言语
const appStore = useAppStore()
const { language } = storeToRefs(appStore)
i18n.global.locale.value = lang // 修正 i18n
language.value = lang // 修正 pinia
localCache.setItem(LANGUAGE, lang) // 修正缓存
}
图标的运用
趁便阐明下 naive ui 中图标的运用,图标选自 naive ui 文档引荐的 xicons 图标库,运用前需求根据所选用的图标做对应的装置:
npm i -D @vicons/ionicons5
然后进行引进,并作为 <n-icon>
的默许插槽内容运用:
<!-- srccomponentsLangSelectLangSelect.vue -->
<script lang="ts" setup>
import { Language } from '@vicons/ionicons5'
</script>
<template>
<n-icon>
<Language />
</n-icon>
</template>
处理控制台正告
做到这一步,假如翻开浏览器控制台,可能会看到如下正告:
处理办法是在 vite.config.ts 增加如下装备:
export default defineConfig({
// ...
define: {
__VUE_I18N_FULL_INSTALL__: true,
__VUE_I18N_LEGACY_API__: false,
__INTLIFY_PROD_DEVTOOLS__: false
}
})
由于项目里都是运用 Composition API,无需启用对选项式 api 的支撑,所以 __VUE_I18N_LEGACY_API__
的值由默许的 true
改为了 false
,其他两项则维持默许值。
作用
至此,本项意图国际化装备就完成了。最后来看一下作用(现在只做了部分案牍的初步翻译):
本文正在参与「金石方案 . 分割6万现金大奖」