從前端國際化開始:用 i18n 打造多語言應用的實戰指南

如果你正在用 Vue 3 + Vite 打造後台系統,某天產品要賣到海外、或是要同時支援簡體、繁體、英文,你會發現「把文字寫死在模板裡」是第一個災難——等到要改語言時,得在幾百個元件裡逐行替換。這篇文章就用實戰步驟,帶你把多語言架構一次打好。

一、什麼是 i18n,為什麼需要它

i18n 是 internationalization 的縮寫(i 與 n 中間有 18 個字母)。它本質上是一套「把顯示文字從程式碼抽離」的機制:所有會出現在畫面上的文案,都集中放在語言包(message bundle)裡,程式只負責「按 key 取值」,再由框架根據當前語言渲染對應文字。

  • 對開發者:文案與邏輯解耦,改語言不必動程式。
  • 對翻譯團隊:只需維護幾份 JSON,不必讀原始碼。
  • 對產品:上線後能動態切換,甚至按使用者偏好記住語言。

二、用 Vue I18n 搭建多語言骨架

重點:Vue 3 請安裝 vue-i18n@9,它原生支援 Composition API。下面三步把骨架立起來。

步驟 1:安裝依賴

npm i vue-i18n@9

步驟 2:建立 i18n 實例與語言包

// i18n/index.js
import { createI18n } from 'vue-i18n'

const messages = {
  'zh-TW': { greeting: '歡迎回來', save: '儲存' },
  'en':    { greeting: 'Welcome back', save: 'Save' },
  'zh-CN': { greeting: '欢迎回来', save: '保存' },
}

export const i18n = createI18n({
  legacy: false,
  locale: 'zh-TW',
  fallbackLocale: 'en',
  messages,
})

步驟 3:在 main.js 掛載

import { createApp } from 'vue'
import { i18n } from './i18n'
createApp(App).use(i18n).mount('#app')

三、在元件中使用多語言

Composition API 下用 t() 取文字,模板與 script 都一樣直覺:

<template>
  <h1>{{ t('greeting') }}</h1>
  <button>{{ t('save') }}</button>
</template>

<script setup>
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
</script>

重點:遇到帶變數的句子(如「您有 3 筆待辦」),用具名插值 t('todo', { n: 3 }),避免把數字硬拼進字串,這在英文單複數處理上尤其重要。

四、動態切換語言

切換只需改 locale,畫面會自動重渲染:

import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
function changeLang(l) {
  locale.value = l
  localStorage.setItem('lang', l)  // 記住使用者偏好
}

五、用 Vite 自動載入翻譯檔

當語言包變多,手動 import 很痛苦。重點:用 Vite 的 import.meta.glob 一次匯入整個資料夾,新增語言檔不必改任何程式:

const modules = import.meta.glob('./locales/*.json', { eager: true })
const messages = {}
for (const path in modules) {
  const lang = path.split('/').pop().replace('.json', '')
  messages[lang] = modules[path].default
}

這正是大型後台(如 Vben Admin 系列)處理多語言的慣用手法,翻譯檔隨建隨用。

六、常見陷阱與最佳實踐

  • key 要有意義且分層(user.list.title),別用 text1、text2。
  • 永遠設 fallbackLocale,缺譯時降級而非空白。
  • 日期、數字、金額請用 Intl API 或 i18n 的 datetimeNumberFormats,別自己格式化。
  • 語言包體積大時,考慮按需載入(動態 import)而不是全部打包。

互動話題:你的專案目前支援幾種語言?在處理多語言時,踩過最痛的坑是什麼?歡迎在留言區分享,我們一起把國際化做得更順手!