[指南] 整合 Vue-i18N 國際化 和 TypeScript 到現有的 Vue 2.X 專案

Vue-i18N 算是採用 Vue 為前端框架者,常會使用的多國語言翻譯套件。不過為了支援 TypeScript 和便於日後維護,筆記下檔案的配置和資料流向。
vue typescript


關鍵點

1. Vuex:紀錄使用者的語系 ( 如:en_us ),並運用 vuex 中的 action 方法來重複呼叫對應的 mutation
2. .vue 元件檔:取用 vuex 中預先寫好的 getter 方法,並將其綁定到 v-model 上。當修改時,將 vuex 中的 action 方法當作 set 的方式,寫回到 vuex 中並同時修改 $i18n 的值。
3. .vue 元件檔中,在 template 中有綁定 $t 的,可以直接使用。其餘的部分,要藉由監聽 vuex 中紀錄使用者語系的變數,顯示對應的變化。初始的預設值,請寫在該元件檔的 data 內。
4. Tsconfig 檔,要新增 “compilerOptions.resolveJsonModule”: true
5. 在根目錄下建立一個 i18n 的資料夾,裏頭放置語系的 json 檔。可以支援多層的 key-value
6. i18n/config 中,會新增兩隻檔案:index.ts / locales.ts 。每當要新增語系時,要修改 locales.ts 中的 enum Locales{} 、LayoutLanguages 和 index.ts 三處即可

示範程式碼

<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p v-html="headline"></p>
<h3>{{ $t("intro.titles.links") }}</h3>
<ul>
<li v-for="(link, index) in essentialLinks" :key="index">
<a :href="link.url" target="_blank" rel="noopener">{{ link.caption }}</a>
</li>
</ul>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import {
TranslateResult
} from 'vue-i18n'
import {
mapGetters
} from 'vuex'
import {
Link
} from '../declarations/HelloWorld'
export default Vue.extend({
name: 'HelloWorld',
data () {
return {
headline: this.$t('intro.headline') as TranslateResult,
essentialLinks: (this.$t('intro.essentialLinks') as unknown) as Link[]
}
},
props: {
msg: String
},
computed: {
...mapGetters(['selectedLanguage'])
},
watch: {
selectedLanguage: function () {
this.headline = this.$t('intro.headline')
this.essentialLinks = (this.$t('intro.essentialLinks') as unknown) as Link[]
}
}
})
</script>
// i18n/config/index.ts
import {
Locales
} from './locales'
import enUs from '../en_us.json'
import zhTw from '../zh_tw.json'
import zhCn from '../zh_cn.json'
export const messages = {
[Locales.enUs]: enUs,
[Locales.zhTw]: zhTw,
[Locales.zhCn]: zhCn
// 若要新增語系,在這邊定義
}
// 修改預設語系
export const defaultLocale = Locales.enUs
// i18n/config/locales.ts
interface I18nLanguage {
param: string;
title: string;
}
export enum Locales {
enUs = 'en_us',
zhTw = 'zh_tw',
zhCn = 'zh_cn',
// 若要新增語系,在這邊定義
}
export const LayoutLanguages: Array<I18nLanguage> = [
{
param: Locales.enUs,
title: 'English'
},
{
param: Locales.zhTw,
title: '繁體中文'
},
{
param: Locales.zhCn,
title: '简体中文'
}
// 若要新增語系,在這邊定義選單選項
]
// store/index.ts
import Vue from 'vue'
import Vuex from 'vuex'
// vue-i18n
import {
Locales
} from '@/i18n/config/locales'
import {
defaultLocale
} from '@/i18n/config'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
selectedLanguage: defaultLocale
},
getters: {
selectedLanguage: state => state.selectedLanguage
},
mutations: {
setLanguage (state, payload: Locales) {
state.selectedLanguage = payload
}
},
actions: {
selectNewDefaultLanguage ({ getters, commit }, lang: Locales) {
const { selectedLanguage }: { selectedLanguage: Locales } = getters
if (lang !== selectedLanguage) {
commit('setLanguage', lang)
}
}
}
})

Github 位置:https://github.com/andy922200/vue-vuetify-typescript-eslint-babel-stylelint-integration


資料來源

1. Manage Vue i18n with Typescript
2. 在 Vue-cli 中使用 i18n 實作多國語系

按讚加入粉絲團

延伸閱讀