在 Vue-cli 中使用 i18n 實作多國語系

Eason Lin
Eason’s murmuring
7 min readApr 4, 2020

這篇文主要記錄在 Vue-cli 中使用 i18n 的方式,Vue i18n 官方文件中有提供 Vue-cli 3 專用的 vue add i18n ,這篇文則會使用 vue-cli 3 但基於 npm 安裝的方式。

建立好 Vue-cli 專案後,於根目錄下開啟終端機,安裝 vue-i18n

npm install vue-i18n

在根目錄下,建立 common 資料夾,接著建立 config, plugins 資料夾。config 資料夾中建立 i18n 資料夾,這個資料夾會是我們多國語系每一個檔案的存放處;plugins 則會放入 vue-i18n 的設定檔:

這篇文我們以中文(台灣)及英文為例子。在 i18n 資料夾中建立 tw.jsen.js 兩個檔案,於 en.js 加入以下程式碼:

// en.js
export const locale = {
GENERAL: {
NAV_OPTIONS: ['Home', 'About', 'Contact'],
WELCOME_WORD: 'Welcome to your Vue.js application',
OK: 'ok',
CONTINUE: 'continue',
CANCEL: 'cancel',
GUEST: 'guest',
},
}

tw.js

// tw.js
export const locale = {
GENERAL: {
NAV_OPTIONS: ['首頁', '關於', '聯絡我們'],
WELCOME_WORD: '歡迎來到 Vue.js 應用程式',
OK: '好',
CONTINUE: '繼續',
CANCEL: '取消',
GUEST: '訪客',
},
}

在 plugins 建立 vue-i18n.js,加入以下程式碼:

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import { locale as en } from '@/common/config/i18n/en'
import { locale as tw } from '@/common/config/i18n/tw'
Vue.use(VueI18n)let messages = {}
messages = { ...messages, en, tw }
const lang = localStorage.getItem('language') || 'tw'const i18n = new VueI18n({
locale: lang,
messages,
})
export default i18n

將我們的語言 importvue-i18n.js 中,接著將其放入 messages 物件中,語言部份則透過 localStorage 取得,並將預設值設定為 twvue-i18n 會幫我們把我們在 common/config/i18n 中的資料引入。

main.js ,將我們設定好的 i18n 引入,並加入至 Vue instance 中:

import Vue from 'vue'
import App from './App.vue'
import i18n from './common/plugins/vue-i18n'
Vue.config.productionTip = falsenew Vue({
i18n,
render: (h) => h(App),
}).$mount('#app')

接著我們就能在任何一個組件中,使用 $t(‘鍵’) 的方式直接取得我們在 tw.jsen.js 中輸入的值。例如:

// HelloWorld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h1>{{ $t('GENERAL.OK') }}</h1>
</div>
</template>

npm run serve,到前台應該可以看到

接著把 locale 中所有的值引入:

// HelloWorld.vue
<template>
<div class="hello">
<ul>
<li
v-for="(menuItem, index) in $t('GENERAL.NAV_OPTIONS')"
:key="index + 1"
>
{{ menuItem }}
</li>
</ul>
<h1>{{ msg }}</h1>
<h1>{{ $t('GENERAL.OK') }}</h1>
<h1>{{ $t('GENERAL.CONTINUE') }}</h1>
<h1>{{ $t('GENERAL.CANCEL') }}</h1>
<h1>{{ $t('GENERAL.GUEST') }}</h1>
</div>
</template>

其中可以注意到 i18n 可接受的不僅有字串,亦可以傳入陣列或其他資料型態,如 GENERAL.NAV_OPTIONS 的值為 [‘首頁’, ‘關於’, ‘聯絡我們’],並在模板中使用 v-for 引入。

亦可以用資料綁定的方式傳入子組件:

// App.vue
<template>
<div id="app">
<HelloWorld :msg="$t('GENERAL.WELCOME_WORD')" />
</div>
</template>

最後加入切換語言的按鈕。加入兩個 button

// HelloWorld.vue
<template>
<div class="hello">
<ul>
<li
v-for="(menuItem, index) in $t('GENERAL.NAV_OPTIONS')"
:key="index + 1"
>
{{ menuItem }}
</li>
</ul>
<h1>{{ msg }}</h1>
<h1>{{ $t('GENERAL.OK') }}</h1>
<h1>{{ $t('GENERAL.CONTINUE') }}</h1>
<h1>{{ $t('GENERAL.CANCEL') }}</h1>
<h1>{{ $t('GENERAL.GUEST') }}</h1>
<div>
<button data-lang="tw" @click="setLang">中文</button>
<button data-lang="en" @click="setLang">English</button>
</div>
</div>
</template>

加入兩個 methodssetActiveLanguage 會將 localStorage 中的 lang 設定為傳入的參數;setLang 則會將 buttondataset.lang 值傳入 setActiveLanguage,並在最後重整網頁。

methods: {
setActiveLanguage(lang) {
localStorage.setItem('language', lang)
},
setLang(evt) {
const lang = evt.target.dataset.lang
this.setActiveLanguage(lang)
return history.go(0)
},
}

實測:

程式碼可參考:https://github.com/EasonLin0716/vue-cli-i18n-example

vue-i18n 的初步使用介紹就到這邊,實際上使用我覺得最麻煩的應該是翻譯及把現有專案模板或其他地方的值一個個替換,據使用過的同事所述是「非常花時間的事情」。

如果這篇文有任何錯誤,再麻煩觀看的人指出,我會盡快修正,希望能幫助到大家,謝謝。

--

--