iT邦幫忙

2023 iThome 鐵人賽

DAY 23
0
自我挑戰組

Vue 元素美麗的轉變:前端小萌新勇闖套件的魔法陣系列 第 23

吃翻譯年糕 - 多國語系 vue-i18n-next (下)

  • 分享至 

  • xImage
  •  

話不多說,直接進入主題.../images/emoticon/emoticon01.gif

#應用

前一篇有提到,在多國語系 vue-i18n-next 應用篇主要分享幾個主題:

  1. 運用 Pinia 記憶使用者選擇語系 - localStorage
  2. 線上網站統一管理語言包 - Loco
  3. Google 試算表管理語言包

評估內容很像會太多,但是對於前端管理語言包真的很實用,只是自己實作上比較常使用是第一項和第三項,第二項的後半部因為對 Node.js 不熟悉,相關原理也就是為什麼語法可以這樣下,可能還需要再研究...,所以附上相關參考資料,未來把 Node.js 觀念補足後再回來這裡寫補充。

- 運用 Pinia 記憶使用者選擇語系 - localStorage

同樣身為使用者會希望自己造訪某個網頁已經選擇語系,之後再次回訪能夠不用再重新選擇,此時可以使用 localStorage (網頁資料庫)。

https://ithelp.ithome.com.tw/upload/images/20230923/20158099EHsGmQeAgq.png

(資料來源:Window.localStorage)

https://ithelp.ithome.com.tw/upload/images/20230923/20158099JfYzkELVPX.png

(本機查詢方法:可以開啟 chrome 開發者工具的 Application 看到有 3 個瀏覽器網頁資料庫。)

以上是基本的介紹,簡單來說:就是一個存取資料的一個地方,假設今天在 A 網頁用 setItem 存入資料,可以在其他網頁用 getItem ,直到碰到程式碼有 removeItem 或是 clear ,才會消失不見,更多詳細內容可以用關鍵字 localStorage 查詢。

接下來就要試著用 localStorage 的特性記憶使用者的語言選擇,這裡使用下拉式選單當作語言切換觸發點:

  1. store 中做語言包的狀態管理:

    • 這裡定義下拉式選單的選項,以及當前的語言
    • 把當前語言宣告在 Pinia 主要是因為 i18n 主要是針對本地且不會動態變化的項目像 <header>…</header><footer>…</footer> 內容較為固定的設定,如果要把內容也轉換,通常會透過傳參數的方法或是讓 url 夾帶給 api 請後端幫忙回傳,此時如果有一個共用的地方就不需要一直用 getItem 取得 localStorage 資料。
    // src/store/index.js
    
    import { defineStore } from "pinia";
    import { reactive } from "vue";
    
    export const useLangStore = defineStore('language', () => {
        const stateInit = reactive({
            langsOption: [
                {
                    id: 0,
                    key: "zh-TW",
                    title: "繁體中文",
                },
                {
                    id: 1,
                    key: "en-US",
                    title: "English(United States)",
                },
                {
                    id: 2,
                    key: "ja-JP",
                    title: "日本語",
                },
            ],
            currentLang: null
        })
    
        return { stateInit }
    })
    
  2. 定義語言包內容:

    // src/i18n/common.json
    
    {
        "zh-TW": {
          "welcome": "你好世界"
        },
        "ja-JP": {
          "welcome": "こんにちは世界"
        },
        "en-US": {
          "welcome": "Hello World"
        }
    }
    
  3. 建立 vue-i18n-next:在默認語言中先取得 localStorage 的紀錄
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099BvwaYDq0Q1.png

    取得 localStorage 紀錄流程:F12 → ApplicationlocalStorage
    // src/i18n/i18n.js
    
    import { createI18n } from "vue-i18n";
    import message from "./common.json";
    
    const i18n = new createI18n({
      legacy: false,                                        // 啟用新的 Vue3 選項
      locale: localStorage.getItem('lang') ?? "zh-TW",      // 設置默認語言
      messages: message,
      fallbackLocale: "zh-TW",
    });
    
    export { i18n };
    
  4. main.js 引入 vue-i18n-next

    import { i18n } from "@/i18n/i18n";
    
    import { createApp } from 'vue';
    import { createPinia } from 'pinia';
    
    import App from './App.vue';
    import router from './router';
    
    const app = createApp(App);
    const pinia = createPinia();
    
    app.use(i18n);
    app.use(pinia);
    app.use(router);
    
    app.mount('#app');
    
  5. .vue 元件中引入:

    • 監聽套件的 locale 如果有變化用 setItem 記錄使用者的選擇,並且同步到 Pinia
    import { watch } from 'vue';
    import { useI18n } from 'vue-i18n';
    import { useLangStore } from '@/stores/index.js';
    
    const { locale } = useI18n();
    const langStore = useLangStore();
    langStore.stateInit.currentLang = locale.value;
    watch(locale, (newLocale) => {
      langStore.stateInit.currentLang = newLocale;
      localStorage.setItem('lang', newLocale);
    })
    
    • 用解構把 locale 取出並做雙向綁定,讓使用者切換語系的時候,也對套件直接切換語系,不會重整頁面。
    <div class="my-5">
     <select class="form-select w-25" v-model="locale">
       <option
         v-for="(lang, i) in langStore.stateInit.langsOption"
         :key="`Lang${i}${lang.id}`"
         :value="lang.key"
       >
         {{ lang.title }}
       </option>
     </select>
     <p class="text-primary">{{ $t('welcome') }}</p>
    </div>
    
  6. 畫面展示:https://ithelp.ithome.com.tw/upload/images/20230923/20158099yJLQ6lXBvn.png

