AionUi i18n
git clone https://github.com/iOfficeAI/AionUi
T=$(mktemp -d) && git clone --depth=1 https://github.com/iOfficeAI/AionUi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/i18n" ~/.claude/skills/iofficeai-aionui-i18n && rm -rf "$T"
.claude/skills/i18n/SKILL.mdi18n 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."
IMPORTANT: Read Config First
Before doing any i18n work, always read
to get the current list of supported languages and modules. Never assume a fixed number — languages and modules may have been added or removed since this skill was written.src/common/config/i18n-config.json
cat src/common/config/i18n-config.json
This file is the single source of truth. All scripts, runtime code, and this workflow depend on it.
File Structure
src/common/config/i18n-config.json # Single source of truth: languages, modules src/renderer/i18n/ ├── index.ts # i18next configuration ├── i18n-keys.d.ts # AUTO-GENERATED — do not edit manually └── locales/ ├── <lang>/ # One directory per language in i18n-config.json │ ├── index.ts # Barrel import for all modules │ ├── common.json # One JSON per module in i18n-config.json │ ├── conversation.json │ └── ... └── ...
Key Facts
- Reference language: defined by
inreferenceLanguage
(currentlyi18n-config.json
)en-US - Supported languages: defined by
array — read the file to get the current listsupportedLanguages - Modules: defined by
array — read the file to get the current listmodules
Key Structure
Keys use namespaced dot notation in code:
t('module.key') or t('module.nested.key').
Inside each module JSON file, keys can be flat or nested:
// common.json — flat keys { "send": "Send", "cancel": "Cancel", "copySuccess": "Copied" } // cron.json — nested keys { "scheduledTasks": "Scheduled Tasks", "status": { "active": "Active", "paused": "Paused" } }
In code:
t('common.send'); // flat key in common.json t('cron.status.active'); // nested key in cron.json
Key Naming Rules
- Use camelCase for key names:
,copySuccessscheduledTasks - Group related keys with nesting:
,status.activeactions.pause - Reusable text goes in
: save, cancel, delete, confirm, etc.common.json - Feature-specific text goes in the corresponding module
Common Suffixes
| Suffix | Usage |
|---|---|
| Section/page titles |
| Input placeholders |
| Form labels |
/ | Status messages |
| Confirmation dialogs |
| Empty state messages |
| Tooltip text |
Adding New Text — Workflow
Step 1: Read src/common/config/i18n-config.json
src/common/config/i18n-config.jsonGet the current language list and module list. Do not skip this step.
Step 2: Check Existing Keys
Before adding a new key, search for similar existing keys:
grep -r "keyword" src/renderer/i18n/locales/en-US/
Reuse
common.* keys when possible.
Step 3: Choose the Right Module
Match the module to the feature area. If no module fits, consider whether a new module is needed (see "Adding a New Module" below).
Step 4: Add to ALL Locale Directories
CRITICAL: Every new key must be added to every locale in
supportedLanguages. Use this checklist for each key:
-
— reference language (added in Step 3)en-US/<module>.json -
— addedzh-CN/<module>.json -
— addedzh-TW/<module>.json - Any other language listed in
→src/common/config/i18n-config.json
— addedsupportedLanguages
A key missing from even one locale will cause
node scripts/check-i18n.js to fail in CI.
Step 5: Use in Component
import { useTranslation } from 'react-i18next'; function MyComponent() { const { t } = useTranslation(); return <button>{t('common.save')}</button>; }
Step 6: Regenerate Types and Validate
Run these two commands in order — both must pass before committing:
bun run i18n:types # Step A: regenerate i18n-keys.d.ts from reference locale node scripts/check-i18n.js # Step B: validate structure, keys, and type sync
must be run beforei18n:types
— the check validates the generated filecheck-i18n.js- If
exits with errors (❌), fix them before proceedingcheck-i18n.js - If
exits with warnings only (⚠️), review but may proceedcheck-i18n.js - Never commit with a stale
i18n-keys.d.ts
Adding a New Module
- Add module name to
→src/common/config/i18n-config.json
arraymodules - Create
in every locale directory (read<module>.json
to know which)supportedLanguages - Add import + export in each locale's
index.ts - Run
to regenerate type definitionsbun run i18n:types - Run
to validatenode scripts/check-i18n.js
Hardcoded String Detection
Prohibited Patterns
Never use hardcoded Chinese/English text in JSX:
// Bad <span>重命名</span> <span>Delete</span> {name || '新对话'} // Good <span>{t('common.rename')}</span> <span>{t('common.delete')}</span> {name || t('conversation.newConversation')}
Exceptions
- Code comments (any language OK)
/ debug outputconsole.log()- Internal string constants not shown to users
Interpolation
Variables
{ "taskCount": "{{count}} task(s)", "greeting": "Hello, {{name}}!" }
t('cron.taskCount', { count: 5 });
HTML in Translations
Use Trans component for complex markup:
import { Trans } from 'react-i18next'; <Trans i18nKey='cron.countdown'> Task <strong>{{ taskName }}</strong> in <span>{{ countdown }}</span> </Trans>;
zh-TW Maintenance
Most terms can be auto-converted from zh-CN, but some need manual review:
| zh-CN | zh-TW | Notes |
|---|---|---|
| 视频 | 影片 | Different term |
| 软件 | 軟體 | Different term |
| 信息 | 訊息 | Different term |
| 默认 | 預設 | Different term |
Quick Checklist
Before submitting code with new text:
- Read
to get current languages and modulessrc/common/config/i18n-config.json - All user-visible text uses
functiont() - New keys added to every locale directory in
supportedLanguages - No hardcoded Chinese/English in JSX
- zh-TW reviewed for term differences
-
ran first (regeneratesbun run i18n:types
)i18n-keys.d.ts -
passed after types regenerated (no errors)node scripts/check-i18n.js
Common Mistakes
| Mistake | Correct |
|---|---|
| Assuming a fixed number of languages | Always read first |
| Adding key to only some locales | Add to every locale in |
Editing manually | Run to generate |
Using | Define key: |
Not updating for new module | Update config first, then create files |
Adding module JSON but not updating | Must add import + export in each locale's |