Vue3 TypeScript 的 Vue-i18n mulitional languages

在Vue3 TypeScript專案內安裝 Vue-i18n

安裝指令

1
npm install vue-i18n@next --save

在 src/ 目錄底下,新增 lang資料夾,並新增zh-TW.json,en-US.json 檔案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//en-US.json
{
"nav_menu":{
"home":"Home",
"login":"Login"
}
}
//zh-TW.json
{
"nav_menu":{
"home":"首頁",
"login":"登入"
}
}

在 src/ 目錄底下,新增 languages/i18n.ts,並設定語系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createI18n } from 'vue-i18n'
import zh from '../lang/zh-TW.json'
import en from '../lang/en-US.json'

type MessageSchema = typeof zh

const i18n = createI18n<[MessageSchema], 'zh-TW' | 'en-US'>({
legacy: false, // 要把 legacy 設為 false,才可以使用 Composition API
locale: 'zh-TW',
fallbackLocale: 'zh-TW',
globalInjection: true,
messages: {
'zh-TW': zh,
'en-US': en
}
})

export default i18n

在 main.ts 引入 Vue-i18n

1
2
3
4
5
6
7
//引入plugins/i18n
import i18n from './plugins/i18n'

const app = createApp(App)
//使用use i18n
app.use(i18n)
app.mount('#app')

在App.vue 載入語系測試使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div>
<div>切換語言:</div>
<select @change="changeLang">
<option value="zh-TW">中文</option>
<option value="en-US">English</option>
</select>
</div>
<p>
{{ $t('nav_menu.home') }}
</p>
</div>
</template>

<script setup lang="ts">
//載入vue-i18n
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
//改變語系切換
const changeLang = (e) => {
locale.value = e.target.value
}
</script>

另一種寫法:pinia

在sores新增nav.ts

  • pinia載入
  • vue 方法 ref, computed 載入
  • vue-i18n載入
  • 數據的Ts撰寫homeMenuType 與載入
1
2
3
4
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { useI18n } from "vue-i18n";
import { homeMenuType } from "../types/all";

在types新增all.ts
轉寫
homeMenuType

1
2
3
4
5
export interface homeMenuType{
name?: string |null |any,
id?: string |null |any,
link: string | null | any,
}
  • 使用computed 解析nav_menu.home
  • 放入陣列homeMenu
  • 寫函式 changeLang改變語系
  • return homeMenu,changeLang
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//useNavbarStore 
export const useNavbarStore = defineStore('navbar', () => {
const { locale } = useI18n();
const i18n = useI18n();

const i18nPlatform = computed(() => i18n.t("nav_menu.home"))
const i18nCompany = computed(() => i18n.t("nav_menu.login"))

const homeMenu=ref<homeMenuType[]>([
{ name: i18nPlatform, id: '001', link: '/index' },
{ name: i18nCompany, id: '002', link: '/aboutus' }
])


const changeLang = (e: any) => {
console.log(e)
locale.value = e.target.value
console.log(locale.value)
}
watch(locale, newlocale => {
localStorage.setItem("locale", newlocale);
});

return {
homeMenu, changeLang
}
})

在頁面使用
  • 載入pinia storeToRefs
  • 宣告store = useNavbarStore()
  • 解構
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<template>
<div>
<div>
切換語言:
<select @change="changeLang">
<option value="zh-TW">
中文
</option>
<option value="en-US">
English
</option>
</select>
</div>
<ul>
<li v-for="(item, id) in homeMenu"
:key="id">
{{ item.name }}
</li>
</ul>
<router-view />
</div>
</template>

<script setup lang="ts">
//載入pinia storeToRefs
import { storeToRefs } from 'pinia';
import { useNavbarStore } from './stores/nav';
//宣告store = useNavbarStore()
const store = useNavbarStore();
//解構
const { homeMenu } = storeToRefs(store);
const { changeLang } = store;
</script>

<style lang="scss" scoped>
ul{
display: flex;
li {
display : flex;
padding:10px;

}
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>