国际化支持
国际化是现代前端开发中不可或缺的一部分,尤其在组件库开发中,良好的国际化支持能大幅提升组件的复用性和用户体验。以下从设计原则、技术实现到具体案例,详细探讨如何为组件开发规范融入国际化能力。
国际化设计原则
组件国际化需要遵循三个核心原则:
- 文本外置:所有UI文本必须与代码分离,通过键值对管理
- 文化适配:日期/时间/货币等格式需自动适应地区差异
- 布局弹性:文本长度变化时组件布局应保持稳定
反例示范:
// 错误示范:硬编码中文文本
<Button>确认</Button>
语言包结构规范
推荐采用分层式语言包结构:
locales/
├─ zh-CN/
│ ├─ component.json
│ ├─ page.json
├─ en-US/
│ ├─ component.json
│ ├─ page.json
component.json示例:
{
"button": {
"confirm": "确认",
"cancel": "取消"
},
"modal": {
"close": "关闭"
}
}
动态加载实现方案
基于React的国际化加载器实现:
import { createContext, useContext, useState } from 'react';
const I18nContext = createContext();
export function I18nProvider({ children }) {
const [locale, setLocale] = useState('zh-CN');
const [messages, setMessages] = useState({});
const loadLocale = async (locale) => {
const res = await import(`./locales/${locale}/component.json`);
setMessages(prev => ({ ...prev, ...res.default }));
};
return (
<I18nContext.Provider value={{ locale, messages, setLocale, loadLocale }}>
{children}
</I18nContext.Provider>
);
}
export function useI18n() {
return useContext(I18nContext);
}
日期时间本地化
使用day.js实现日期国际化:
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import 'dayjs/locale/ja';
function formatDate(date, locale) {
dayjs.locale(locale);
return dayjs(date).format('ll'); // 自动适配本地化格式
}
// 使用示例
formatDate(new Date(), 'zh-cn'); // 输出:2023年8月15日
formatDate(new Date(), 'en-us'); // 输出:Aug 15, 2023
复数规则处理
不同语言的复数规则差异示例:
const pluralRules = {
en: (n) => n === 1 ? 'one' : 'other',
ru: (n) => {
if (n % 10 === 1 && n % 100 !== 11) return 'one';
if ([2,3,4].includes(n % 10) && ![12,13,14].includes(n % 100)) return 'few';
return 'many';
}
};
function getPluralForm(locale, count) {
const rule = pluralRules[locale.split('-')[0]] || pluralRules.en;
return rule(count);
}
RTL布局支持
针对阿拉伯语等从右向左书写的语言:
[dir="rtl"] .menu {
padding-right: 20px;
padding-left: initial;
}
/* 使用逻辑属性替代物理属性 */
.sidebar {
padding-inline-start: 1rem;
text-align: start;
}
测试验证方案
编写国际化测试用例:
describe('i18n', () => {
beforeAll(async () => {
await loadLocale('ar-EG');
});
test('RTL布局生效', () => {
render(<App locale="ar-EG" />);
expect(document.documentElement).toHaveAttribute('dir', 'rtl');
});
test('阿拉伯语翻译存在', () => {
expect(t('button.confirm')).toBe('تأكيد');
});
});
构建优化策略
配置webpack实现按需加载语言包:
module.exports = {
module: {
rules: [
{
test: /locales\/.*\.json$/,
type: 'javascript/auto',
use: [
{
loader: 'bundle-loader',
options: {
lazy: true,
name: '[folder]/[name]'
}
}
]
}
]
}
}
错误处理机制
实现翻译回退链:
function t(key, locale = currentLocale) {
const locales = [locale];
// 添加回退链
if (locale.includes('-')) {
locales.push(locale.split('-')[0]);
}
locales.push('en'); // 最终回退到英文
for (const l of locales) {
if (messages[l]?.[key]) {
return messages[l][key];
}
}
return key; // 最后返回key本身
}
文档规范要求
在组件文档中明确国际化字段:
### DatePicker 国际化字段
```json
{
"datePicker": {
"placeholder": "请选择日期",
"rangePlaceholder": ["开始日期", "结束日期"],
"today": "今天"
}
}
```
版本控制策略
语言包版本与组件主版本号绑定:
1.2.0-component
1.2.0-locales-zh-CN
1.2.0-locales-en-US
自动化检测工具
配置CI检测脚本:
# 检查是否存在未翻译字段
grep -rE 't\(.+\)' src/ | awk -F"'" '{print $2}' | sort | uniq > used_keys.txt
comm -23 used_keys.txt <(jq -r 'keys[]' locales/en-US/component.json | sort) > missing_keys.txt
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn