Label Studio Editor i18n 快速参考指南(ZH)

2025/12/1 Label Studioi18n

🌙 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. 在非组件代码中使用

import i18n from 'i18next';

const label = i18n.t('key');
1
2
3

🌙 3. 使用HTML内容

import { Trans } from 'react-i18next';

<Trans i18nKey="key_with_html" />
1
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

🌙 添加新翻译

🌙 步骤 1: 添加到翻译文件

英文 (locales/en/translations.ts):

const EN_TRANSLATIONS = {
  my_new_key: "My New Text",
  // ... 其他键
};
1
2
3
4

中文 (locales/zh/translations.ts):

const ZH_TRANSLATIONS = {
  my_new_key: "我的新文本",
  // ... 其他键
};
1
2
3
4

🌙 步骤 2: 在组件中使用

const { t } = useTranslation();
<div>{t('my_new_key')}</div>
1
2

🌙 常见模式

🌙 带变量(插值)

翻译:

{
  welcome: "欢迎, {name}!"
}
1
2
3

用法:

t('welcome', { name: 'John' })
// 输出: "欢迎, John!"
1
2

🌙 条件文本

const message = isActive 
  ? i18n.t('active_message') 
  : i18n.t('inactive_message');
1
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

🌙 在工具提示中使用

<Tooltip title={i18n.t('tooltip_text')}>
  <Button />
</Tooltip>
1
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

🌙 ❌ 不要这样做

// 不要使用无意义的键名
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

🌙 翻译键命名约定

🌙 模式: 功能_动作_上下文

{
  // 功能: 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

🌙 常见前缀

  • 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. 添加翻译

// 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

🌙 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

🌙 4. 更新语言切换器

// LanguageSwitcher.tsx
const languages = [
  { code: 'en', lang: 'English' },
  { code: 'zh', lang: '简体中文' },
  { code: 'fr', lang: 'Français' },
];
1
2
3
4
5
6

🌙 故障排除

🌙 问题: 显示翻译键而不是文本

检查:

  1. 键是否存在于翻译文件中
  2. 当前语言是否与文件匹配
  3. 键名是否有拼写错误

调试:

console.log(i18n.t('your_key'));
console.log(i18n.language);
1
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

🌙 问题: HTML标签显示为文本

解决方案: 使用 <Trans> 组件

// ❌ HTML被转义
<div>{t('message_with_html')}</div>

// ✅ HTML被渲染
<div><Trans i18nKey="message_with_html" /></div>
1
2
3
4
5

🌙 翻译检查清单

在提交翻译更改之前:

  • [ ] 所有键都存在于 enzh 翻译文件中
  • [ ] 键名具有语义且描述性强
  • [ ] 变量(如 {name})在各种语言中保持一致
  • [ ] HTML标签在各种语言中保持一致
  • [ ] 组件中没有硬编码的文本字符串
  • [ ] 测试了语言切换
  • [ ] 翻译准确且自然
  • [ ] 长度不会破坏UI布局

🌙 常见翻译键参考

🌙 操作

delete, cancel, submit, update, save, reset, 
undo, redo, skip, edit, add, create, copy
1
2

🌙 状态

draft, submitted, saved, skipped, accepted, 
rejected, updated, created, started
1
2

🌙 UI元素

settings, general, hotkeys, layout, regions, 
labels, comments, annotations, relations
1
2

🌙 消息

pls_confirm_del, no_changes_made, are_sure,
yes, no, confirm, proceed, cancel_edit
1
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

🌙 Trans 组件

<Trans 
  i18nKey="translation_key"
  values={{ variable: value }}
  components={{ bold: <strong /> }}
/>
1
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

🌙 配置概览

// 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

🌙 按用例分类的示例

🌙 按钮标签

<Button>{t('delete')}</Button>
<Button>{t('submit')}</Button>
<Button>{t('cancel')}</Button>
1
2
3

🌙 表单标签

<label>{t('start')}</label>
<label>{t('end')}</label>
<label>{t('duration')}</label>
1
2
3

🌙 工具提示

<Tooltip title={t('delete_annotation')}>
  <IconButton />
</Tooltip>
1
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

🌙 错误消息

{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

🌙 带变量

// 简单变量
t('welcome', { name: username })

// 多个变量
t('region_selected', { num: count })

// 时间格式化
t('time_ago', { time: formatTime(date) })
1
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指南