- 線上網站統一管理語言包 - Loco

前面有提到, i18n 很好用但是如果只能在本地新增編輯語言包真的不太方便,而且量很大,如果是自己的專案可以在現有的 api 新增 key 分離不同語系的翻譯包,但是協同開發呢?

如果有工具可以統一管理其實是前端一大福音,研究 i18n 過程發現 RexHung's Blog 分享的 Loco 開發人員翻譯管理。

官網文件:Translation Management for Developers
https://localise.biz/

以下是對於這個網站的註冊使用流程,建立完成後的一鍵更新語言包,個人建議詳細資料可以參考這篇「[Vue Note] — 在 Vue3 優雅的引入 I18n 之餘,透過網站統一管理並一鍵更新」的後半段

  1. 官網簡介:
    這是要錢的…但是註冊後免費的額度每一個字串一種語言為一個項目,免費額度基本上的項目為 2000,所以基本上還是可以使用的。
    https://ithelp.ithome.com.tw/upload/images/20230923/201580991li2lHIRtH.png
  2. 建立專案
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099xPcdy1aBVX.png
  3. 建立第一個翻譯:
    轉換頁面之後,點擊綠色的按鈕新增第一個翻譯,然後在 Asset ID 輸入要設定的語系 Key,這邊先測試輸入 welcome。
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099uI99L0ECnC.png
  4. 新增語系:
    查看右邊的地方有一個地球的 Icon,點擊後下面會出現 New locale,再度點擊後會彈出一個視窗,這時候就可以輸入你想新增的語系了,但記得,語系越多,佔用的 Translation 就會越多!
    https://ithelp.ithome.com.tw/upload/images/20230923/201580992IrVXhrTpX.png
  5. 開始翻譯:
    最後在大框框那邊輸入你想翻譯的文字,然後再透過下拉去切換語言,把你設定的語言都新增好,右邊地球那邊會顯示你的百分比,如果某些語言沒有翻譯,就不會 100%。
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099XSEfpRxm6d.png
  6. 拿取 API Key
    與大多的網站差不多,通常要打那個網站的 API,都會需要帶 Key 也就是金鑰,一樣看到剛剛右邊的地球,點擊地球右邊的板手 Icon,下方有一個 API Keys,點擊後又會彈出一個視窗,記下 API Keys,記得請使用上方的,下方的會包含可以修改的權限,這邊不需要用到
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099HyGnNqtN6r.png
  7. 查閱 Document:
    接著到網站的 API 文件 可以看見許多 API 的介紹,進去後找 GET /api/export/all.{ext} 這支 API。
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099XCmIW8U8dz.png
    https://ithelp.ithome.com.tw/upload/images/20230923/201580990TFuSeInZp.png
    打開文件內容,透過 API 取得語言包的 JSON 然後載入套件中。
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099DekkNrIRMN.png
    https://ithelp.ithome.com.tw/upload/images/20230923/20158099xebhbt7KAu.png
  8. 運用 Node.js 建立在 Loco 中建立的語言檔
    自動化更新語言包通常可以使用腳本來實現,這個腳本可以定期從 Loco 下載最新的語言包替換專案中的本地化文件。
    npm install axios fs
    
    創建一個名為 updateLocales.js 的腳本文件
    const axios = require('axios');
    const fs = require('fs');
    
    // Loco API 設置
    const LOCO_API_KEY = 'pEeDnRydTNs_vVLSIh_KyK3?????????'; // 替換為 Loco API 密鑰
    const LOCO_PROJECT_ID = 'test'; // 替換為 Loco 專案 ID
    const LOCO_EXPORT_FORMAT = 'json'; // 語言包導出格式 JSON 
    
    // 目標本地化文件目錄
    const LOCALES_DIR = './src/locales'; // 替換為本地化文件存放目錄
    
    // 語言列表
    const LANGUAGES = ['zh-TW', 'ja-JP', 'en-US']; // 替換為語言列表
    
    // Loco API 請求頭
    const axiosInstance = axios.create({
      baseURL: `https://localise.biz/api/export/locale/${LOCO_EXPORT_FORMAT}`,
      headers: {
        Authorization: `Loco ${LOCO_API_KEY}`,
      },
    });
    
    // 下載並更新語言包
    async function updateLocales() {
      try {
        for (const lang of LANGUAGES) {
          const response = await axiosInstance.get(`/${LOCO_PROJECT_ID}/${lang}`);
          const localeData = response.data;
    
          // 將語言包保存到本地文件
          const filePath = `${LOCALES_DIR}/${lang}.json`;
          fs.writeFileSync(filePath, JSON.stringify(localeData, null, 2), 'utf8');
          console.log(`Updated ${lang}.json`);
        }
    
        console.log('Localization files updated successfully.');
      } catch (error) {
        console.error('Error updating localization files:', error);
      }
    }
    
    // 執行更新語言包操作
    updateLocales();
    
    
  9. 上一步驟是在根目錄下創建一個新的腳本文件 updateLocales.js,再需要時運行腳本就會更新。
    node updateLocales.js
    
    

- Google 試算表管理語言包

因為研究上一個方法其實耗了不少時間,在研究成功之前,其實主要用 2 種方法轉換:

  1. 在現有的 JSON-server 建立客製化資料庫 (如果有現成的 API 可以打,也可以用 POST /posts 的方法丟翻譯物件到資料庫
  2. Mike - [重構倒數第20天] - i18n什麼的交給前端來處理吧(一) 把GoogleSheet文件轉成JSON文件

Mike 的流程寫得很清楚,還有附上 google API 金鑰申請流程,需要的夥伴可以多加參考!
今天要另外分享的是六角學院 2023-09-07 舉辦線上分享會「利用前端解決多國語系專案維護的種種難題 - 教你如何提升跨國團隊的協作效率 by Unabiz Neil , Zoie」內容提到:翻譯師可能去修改語言表達內容,告知開發需要一個一個比對並且複製貼上去修改,這實在太辛苦,如果有工具可以大家一起維護還有防呆機制或許是很好的選擇,講師主要分享 google 試算表的方法,詳細可以上 github 看一下,目前還沒有 npm 安裝,有許願希望能實現,這樣也可以少很多工。

利用前端解決多國語系專案維護的種種難題,教你如何提升跨國團隊的協作效率
https://github.com/neil585456525/i18n-google-sheet-example
https://ithelp.ithome.com.tw/upload/images/20230923/20158099u0AvN7J2Nl.png


個人目前使用第一種和第三種的方法混打,或許 Neil 大大有 npm 安裝後,就可以再更方便使用語系轉換,期待願望成真/images/emoticon/emoticon31.gif


上一篇
吃翻譯年糕 - 多國語系 vue-i18n-next (上)
下一篇
我有話要說 - CKEditor5
系列文
Vue 元素美麗的轉變:前端小萌新勇闖套件的魔法陣30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言