i18n
Original:🇺🇸 English
Translated
Internationalization (i18n) workflow and standards for managing translations. Use when: (1) Adding new user-facing text, (2) Creating new components with text, (3) Reviewing code for i18n compliance. Features: Key naming conventions, sync checking, hardcoded string detection, translation workflow.
2installs
Sourceiofficeai/aionui
Added on
NPX Install
npx skill4agent add iofficeai/aionui i18nTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →i18n Skill
Standards and workflow for internationalization. All user-visible text must use i18n.
Announce at start: "I'm using i18n skill to ensure proper internationalization."
File Structure
src/renderer/i18n/
├── index.ts # i18next configuration
└── locales/
├── en-US.json # English (primary)
├── zh-CN.json # Simplified Chinese
├── zh-TW.json # Traditional Chinese
├── ja-JP.json # Japanese
└── ko-KR.json # KoreanKey Naming Convention
IMPORTANT: New i18n keys MUST use flat dot-notation format.
Format:
<module>.<feature>.<detail>Rules
| Level | Description | Examples |
|---|---|---|
| Module | Page or major feature | |
| Feature | Specific functionality | |
| Detail | Specific text purpose | |
Examples
✓ cron.form.title
✓ cron.form.namePlaceholder
✓ cron.list.emptyState
✓ settings.llm.apiKeyRequired
✗ cronFormTitle (missing dots)
✗ CRON.FORM.TITLE (wrong case)Flat vs Nested Structure
json
// ✅ GOOD - flat structure (use for NEW keys)
{
"cron.form.title": "Create Scheduled Task",
"cron.form.nameLabel": "Task Name",
"cron.list.empty": "No scheduled tasks"
}
// ❌ AVOID - nested structure (legacy only, do not add new)
{
"cron": {
"form": {
"title": "..."
}
}
}Rationale:
- Flat keys are searchable in codebase (see , search directly)
t('cron.form.title') - Easier to verify sync across locale files
- Avoids deep nesting confusion
Common Suffixes
| Suffix | Usage |
|---|---|
| Section/page titles |
| Input placeholders |
| Form labels |
| Button text |
| Status messages |
| Confirmation dialogs |
| Empty state messages |
| Loading states |
| Tooltip text |
Shared Keys
Use for reusable text:
common.*json
{
"common.save": "Save",
"common.cancel": "Cancel",
"common.confirm": "Confirm",
"common.delete": "Delete",
"common.loading": "Loading..."
}Adding New Text Workflow
Step 1: Check Existing Keys
Before adding new key, search for similar existing keys:
bash
grep -r "keyword" src/renderer/i18n/locales/Step 2: Add to ALL Locale Files
CRITICAL: Must add to all 5 files simultaneously.
bash
# Files to update:
src/renderer/i18n/locales/en-US.json # English text
src/renderer/i18n/locales/zh-CN.json # Simplified Chinese
src/renderer/i18n/locales/zh-TW.json # Traditional Chinese
src/renderer/i18n/locales/ja-JP.json # Japanese
src/renderer/i18n/locales/ko-KR.json # KoreanStep 3: Use in Component
tsx
import { useTranslation } from 'react-i18next';
function MyComponent() {
const { t } = useTranslation();
return <button>{t('module.feature.action')}</button>;
}Step 4: Verify Sync
After adding, verify all files have the new keys.
Sync Checking
Before Commit
Always verify key sync across all locale files:
bash
# Quick check - compare line counts (rough indicator)
wc -l src/renderer/i18n/locales/*.json
# Check for flat keys diff between en-US and zh-CN
diff <(grep -oE '"[a-zA-Z0-9_.]+":' src/renderer/i18n/locales/en-US.json | sort -u) \
<(grep -oE '"[a-zA-Z0-9_.]+":' src/renderer/i18n/locales/zh-CN.json | sort -u)Fix Sync Issues
If keys are out of sync:
- Identify missing keys from diff output
- Add missing keys to appropriate files
- Re-run diff to verify
Hardcoded String Detection
Prohibited Patterns
Never use hardcoded Chinese/English text in JSX:
tsx
// ❌ BAD
<span>重命名</span>
<span>Delete</span>
<button title="更多操作">...</button>
{name || '新对话'}
// ✅ GOOD
<span>{t('common.rename')}</span>
<span>{t('common.delete')}</span>
<button title={t('common.moreActions')}>...</button>
{name || t('chat.newConversation')}Exceptions
Comments and internal logs are allowed:
tsx
// This is a comment, Chinese is OK
console.log('Debug info'); // OK for logszh-TW Maintenance
Auto-conversion Safe
Most terms can be auto-converted from zh-CN:
- 设置 → 設置
- 删除 → 刪除
- 确认 → 確認
Manual Adjustment Required
Some terms need manual review:
| zh-CN | zh-TW | Notes |
|---|---|---|
| 视频 | 影片 | Different term |
| 软件 | 軟體 | Different term |
| 信息 | 訊息 | Different term |
| 默认 | 預設 | Different term |
Interpolation
Variables
json
{
"greeting": "Hello, {{name}}!",
"itemCount": "{{count}} items"
}tsx
t('greeting', { name: 'User' });
t('itemCount', { count: 5 });HTML in Translations
Use Trans component for complex markup:
tsx
import { Trans } from 'react-i18next';
<Trans i18nKey='cron.countdown'>
Task <strong>{{ taskName }}</strong> in <span>{{ countdown }}</span>
</Trans>;Quick Checklist
Before submitting code with new text:
- All user-visible text uses function
t() - New keys use flat format
module.feature.detail - New keys added to ALL 5 locale files
- No hardcoded Chinese/English in JSX
- zh-TW reviewed for term differences
- ja-JP and ko-KR translations added (or marked TODO)
Common Mistakes
| Mistake | Correct |
|---|---|
| Adding key to only one file | Add to all 5 files |
| Using nested structure for new | Use flat |
Using | Define key: |
| Inline Chinese in JSX | Use |
| Forgetting interpolation | Use |