随着互联网产品全球化趋势加速,国际化(i18n)已经从「锦上添花」变成了前端项目的「基本能力」。
一个优秀的前端 i18n 方案需要满足以下要求:
- 项目框架(React / Vue)要有完善的语言切换能力
- 组件库内部需要支持国际化并可与应用层联动
- user-facing 文案需要支持语序、占位符、多语言扩展
- Web Component 要能被任意框架或原生应用使用,且保持语言一致
本文将从框架层(React / Vue)与组件库层(Web Component)两个维度,给出完整可落地的 i18n 实践方案。
一、前端国际化核心概念
国际化 i18n 的核心是:
界面语言不写死 → 文案全部抽离到语言包 → 通过 key 获取
形式上就是:
t('button.ok')
国际化的难点主要在于:
- 语言语序不同(如英文是 “Hello {{name}}”,中文是“你好,{{name}}”)
- 文案需要动态变化
- 组件库和应用层如何共享语言环境
- Web Component 不属于任意框架,需要独立上下文
以下将进入框架层实践。
二、React 应用的国际化方案
React 生态主流方案是 react-intl 和 react-i18next,本文以更常用的 react-i18next 为例。
1. 安装
npm install react-i18next i18next
2. 定义语言包
// locales/en.ts
export default {
login: {
title: 'Login',
welcome: 'Welcome, {{name}}!'
}
}
// locales/zh.ts
export default {
login: {
title: '登录',
welcome: '欢迎你,{{name}}!'
}
}
3. 初始化 i18n
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import en from './locales/en'
import zh from './locales/zh'
i18n.use(initReactI18next).init({
resources: { en: { translation: en }, zh: { translation: zh } },
lng: 'zh',
fallbackLng: 'en'
})
export default i18n
4. 在 React 组件中使用
import { useTranslation } from 'react-i18next'
export function LoginPage() {
const { t } = useTranslation()
return <h1>{t('login.welcome', { name: 'Jack' })}</h1>
}
5. 切换语言
i18n.changeLanguage('en')
三、Vue 应用的国际化方案
Vue 推荐使用 vue-i18n(Vue2/Vue3 通用方案)。
1. 安装
npm install vue-i18n
2. 定义语言包
// locales/zh.ts
export default {
menu: {
home: '首页',
about: '关于'
}
}
// locales/en.ts
export default {
menu: {
home: 'Home',
about: 'About'
}
}
3. 初始化(以 Vue2 + @vue/composition-api 为例)
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import zh from './locales/zh'
import en from './locales/en'
Vue.use(VueI18n)
export const i18n = new VueI18n({
locale: 'zh',
messages: { zh, en }
})
4. 使用
<template>
<div>{{ $t('menu.home') }}</div>
</template>
5. 切换语言
i18n.locale = 'en'
四、Web Component 组件库的 i18n 实现方案
—— 支持组件库内部默认语言 + 外部注入扩展语言包
Web Component 不依赖框架,因此必须自己实现一套语言管理系统。
目标是:
- 组件库内部有默认语言(如 zh/en)
- 外部项目可注入新语言(如 fr、jp)
- 外部可覆盖组件库默认语言
- 切换语言后所有组件自动刷新
- React / Vue / 原生项目都能通用
以下方案适用于 Lit / Web Component。
1. 定义语言包
// locales/en.ts
export const en = {
button: {
ok: 'OK',
cancel: 'Cancel'
}
}
// locales/zh.ts
export const zh = {
button: {
ok: '确定',
cancel: '取消'
}
}
2. 构建 LocaleStore(语言管理器)
使用事件订阅模式:
export class LocaleStore {
private locale = 'zh';
private messages = {};
private watchers = new Set<() => void>();
constructor(defaultMessages) {
this.messages = defaultMessages;
}
getLocale() {
return this.locale;
}
setLocale(lang) {
this.locale = lang;
this.notify();
}
extendMessages(lang, payload) {
this.messages[lang] = {
...this.messages[lang],
...payload
};
this.notify();
}
t(key, params) {
const msg = key.split('.').reduce((acc, cur) => acc?.[cur], this.messages[this.locale]);
return this.format(msg, params);
}
subscribe(fn) { this.watchers.add(fn); }
unsubscribe(fn) { this.watchers.delete(fn); }
notify() { this.watchers.forEach(fn => fn()); }
format(str, params) {
if (!params) return str;
return str.replace(/\{\{(.*?)\}\}/g, (_, key) => params[key.trim()]);
}
}
3. 组件库创建全局语言实例
import { zh } from './locales/zh'
import { en } from './locales/en'
import { LocaleStore } from './locale-store'
export const locale = new LocaleStore({ zh, en })
并导出:
export const setLocale = (lang) => locale.setLocale(lang)
export const extendLocale = (lang, msg) => locale.extendMessages(lang, msg)
4. Web Component 内使用语言
import { LitElement, html } from 'lit'
import { locale } from '../i18n/locale'
export class YcButton extends LitElement {
updateLocale = () => this.requestUpdate()
connectedCallback() {
super.connectedCallback()
locale.subscribe(this.updateLocale)
}
disconnectedCallback() {
locale.unsubscribe(this.updateLocale)
super.disconnectedCallback()
}
render() {
return html`<button>${locale.t('button.ok')}</button>`
}
}
语言切换后所有组件会自动渲染。
5. 应用层扩展语言包
① 注入新语言
extendLocale('fr', {
button: {
ok: 'D’accord'
}
})
setLocale('fr')
② 覆盖默认语言
extendLocale('zh', {
button: { ok: '好的' }
})
6. Web Component i18n 的优势总结
| 能力 | 是否支持 |
|---|---|
| 默认语言(内置) | ✔ |
| 外部扩展语言包 | ✔ |
| 外部覆盖默认语言 | ✔ |
| 全局切换语言 | ✔ |
| 所有组件自动刷新 | ✔ |
| 支持 React/Vue/原生环境 | ✔ |
| 支持按需加载语言包 | ✔ |
五、i18n 开发常见技巧
1. 不同语言语序
模板语法自动处理:
// zh
"welcome": "你好,{{name}}!"
// en
"welcome": "Hello, {{name}}!"
使用:
t('welcome', { name: 'Tom' })
框架会自动根据语言包输出正确语序。
2. 多复数处理(英文常见)
英文:
"count": "You have {{count}} message",
"count_plural": "You have {{count}} messages"
中文不需要复数处理。
3. 富文本内容
React:
t('content', {
name: <strong>Tom</strong>
})
Vue:
<div v-html="$t('content', { name: '<b>Tom</b>' })"></div>
4. 动态 key
t(`menu.${activeTab}.title`)
5. 按需加载语言
const lang = await import(`./locale/${langCode}.js`)
extendLocale(langCode, lang.default)
六、总结
前端国际化的核心目标是保证文案结构、语序、格式的灵活性,并提供企业级可扩展方案。
React 与 Vue 的方案成熟稳定,组件库需要独立设计 i18n 上下文,确保在不同应用中一致工作。
在实战中需要重点关注:
- 语序差异要在语言文件中解决
- 变量、复数、格式化能力必不可少
- 推荐使用 Intl API
- 大项目必须支持按需加载语言包
- 组件库需要提供 LocaleProvider 并允许外部覆盖语言
完整的 i18n 方案不仅提高产品国际化能力,也让开发过程更加规范可控。
文章评论