Label Studio Editor i18n Quick Reference Guide (EN)

2025/12/1 Label Studioi18n

🌙 i18n Quick Reference Guide

🌙 Quick Start

🌙 1. Using in Components (Hook)

import { useTranslation } from 'react-i18next';

const MyComponent = () => {
  const { t } = useTranslation();
  return <div>{t('key')}</div>;
};
1
2
3
4
5
6

🌙 2. Using in Non-Component Code

import i18n from 'i18next';

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

🌙 3. Using with HTML Content

import { Trans } from 'react-i18next';

<Trans i18nKey="key_with_html" />
1
2
3

🌙 File Structure

web/libs/editor/src/i18n/
├── index.ts                    # i18n initialization
├── LanguageSwitcher.tsx        # Language selector component
├── react-i18next.d.ts          # TypeScript types
└── locales/
    ├── en/
    │   └── translations.ts     # English translations
    └── zh/
        └── translations.ts     # Chinese translations
1
2
3
4
5
6
7
8
9

🌙 Adding New Translations

🌙 Step 1: Add to Translation Files

English (locales/en/translations.ts):

const EN_TRANSLATIONS = {
  my_new_key: "My New Text",
  // ... other keys
};
1
2
3
4

Chinese (locales/zh/translations.ts):

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

🌙 Step 2: Use in Components

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

🌙 Common Patterns

🌙 With Variables (Interpolation)

Translation:

{
  welcome: "Welcome, {name}!"
}
1
2
3

Usage:

t('welcome', { name: 'John' })
// Output: "Welcome, John!"
1
2

🌙 Conditional Text

const message = isActive 
  ? i18n.t('active_message') 
  : i18n.t('inactive_message');
1
2
3

🌙 In Modal/Confirm

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

🌙 In Tooltips

<Tooltip title={i18n.t('tooltip_text')}>
  <Button />
</Tooltip>
1
2
3

🌙 Best Practices

🌙 ✅ DO

// Use semantic key names
t('delete_annotation')

// Organize by feature
const SETTINGS = {
  enable_hotkeys: "Enable Hotkeys",
  show_labels: "Show Labels"
};

// Use variables for dynamic content
t('time_ago', { time: '5 minutes' })

// Use Trans for HTML content
<Trans i18nKey="message_with_html" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14

🌙 ❌ DON'T

// Don't use meaningless keys
t('text1')

// Don't hard-code text
<button>Delete</button>

// Don't forget to handle both languages
// Always add translations to both en and zh files

// Don't use t() for HTML content
t('message_with_html')  // HTML tags will be escaped
1
2
3
4
5
6
7
8
9
10
11

🌙 Translation Key Naming Conventions

🌙 Pattern: feature_action_context

{
  // Feature: annotation, action: delete, context: title
  annotation_delete_title: "Delete Annotation",
  
  // Feature: annotation, action: delete, context: description
  annotation_delete_desc: "Are you sure?",
  
  // Feature: region, action: show, context: all
  region_show_all: "Show All Regions",
}
1
2
3
4
5
6
7
8
9
10

🌙 Common Prefixes

  • enable_* - Settings/toggles
  • show_* - Display options
  • *_title - Dialog/modal titles
  • *_desc - Descriptions
  • *_info - Information messages
  • *_error - Error messages

🌙 Adding a New Language

🌙 1. Create Translation File

mkdir -p web/libs/editor/src/i18n/locales/fr
touch web/libs/editor/src/i18n/locales/fr/translations.ts
1
2

🌙 2. Add Translations

// locales/fr/translations.ts
const FR_TRANSLATIONS = {
  settings: "Paramètres",
  delete: "Supprimer",
  // ... copy all keys from EN
};

export default FR_TRANSLATIONS;
1
2
3
4
5
6
7
8

🌙 3. Update Configuration

// 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. Update Language Switcher

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

🌙 Troubleshooting

🌙 Issue: Translation key shows instead of text

Check:

  1. Key exists in translation file
  2. Current language matches file
  3. No typos in key name

Debug:

console.log(i18n.t('your_key'));
console.log(i18n.language);
1
2

🌙 Issue: Language switch doesn't update UI

Solution: Use useTranslation() hook instead of direct i18n.t()

// ❌ Won't update
const Component = () => {
  const label = i18n.t('label');
  return <div>{label}</div>;
};

// ✅ Will update
const Component = () => {
  const { t } = useTranslation();
  return <div>{t('label')}</div>;
};
1
2
3
4
5
6
7
8
9
10
11

🌙 Issue: HTML tags display as text

Solution: Use <Trans> component

// ❌ HTML escaped
<div>{t('message_with_html')}</div>

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

🌙 Translation Checklist

Before committing translation changes:

  • [ ] All keys exist in both en and zh translation files
  • [ ] Key names are semantic and descriptive
  • [ ] Variables (like {name}) are consistent across languages
  • [ ] HTML tags are consistent across languages
  • [ ] No hard-coded text strings in components
  • [ ] Tested language switching
  • [ ] Translation is accurate and natural
  • [ ] Length doesn't break UI layout

🌙 Common Translation Keys Reference

🌙 Actions

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

🌙 Status

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

🌙 UI Elements

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

🌙 Messages

pls_confirm_del, no_changes_made, are_sure,
yes, no, confirm, proceed, cancel_edit
1
2

🌙 Time/User

time_ago, by_name, created, started, updated
1

🌙 API Quick Reference

🌙 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 Component

<Trans 
  i18nKey="translation_key"
  values={{ variable: value }}
  components={{ bold: <strong /> }}
/>
1
2
3
4
5

🌙 Direct i18n Access

i18n.t(key: string, options?: object): string
i18n.changeLanguage(lng: string): Promise
i18n.language: string
i18n.languages: string[]
1
2
3
4

🌙 Configuration Overview

// i18n/index.ts
i18n.init({
  supportedLngs: ['en', 'zh'],      // Supported languages
  fallbackLng: 'en',                // Default language
  defaultNS: 'translation',         // Default namespace
  
  detection: {
    order: [                        // Detection order
      'queryString',                // ?lng=en
      'cookie',                     // Cookie
      'localStorage',               // localStorage
      'navigator',                  // Browser setting
      'htmlTag'                     // <html lang="">
    ],
    caches: ['cookie'],             // Cache location
  },
  
  react: {
    useSuspense: true,              // Use React Suspense
  },
  
  interpolation: {
    escapeValue: false,             // React handles 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

🌙 Examples by Use Case

🌙 Button Labels

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

🌙 Form Labels

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

🌙 Tooltips

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

{error && <div className="error">{t('error_message')}</div>}
1

🌙 Dynamic Lists

const items = [
  { key: 'option1', label: t('option1') },
  { key: 'option2', label: t('option2') },
];
1
2
3
4

🌙 With Variables

// Simple variable
t('welcome', { name: username })

// Multiple variables
t('region_selected', { num: count })

// Time formatting
t('time_ago', { time: formatTime(date) })
1
2
3
4
5
6
7
8

🌙 Resources

  • Full Documentation: I18N_IMPLEMENTATION_GUIDE.md
  • i18next Docs: https://www.i18next.com/
  • react-i18next Docs: https://react.i18next.com/
  • Source Code: web/libs/editor/src/i18n/

For detailed information, examples, and best practices, see the complete i18n guide.