🌙 i18n 快速参考指南
🌙 快速开始
🌙 1. 在组件中使用(Hook)
import { useTranslation } from 'react-i18next';
const MyComponent = () => {
const { t } = useTranslation();
return <div>{t('key')}</div>;
};
1
2
3
4
5
6
2
3
4
5
6
🌙 2. 在非组件代码中使用
import i18n from 'i18next';
const label = i18n.t('key');
1
2
3
2
3
🌙 3. 使用HTML内容
import { Trans } from 'react-i18next';
<Trans i18nKey="key_with_html" />
1
2
3
2
3
🌙 文件结构
web/libs/editor/src/i18n/
├── index.ts # i18n 初始化
├── LanguageSwitcher.tsx # 语言选择器组件
├── react-i18next.d.ts # TypeScript 类型
└── locales/
├── en/
│ └── translations.ts # 英文翻译
└── zh/
└── translations.ts # 中文翻译
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
🌙 添加新翻译
🌙 步骤 1: 添加到翻译文件
英文 (locales/en/translations.ts):
const EN_TRANSLATIONS = {
my_new_key: "My New Text",
// ... 其他键
};
1
2
3
4
2
3
4
中文 (locales/zh/translations.ts):
const ZH_TRANSLATIONS = {
my_new_key: "我的新文本",
// ... 其他键
};
1
2
3
4
2
3
4
🌙 步骤 2: 在组件中使用
const { t } = useTranslation();
<div>{t('my_new_key')}</div>
1
2
2
🌙 常见模式
🌙 带变量(插值)
翻译:
{
welcome: "欢迎, {name}!"
}
1
2
3
2
3
用法:
t('welcome', { name: 'John' })
// 输出: "欢迎, John!"
1
2
2
🌙 条件文本
const message = isActive
? i18n.t('active_message')
: i18n.t('inactive_message');
1
2
3
2
3
🌙 在模态框/确认框中使用
confirm({
title: i18n.t('confirm_title'),
content: i18n.t('confirm_message'),
okText: i18n.t('ok'),
cancelText: i18n.t('cancel'),
});
1
2
3
4
5
6
2
3
4
5
6
🌙 在工具提示中使用
<Tooltip title={i18n.t('tooltip_text')}>
<Button />
</Tooltip>
1
2
3
2
3
🌙 最佳实践
🌙 ✅ 应该这样做
// 使用语义化的键名
t('delete_annotation')
// 按功能组织
const SETTINGS = {
enable_hotkeys: "启用快捷键",
show_labels: "显示标签"
};
// 对动态内容使用变量
t('time_ago', { time: '5分钟前' })
// 对HTML内容使用Trans组件
<Trans i18nKey="message_with_html" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
🌙 ❌ 不要这样做
// 不要使用无意义的键名
t('text1')
// 不要硬编码文本
<button>Delete</button>
// 不要忘记处理两种语言
// 始终在en和zh文件中添加翻译
// 不要在HTML内容中使用t()
t('message_with_html') // HTML标签会被转义
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
🌙 翻译键命名约定
🌙 模式: 功能_动作_上下文
{
// 功能: annotation, 动作: delete, 上下文: title
annotation_delete_title: "删除标注",
// 功能: annotation, 动作: delete, 上下文: desc
annotation_delete_desc: "您确定吗?",
// 功能: region, 动作: show, 上下文: all
region_show_all: "显示所有区域",
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
🌙 常见前缀
enable_*- 设置/开关show_*- 显示选项*_title- 对话框/模态框标题*_desc- 描述*_info- 信息消息*_error- 错误消息
🌙 添加新语言
🌙 1. 创建翻译文件
mkdir -p web/libs/editor/src/i18n/locales/fr
touch web/libs/editor/src/i18n/locales/fr/translations.ts
1
2
2
🌙 2. 添加翻译
// locales/fr/translations.ts
const FR_TRANSLATIONS = {
settings: "Paramètres",
delete: "Supprimer",
// ... 从EN复制所有键
};
export default FR_TRANSLATIONS;
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
🌙 3. 更新配置
// i18n/index.ts
import FR from './locales/fr/translations';
i18n.init({
supportedLngs: ['en', 'zh', 'fr'],
resources: {
en: { translation: EN },
zh: { translation: ZH },
fr: { translation: FR },
},
});
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
🌙 4. 更新语言切换器
// LanguageSwitcher.tsx
const languages = [
{ code: 'en', lang: 'English' },
{ code: 'zh', lang: '简体中文' },
{ code: 'fr', lang: 'Français' },
];
1
2
3
4
5
6
2
3
4
5
6
🌙 故障排除
🌙 问题: 显示翻译键而不是文本
检查:
- 键是否存在于翻译文件中
- 当前语言是否与文件匹配
- 键名是否有拼写错误
调试:
console.log(i18n.t('your_key'));
console.log(i18n.language);
1
2
2
🌙 问题: 语言切换不更新UI
解决方案: 使用 useTranslation() hook 而不是直接使用 i18n.t()
// ❌ 不会更新
const Component = () => {
const label = i18n.t('label');
return <div>{label}</div>;
};
// ✅ 会更新
const Component = () => {
const { t } = useTranslation();
return <div>{t('label')}</div>;
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
🌙 问题: HTML标签显示为文本
解决方案: 使用 <Trans> 组件
// ❌ HTML被转义
<div>{t('message_with_html')}</div>
// ✅ HTML被渲染
<div><Trans i18nKey="message_with_html" /></div>
1
2
3
4
5
2
3
4
5
🌙 翻译检查清单
在提交翻译更改之前:
- [ ] 所有键都存在于
en和zh翻译文件中 - [ ] 键名具有语义且描述性强
- [ ] 变量(如
{name})在各种语言中保持一致 - [ ] HTML标签在各种语言中保持一致
- [ ] 组件中没有硬编码的文本字符串
- [ ] 测试了语言切换
- [ ] 翻译准确且自然
- [ ] 长度不会破坏UI布局
🌙 常见翻译键参考
🌙 操作
delete, cancel, submit, update, save, reset,
undo, redo, skip, edit, add, create, copy
1
2
2
🌙 状态
draft, submitted, saved, skipped, accepted,
rejected, updated, created, started
1
2
2
🌙 UI元素
settings, general, hotkeys, layout, regions,
labels, comments, annotations, relations
1
2
2
🌙 消息
pls_confirm_del, no_changes_made, are_sure,
yes, no, confirm, proceed, cancel_edit
1
2
2
🌙 时间/用户
time_ago, by_name, created, started, updated
1
🌙 API快速参考
🌙 useTranslation Hook
const { t, i18n } = useTranslation();
t(key: string, options?: object): string
i18n.language: string
i18n.changeLanguage(lng: string): Promise
1
2
3
4
5
2
3
4
5
🌙 Trans 组件
<Trans
i18nKey="translation_key"
values={{ variable: value }}
components={{ bold: <strong /> }}
/>
1
2
3
4
5
2
3
4
5
🌙 直接访问 i18n
i18n.t(key: string, options?: object): string
i18n.changeLanguage(lng: string): Promise
i18n.language: string
i18n.languages: string[]
1
2
3
4
2
3
4
🌙 配置概览
// i18n/index.ts
i18n.init({
supportedLngs: ['en', 'zh'], // 支持的语言
fallbackLng: 'en', // 默认语言
defaultNS: 'translation', // 默认命名空间
detection: {
order: [ // 检测顺序
'queryString', // ?lng=en
'cookie', // Cookie
'localStorage', // localStorage
'navigator', // 浏览器设置
'htmlTag' // <html lang="">
],
caches: ['cookie'], // 缓存位置
},
react: {
useSuspense: true, // 使用React Suspense
},
interpolation: {
escapeValue: false, // React处理XSS
},
});
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
🌙 按用例分类的示例
🌙 按钮标签
<Button>{t('delete')}</Button>
<Button>{t('submit')}</Button>
<Button>{t('cancel')}</Button>
1
2
3
2
3
🌙 表单标签
<label>{t('start')}</label>
<label>{t('end')}</label>
<label>{t('duration')}</label>
1
2
3
2
3
🌙 工具提示
<Tooltip title={t('delete_annotation')}>
<IconButton />
</Tooltip>
1
2
3
2
3
🌙 模态对话框
Modal.confirm({
title: i18n.t('confirm_title'),
content: i18n.t('confirm_message'),
okText: i18n.t('ok'),
cancelText: i18n.t('cancel'),
});
1
2
3
4
5
6
2
3
4
5
6
🌙 错误消息
{error && <div className="error">{t('error_message')}</div>}
1
🌙 动态列表
const items = [
{ key: 'option1', label: t('option1') },
{ key: 'option2', label: t('option2') },
];
1
2
3
4
2
3
4
🌙 带变量
// 简单变量
t('welcome', { name: username })
// 多个变量
t('region_selected', { num: count })
// 时间格式化
t('time_ago', { time: formatTime(date) })
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
🌙 资源
- 完整文档: I18N_IMPLEMENTATION_GUIDE.md
- i18next 文档: https://www.i18next.com/
- react-i18next 文档: https://react.i18next.com/
- 源代码:
web/libs/editor/src/i18n/
有关详细信息、示例和最佳实践,请参阅完整的i18n指南。