本篇文章開始,筆者準備開啟一個小系列,稱之為現代 Vue 工程 ,本篇為第一篇 國際化 i18n 開發
我們公司的開源工具產品 Bytebase, 目前只有英文版本。社群裡也有一些小夥伴也提問到了有沒有中文版本的計劃,答案當然是有了。我們團隊正計劃於下次版本釋出日 12 月 23 日釋出國際化支援,順利的話將全面支援中、英版本的切換。
如果做過前端國際化方案的小夥伴應該會有所瞭解,維護大量的文案翻譯是很讓人頭疼的,徒手翻譯更是個體力活。以筆者以往的經驗來講,無論是用文案提取工具一次性提取文案去翻譯的方法,還是人工一條條去提取文案到文案資產。在複雜專案中遇到的一些問題往往不是翻譯個單詞或者語句這麼簡單。
所以筆者總結了一些在 Vue 工程中實現國際化 i18n 的開發方法,主要是針對 Vue 專案而言的,所謂現代Vue工程
即是藉助一些好用的工具,可能是你以往沒有接觸過的,也可能是你正在使用的,它們是一些提升開發效率的方法、工具等。
本期主要介紹的工具是 VSCode 外掛 i18n-ally
國際化 i18n 開發
滿足的條件
- VSCode
- VSCode 外掛 i18n-ally
- Vue 工程整合 vue-i18n
接下來,我會通過 Vite 建立一個 Vue 3 演示工程來和大家實踐以下在 Vue 工程中如何做國際化的
? 工程地址:
https://github.com/xiaoluoboding/vue-i18n-practice
TL;DR
- 初始化 Vue 工程
- 在 vite 中配置 vue-i18n
- 持久化使用者選擇習慣
- 使用 i18n-ally 外掛加速翻譯流程
初始化 Vue 工程
使用 Vite 建立一個 Vue 工程,我選擇的 vue-ts
模版
yarn create vite
✔ Project name: … vue-i18n-practice
✔ Select a framework: › vue
✔ Select a variant: › vue-ts
? 可檢視 commit: https://github.com/xiaoluobod...
在 vite 中配置 vue-i18n
需要安裝三個庫:
- vue-i18n@next
- @types/node
- @intlify/vite-plugin-vue-i18n
PS. 在 Vue 3 專案中我們需要安裝 vue-i18n 的 next 版本
yarn add vue-i18n@next -S && yarn add @types/node @intlify/vite-plugin-vue-i18n -D
配置 vite.config.ts
指定 locales 檔案路徑為 src/locales
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import VueI18n from '@intlify/vite-plugin-vue-i18n'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
// https://github.com/intlify/vite-plugin-vue-i18n
VueI18n({
// define the locales files directory
include: [resolve(__dirname, 'src/locales/**')],
}),
],
})
以 Vue 外掛的形式使用 i18n:
// plugins/i18n.ts
import { App } from 'vue'
import { createI18n } from 'vue-i18n'
const localPathPrefix = '../locales/'
// import i18n resources
// https://vitejs.dev/guide/features.html#glob-import
const messages = Object.fromEntries(
Object.entries(import.meta.globEager('../locales/*.y(a)?ml')).map(
([key, value]) => {
const yaml = key.endsWith('.yaml')
return [key.slice(localPathPrefix.length, yaml ? -5 : -4), value.default]
}
)
)
const install = (app: App) => {
const i18n = createI18n({
legacy: false,
locale: 'en',
globalInjection: true,
messages,
})
app.use(i18n)
}
export default install
增加一個文案
<template>
<h1>{{ $t('common.home') }}</h1>
</template>
// en.yml
common:
home: Home
// zh_cn.yml
common:
home: 主頁
最後的展示效果如下:
? 可檢視 commit:https://github.com/xiaoluobod...
持久化使用者語言選擇習慣
一般使用者會在進入站點選擇完語言版本後,希望再次進入站點還是看到我選擇過的語言版本。所以我們需要儲存使用者的偏好設定。這裡推薦使用 localStorage
來儲存使用者資料,我來介紹一個比較好用的庫結合此場景,做一下使用者行為持久化。
使用 @vueuse/core 庫中的 useLocalStorage
實現一個相應式的配置項
設定初始值,下次進入應用時,優先讀取 localStorage
中的值,代表使用者選擇過的語言版本
import { useLocalStorage } from '@vueuse/core'
const storage = useLocalStorage('site_locale', 'en')
const locale = storage.value
跟隨按鈕切換改變語言版本,設定到 localStorage
const setLang = (lang: string) => {
const storage = useLocalStorage('site_locale', '')
storage.value = lang
}
? 可檢視 commit:https://github.com/xiaoluobod...
使用 i18n-ally 外掛加速翻譯流程
感謝 Anthony Fu 提供的 i18n-ally
外掛,這是一款基於 VSCode
的通用的一站式翻譯外掛,不僅僅用於 Vue 工程中的翻譯場景,可以閱讀下官方文件。
傳統翻譯流程,可能大多數開發者也都遇到過,就是看到文案,複製貼上到相應到 locales 檔案中進行翻譯,而現在我們藉助 i18n-ally 外掛,我們可以進一步的加速翻譯的流程,可能就是點選幾下的事兒,就搞定了文案的翻譯。
安裝 VScode i18n-ally 外掛
VSCode 擴充套件中搜尋 i18n-ally
安裝即可
啟用 i18n-ally
外掛
這裡推薦使用專案中的 .vscode
配置項中配置
// .vscode/settings.json
{
"i18n-ally.localesPaths": [
"src/locales"
],
"i18n-ally.enabledParsers": [
"yaml"
],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh-cn",
"i18n-ally.keystyle": "nested"
}
再次開啟 Vue 元件 HelloWorld.vue
,可以看到文案發生了一些變化:
這是外掛的一個特性 Inline Annotations (行內註釋),將我們之間寫的形$t('common.home')
這樣的程式碼對映為英文的 “Home”,當然我們還可以對映為你喜好的語言,通過改變配置項中的 "i18n-ally.sourceLanguage"
的值來設定。
翻譯過程的術語
- 語言檔案 -
/locale/en.yml
|/locale/zh_CN.yml
名稱空間 - 在 i18n-ally 中稱為路徑,我稱之為“名稱空間“(namespace)
比如語言檔案中的樹形層級關係:
'common.save'
、'field.name'
等t 格式化方法 - t 方法為
vue-i18n
提供的文案格式化翻譯方法,常用格式如下:- Vue 模版插值中 -
{{ $t('common.save') }}
- Vue 模版元件引數中 -
$t('common.save')
- Vue Script 中 -
this.$t('common.save')
/t('common.save')
- Vue 模版插值中 -
提取文案到 YAML 語言檔案
i18n-ally
支援將程式碼檔案內的文案提取到語言檔案中,支援 YAML
、JSON
檔案的讀寫操作。這個功能大大提高了我們翻譯的速度,再也不用手動去複製貼上文案了,整個翻譯流程我們可以不用開啟語言檔案,外掛會幫助把文案提取寫入到相應的名稱空間
下最後一行。
我們所做的大部分工作都轉化為了去命名一個名稱空間
與文案的對應關係,其他的都交給外掛來處理。
大概的一個翻譯流程:
- 選取文案
- 提取文案到語言檔案,輸入
名稱空間
- 替換文案為
t 方法
- 翻譯其他語言版本
? 可檢視 commit:https://github.com/xiaoluobod...
i18n Ally 特性
- 快速提取文案
- 自動預先翻譯(可人工修正)
- 元件內部行內註釋
- 審閱系統(暫未使用)
這些特性可以讓我們快速上手翻譯文案,做到邊開發邊翻譯的狀態。
翻譯技巧
這裡是這在使用 vue-i18n
時遇到的一些常用的翻譯用法,簡單介紹。
文案引用
假設我們已經積累一些單詞表了,那麼有些詞語或者短語是可以通過單詞拼接出來的。vue-i18n 中提供了 Linked messages ,提供了引用其他文案連線語法 @:xxx
,類似於引用變數,這個機制非常適合組合詞語,比如翻譯 App Name
,我們可以定義兩個簡單詞 App
和 Name
,拼成一個短語 App Name
。
common:
app: App
name: Name
header:
title: '@:common.app @:common.name'
為什麼不直接去翻譯 App Name 呢,寫起來也並不難,其實這個還考慮到人工翻譯筆誤、錯別字的問題,多寫多錯是可能存在的,使用 Linked Messages 是可以避免這個問題的,並且 vue-i18n 還提供了內建的類似修飾符一樣的宣告方法,比如:upper
、lower
、capitalize
在翻譯英文文案的時候很有幫助。
?可檢視 commit:https://github.com/xiaoluobod...
傳遞插值
這種方式比較常見,類似傳遞一個變數,我直接拿官網的例子吧:
在模版中對映翻譯的同時傳遞一個 msg
<p>{{ $t('common.hello', { msg: 'hello' }) }}</p>
common:
hello: '{msg} world'
最終展現為 hello world
?可檢視 commit:https://github.com/xiaoluobod...
vue-i18n
還有一些比較特殊的用法比如元件插值、單數複數等特殊的翻譯方法,這裡就不展開了。官方文件講述的比較詳細。
最後再說一句,我們團隊所有人,對是所有人,無論前端後端,都在參與文案的翻譯工作,如果你對 bytebase.com
感興趣,或者對開源專案感興趣,歡迎來參與 PR 哦。
Bytebase.com 是一款聚焦在團隊協作場景下的資料庫結構變更和版本管理(database schema change and version control for teams)的開源工具,主要解決研發工程師和 DBA(資料庫管理員) 在變更資料庫結構時的協同問題。