前言
一般在實作網站的本地化(Localization)時,都會將翻譯文案寫在 JSON 檔或 YAML 檔裡,當文案越來越多時,要管理的翻譯鍵(Key)會越來越多,而工程師就必須因為文案修改而頻繁更版。
受到 Lokalise 啟發,實作了 Localiser 線上翻譯管理系統。可以讓 PM 或相關人員透過 Localiser 後台直接線上更新翻譯內容,如此一來就可以解除 PM 必須將文案交付給工程師,並且還要經過層層部署才能更新網頁內容的依賴關係。
此系統主要有以下功能:
- 認證
- 管理員權限、專案權限
- 線上修改
- 提供前端使用的 API
- 快取
專案架構
分為 3 個部分:
- localiser:後端
- localiser-ui:前端
- localiser-cli:命令列工具
後端
資料模型
主要模型有:
- User:使用者
- Project:專案
- Language:語言
- Key:翻譯鍵
- Value:翻譯值
API
後端主要會有 4 個公開的 API 可以使用。
獲取語言代碼:GET
/api/project/:id/locales
刪除語言代碼快取:DELETE
/api/project/:id/locales
獲取翻譯文案:GET
/api/project/:id/messages
刪除翻譯文案快取:DELETE
/api/project/:id/messages
角色
後端有兩種不同作用域的角色,一種是系統層級的角色,一種是專案層級的角色。
系統層級
Ability |
Admin |
User |
USER_VIEW |
✔️ |
✔️ |
USER_CREATE |
✔️ |
|
USER_UPDATE |
✔️ |
|
USER_DELETE |
✔️ |
|
PROJECT_VIEW |
✔️ |
✔️ |
PROJECT_CREATE |
✔️ |
✔️ |
專案層級
Ability |
Owner |
Maintainer |
Reporter |
Guest |
PROJECT_UPDATE |
✔️ |
✔️ |
|
|
PROJECT_DELETE |
✔️ |
|
|
|
LANGUAGE_CREATE |
✔️ |
|
|
|
LANGUAGE_UPDATE |
✔️ |
✔️ |
|
|
LANGUAGE_DELETE |
✔️ |
|
|
|
KEY_CREATE |
✔️ |
✔️ |
✔️ |
|
KEY_UPDATE |
✔️ |
✔️ |
✔️ |
|
KEY_DELETE |
✔️ |
✔️ |
✔️ |
|
VALUE_CREATE |
✔️ |
✔️ |
✔️ |
|
VALUE_UPDATE |
✔️ |
✔️ |
✔️ |
|
VALUE_DELETE |
✔️ |
✔️ |
✔️ |
|
前端
實作
在 src/plugins/i18n.js
檔:
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
| import { nextTick } from 'vue'; import { createI18n } from 'vue-i18n/index'; import * as actions from '@/actions';
const LOCALES = Object.freeze({ en: 'en', zh: 'zh_TW', zh_TW: 'zh_TW', 'zh-TW': 'zh_TW', });
const language = localStorage.getItem('locale') || window.navigator.language;
export const DEFAULT_LOCALE = language in LOCALES ? LOCALES[language] : LOCALES.en;
const i18n = createI18n({ legacy: false, locale: DEFAULT_LOCALE, });
export const setLanguage = (locale) => { i18n.global.locale.value = locale; document.documentElement.lang = locale; localStorage.setItem('locale', locale); };
export const loadMessage = async (locale) => { try { const message = await actions.project.fetchMessages({ projectId: process.env.VUE_APP_API_PROJECT_ID, locale, }); i18n.global.setLocaleMessage(locale, message); } catch { const message = await import( `@/assets/lang/${locale}.json`); i18n.global.setLocaleMessage(locale, message); } return nextTick(); };
export default i18n;
|
在 main.js
檔:
1 2 3 4 5 6 7
| import { createApp } from 'vue'; import App from './App.vue'; import i18n from './plugins/i18n';
createApp(App) .use(i18n) .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
| import i18n, { DEFAULT_LOCALE, loadMessage, setLanguage, } from '@/plugins/i18n';
export default { name: 'App', setup() { (async () => { await loadMessage(DEFAULT_LOCALE); setLanguage(DEFAULT_LOCALE); })(); const changeLanguage = async (locale) => { if (!i18n.global.availableLocales.includes(locale)) { await loadMessage(locale); } setLanguage(locale); }; return { changeLanguage, }; }, };
|
命令列工具
命令列工具主要是用來將翻譯文案拉取至本地專案以進行版本控制。使用時,要先將執行檔下載下來,並設置到環境變數。
在要使用 Localiser 的專案新增 localiser.yaml
檔:
1 2 3 4
| --- endpoint: http://localhost:8000/api project_id: 1 output_directory: src/assets/lang
|
執行以下指令,即可將翻譯文案下載下來。
程式碼