快速連結

2023年6月13日

[Vue3][筆記]vue-i18n 讀取public資料夾內json file

最近做一個委託,對方需要網站有多國語系,並且他能夠自己去更新語言包內的文字而不需要透過我們再編譯。
vue-i18n可以滿足我們製作多國語系的功能,可惜網路上很少有在討論vue3+i18n+public資料讀取的資訊。
基於vue專案的設計,public資料夾是不能直接上方宣告import js、json檔案來利用的,必須透過await import/await fetch來讀取進來。(如果有搞錯請留言跟我說QQ)
這就導致了通用的vue-i18n範例是不能使用的。 以下是我搜尋後找到的方法,從vue2改寫而來! 參考的文章:VueJS 2.0 教學筆記: i18n 多語套件進階篇

安裝

首先需要安裝套件,套件名稱為vue-i18n-next,詳細官方文件請見Vue I18n 安裝說明
由於我們也要跟參考文章一樣加入cookie的功能,因此也需要安裝js-cookie,套件文件請見js-cookie

資料設定

JSON FILE: /public/lang/cht.json

{
  "header":"測試多語系網站",
  "menu":{
    "info":"資訊",
    "about":"關於我們",
    "contact":"聯繫我們"
  }
  "info_content":"內容"
}


設定檔案:/public/config.json

[
  {
    "LOCALE": "cht"
  }
]

程式碼

cookie:src/utils/cookie.js

import Cookies from 'js-cookie'

// 儲存在cookies時,應以何種名稱為key
const languageKey = 'language'
// 取得cookies設定中的語言設定項目
export const getLanguage = () => Cookies.get(languageKey)
// 語言設定變更時,寫入cookies
export const setLanguage = (language) => Cookies.set(languageKey, language)


i18n初始化/讀取/替換程式碼:src/lang.js

import {createI18n} from 'vue-i18n'
import * as cookie from '@/utils/cookies'

// 由window取設定,稍後我們會在main.js設置一些相關設定
const config = window['config']

export const langType = {
    cht : "cht",
    en : "en"
}

export const i18n = createI18n({
    lazy:true,
    locale: langType.en,
    messages: {}
})
// 預設語言
cookie.setLanguage(langType.en)

const loadedLanguages = []
// 取得現在的語言設定
export const getLocale = () => {
    const cookieLanguage = cookie.getLanguage()
    // from cookie
    if (cookieLanguage) {
    return cookieLanguage
}

// from default config
if (config.LOCALE) {
    return config.LOCALE
}
    return langType.en
}

const locale = getLocale()

// 設置語言的事件
const setI18nLanguage = (lang) => {
    i18n.locale = lang
    i18n.global.locale = lang
    cookie.setLanguage(lang)
    return lang
}

export const loadLanguageAsync = async (lang) => {
    // 如果配置到同樣的語言value時
    if (i18n.locale === lang) {
        return setI18nLanguage(lang)
    }

    // 如果已經載入該語言時
    if (loadedLanguages.includes(lang)) {
        return setI18nLanguage(lang)
    }

    // 如果沒有載入語言時
    const messages = await getMessages(lang)
    i18n.global.setLocaleMessage(lang, messages)
    loadedLanguages.push(lang)
    return setI18nLanguage(lang)
}

// Fetch對應的json語言包
const getMessages = async (locale) => {
    let langFile = await (await fetch(`/data/${locale}.json`)).json()
    return { ...langFile}
}

loadLanguageAsync(locale)
 
export default i18n


src/main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import lang from '@/lang'

import App from './App.vue'

const app = createApp(App)
app.use(lang)
app.use(createPinia())
app.mount('#app')

if (process.env.NODE_ENV === 'development') {
    // i18n 確認是否有存在既有語言KEY
    window['k'] = (v) => {
      const m = i18n.messages['cht']
      const m2 = i18n.messages['en']
      for (let i in m) {
        if (m[i] == v) return i
        if (m2[i] == v) return i
      }
    }
  
    window['t'] = (v) => {
      return i18n.t(v)
    }
}

使用範例





沒有留言:

張貼留言

歡迎大家留言提問,我會答的都會盡力回答!
如果太久沒出現回應就是我又忘記回來看留言了TAT