[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CFB055EXKR72703ST6H3XW":3,"skill-same:01M6CFB055EXKR72703ST6H3XW":82},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":39,"repositoryHtmlUrl":40,"repositoryHomepageUrl":6,"ownerHtmlUrl":41,"ownerBlogUrl":41,"ownerDescription":42,"updatedAt":43,"install":44,"resources":57},"01M6CFB055EXKR72703ST6H3XW","ios-i18n-workflow",null,"Use when iOS apps using SwiftGen L10n need localization work - adding keys, checking missing translations, or cleaning unused entries. Triggered by hardcoded strings, missing L10n references, incomplete translations across multiple languages, or unused localization cleanup requests.","HeathWang\u002Fhw-cc-plugin","HeathWang","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F4961711?v=4","01M6CF9BZ3A0CSSG3QQGGDPFEH","Heath Wang","01M6CF9C3HT4NPM370Z8MYZW4G",1,"MIT","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30],"workflow","ios","ios i18n workflow","cleanup","work","use","references","2026-11-10 10:12:30",false,"---\nname: ios-i18n-workflow\ndescription: Use when iOS apps using SwiftGen L10n need localization work - adding keys, checking missing translations, or cleaning unused entries. Triggered by hardcoded strings, missing L10n references, incomplete translations across multiple languages, or unused localization cleanup requests.\n---\n\n# iOS Internationalization Workflow\n\nComplete workflow for managing iOS app internationalization (i18n) using SwiftGen L10n code generation. Supports any number of target languages. Covers three main scenarios: internationalizing code, verifying translation completeness, and cleaning unused entries.\n\n## When to Use\n\n```dot\ndigraph when_to_use {\n    rankdir=TB;\n    \"User provides code\u002Ffolder for i18n?\" [shape=diamond, style=filled, fillcolor=lightblue];\n    \"User asks to check missing translations?\" [shape=diamond, style=filled, fillcolor=lightgreen];\n    \"User asks to clean unused i18n?\" [shape=diamond, style=filled, fillcolor=lightyellow];\n    \"Standardize\" [shape=box, style=filled, fillcolor=lightcoral];\n    \"CheckMissing\" [shape=box, style=filled, fillcolor=lightcoral];\n    \"CleanUp\" [shape=box, style=filled, fillcolor=lightcoral];\n\n    \"User provides code\u002Ffolder for i18n?\" -> \"Standardize\" [label=\"Yes\\n(Full workflow)\"];\n    \"User asks to check missing translations?\" -> \"CheckMissing\" [label=\"Yes\\n(Verify only)\"];\n    \"User asks to clean unused i18n?\" -> \"CleanUp\" [label=\"Yes\\n(Cleanup only)\"];\n}\n```\n\n**Three main scenarios:**\n\n1. **Internationalize code** - User provides code or folder: \"Here's my view controller, add i18n\"\n   → Run full workflow (baseline → ALL target languages → verify → SwiftGen)\n\n2. **Check missing translations** - User explicitly asks: \"Check if translations are complete\" or \"Find missing i18n keys\"\n   → Run check_missing_localizations.py for each target language and fill gaps\n\n3. **Clean unused entries** - User explicitly asks: \"Clean unused localizations\" or \"Remove unused i18n keys\"\n   → Run clean_unused_localizations.py with dry-run first\n\n**Key principle:** Complete translations for ALL target languages before verification and SwiftGen generation.\n\n**Do NOT use when:**\n- Projects using raw NSLocalizedString without SwiftGen\n- Non-iOS platforms (Android, Web)\n\n## Identifying User Intent\n\n**Determining which scenario applies:**\n\n### Scenario 1: Full Workflow\nUser provides code files or folder paths, says things like \"internationalize this\" or \"add i18n to this code\"\n\n### Scenario 2: Check Missing\nUser asks to verify translation completeness with phrases like \"check if translations complete\" or \"find missing i18n keys\"\n\n### Scenario 3: Cleanup\nUser requests removal of unused entries with phrases like \"clean unused localizations\" or \"remove unused i18n keys\"\n\n**Quick decision guide:**\n- Provides code\u002Ffolder → **Scenario 1** (Full workflow)\n- Asks to check\u002Fverify → **Scenario 2** (Check missing)\n- Asks to clean\u002Fremove → **Scenario 3** (Cleanup)\n\n## Red Flags - STOP and Re-read\n\n**For Scenario 1 (Full internationalization):**\n- \"I'll just run swiftgen real quick\"\n- \"The translations can wait\"\n- \"I'll add the keys manually\"\n- \"This phase doesn't apply to my case\"\n- \"I can skip phase 4 and run it later\"\n- \"No need to verify with scripts, trust me\"\n\n**For Scenario 2 (Check missing):**\n- \"I can just eyeball the files\"\n- \"Checking one target language is enough\"\n- \"I'll add keys later\"\n- \"The other languages look fine\"\n\n**For Scenario 3 (Cleanup):**\n- \"Just delete everything without checking\"\n- \"No need for --dry-run first\"\n\n**All of these mean: Read the skill again and follow the correct workflow.**\n\n## Configuration\n\n**Project-specific variables:**\n```yaml\nproject_root: \"\u002Fpath\u002Fto\u002Fyour\u002FiOS\u002Fproject\"\nlocalization_dir: \"*\u002FLocalization\"\nbaseline_language: \"zh-Hans\"  # Source of truth (can be any language)\ntarget_languages: [\"zh-Hant\", \"en\", \"ja\", \"ko\", \"de\"]  # ALL target languages\ngenerated_file: \"Generated\u002FStrings.swift\"\n```\n\n**Default structure:**\n```\n\u003CProjectRoot>\u002Fpath\u002F\u003Clocalization_dir>\u002F\n├── zh-Hans.lproj\u002FLocalizable.strings  # Baseline (source of truth)\n├── zh-Hant.lproj\u002FLocalizable.strings  # Target 1\n├── en.lproj\u002FLocalizable.strings       # Target 2\n└── ja.lproj\u002FLocalizable.strings       # Target 3 (add more as needed)\n```\n\n**Note:** The baseline language can be any language (zh-Hans, en, ja, etc.). Choose the language you work with most frequently as baseline.\n\n## Scenario 1: Full Internationalization Workflow\n\n**Use when:** User provides code\u002Ffolder for internationalization\n\n**Flow:** Sequential phases with iterative target language processing\n\n```\nPhase 1: Baseline → Phase 2+: Target Languages (repeat for ALL) → Verification → SwiftGen\n```\n\n**Critical:**\n- Complete ALL target language translations sequentially before verification\n- Verification step must confirm ALL languages aligned before SwiftGen\n- If missing keys found, return to incomplete target language phase\n\n### Phase 1: Baseline Localization\n\nUpdate baseline language file and replace hardcoded strings with L10n references.\n\n1. Extract hardcoded strings from Swift\u002FObjC files\n2. Add new\u002Fmodified strings to baseline file following naming conventions\n3. Replace strings with `L10n.xxx` calls\n\n**Completion:** Baseline updated and code references replaced.\n\n### Phase 2+: Target Language Translations (Repeat for ALL Target Languages)\n\n**For EACH target language in your configuration:**\n\n1. **Identify new keys from Phase 1** - Review the keys added to baseline file\n2. **Translate each new key** from baseline language to this target language\n3. **Add translations** to this target language's `.strings` file following the same structure\n\n**Process:**\n- Complete ONE target language fully before moving to the next\n- Copy new\u002Fmodified keys from Phase 1 baseline\n- Translate values (not keys) to target language\n- Maintain same key names and structure as baseline\n- Preserve placeholders like `%@`, `%d`, etc.\n\n### Verification Step (CRITICAL)\n\n**After completing ALL target language translations, verify alignment:**\n\nThis step confirms ALL translations are complete and aligned with baseline.\n\n```bash\n# Check each target language against baseline\nfor target_lang in \"${target_languages[@]}\"; do\n  python3 \u003Cskill_path>\u002Fscripts\u002Fcheck_missing_localizations.py \\\n    \u003Clocalization_dir>\u002F\u003Cbaseline_lang>.lproj\u002FLocalizable.strings \\\n    \u003Clocalization_dir>\u002F${target_lang}.lproj\u002FLocalizable.strings\ndone\n```\n\n**Example:** `python3 scripts\u002Fcheck_missing_localizations.py Localization\u002Fzh-Hans.lproj\u002FLocalizable.strings Localization\u002Fen.lproj\u002FLocalizable.strings`\n\n**Expected output for EACH language:** `✅ [target] 文件没有缺失的键。`\n\n**If missing keys found:** Return to the incomplete target language phase and add missing translations.\n\n**Only proceed to Final Phase after verification confirms ALL languages aligned.**\n\n### Final Phase: Generate Swift Code\n\n**Critical:** Run after ALL changes and verification.\n\n```bash\ncd \u003Cproject_root>\nswiftgen\n```\n\n**Completion:** Code generated with all L10n references available for ALL languages.\n\n## Scenario 2: Check Missing Translations\n\n**Use when:** User explicitly asks \"Check if translations are complete\" or \"Find missing i18n keys\"\n\n### Workflow\n\n1. **Identify baseline language** (usually zh-Hans or en)\n2. **Check EACH target language** against baseline:\n\n```bash\npython3 \u003Cskill_path>\u002Fscripts\u002Fcheck_missing_localizations.py \\\n  \u003Clocalization_dir>\u002F\u003Cbaseline_lang>.lproj\u002FLocalizable.strings \\\n  \u003Clocalization_dir>\u002F\u003Ctarget_lang>.lproj\u002FLocalizable.strings\n```\n\nRepeat for ALL target languages.\n\n3. **Review reports** - Each check shows missing keys for that target language\n4. **Add missing translations** to each target language file\n5. **Re-run verification** for all modified languages to confirm all aligned\n6. **Run SwiftGen** if any translations were added\n\n**Completion:** ALL target languages have complete translations matching baseline.\n\n## Scenario 3: Clean Unused Localizations\n\n**Use when:** User explicitly asks \"Clean unused localizations\" or \"Remove unused i18n keys\"\n\n### Workflow\n\n1. **Dry-run first** (see what would be deleted):\n\n```bash\ncd \u003Cproject_root>\npython3 \u003Cskill_path>\u002Fscripts\u002Fclean_unused_localizations.py --dry-run\n```\n\n2. **Review the report** - Shows unused entries and usage statistics\n3. **Run actual cleanup** (after confirmation):\n\n```bash\npython3 \u003Cskill_path>\u002Fscripts\u002Fclean_unused_localizations.py\n```\n\n4. **Run SwiftGen** to regenerate code:\n\n```bash\nswiftgen\n```\n\n**Safety:**\n- Script creates `.backup` file before deletion\n- Prompts for confirmation before deleting\n- Requires explicit user confirmation\n\n**Completion:** Unused entries removed, SwiftGen regenerated.\n\n## Quick Reference\n\n### Scenario 1: Full Internationalization\n\n| Task | Command\u002FApproach | Phase |\n|------|------------------|-------|\n| Extract hardcoded strings | Manual review of provided code | 1 (Baseline) |\n| Add keys to baseline | Edit baseline `.strings` file | 1 |\n| Replace with L10n | `L10n.Module.key` syntax | 1 |\n| Translate to ALL targets | Copy keys from baseline, translate values sequentially | 2+ |\n| Verify alignment | `python3 scripts\u002Fcheck_missing_localizations.py \u003Cbaseline> \u003Ctarget>` for EACH target | After ALL translations |\n| Generate Swift code | `swiftgen` | Final |\n\n### Scenario 2: Check Missing Only\n\n| Task | Command |\n|------|---------|\n| Check each target | `python3 scripts\u002Fcheck_missing_localizations.py \u003Cbaseline> \u003Ctarget>` for ALL targets |\n| Add missing keys | Edit target `.strings` files |\n| Verify fixed | Re-run check script for all modified targets |\n| Generate (if changed) | `swiftgen` |\n\n### Scenario 3: Cleanup Only\n\n| Task | Command |\n|------|---------|\n| Preview cleanup | `python3 scripts\u002Fclean_unused_localizations.py --dry-run` |\n| Execute cleanup | `python3 scripts\u002Fclean_unused_localizations.py` |\n| Regenerate | `swiftgen` |\n\n## Common Mistakes\n\n| Mistake | Fix | Scenario |\n|---------|-----|----------|\n| Running swiftgen before syncing ALL translations | Always complete ALL target language translations before SwiftGen | 1 |\n| Skipping verification step | Always run check script after ALL target translations to confirm ALL languages aligned | 1 |\n| Only verifying some target languages | Check EVERY target language against baseline before SwiftGen | 1, 2 |\n| Using string interpolation on format functions | Call as function: `L10n.Xxx.func(arg1, arg2)` | 1 |\n| Translating placeholders like %@ | Preserve placeholders exactly: `%@`, `%d`, etc. | 1, 2, 3, 4 |\n| Naming keys starting with numbers | Keys must start with letters: `secure3d` not `3dsecure` | 1, 4 |\n| Skipping final phase for \"later\" | SwiftGen MUST run after all changes or code won't compile | 1, 2, 3 |\n| Cleanup without --dry-run first | Always preview what will be deleted before actual cleanup | 3 |\n| Forgetting SwiftGen after cleanup | Must regenerate code after removing unused keys | 3 |\n\n## Key Rules\n\n### 0. Multi-Language Workflow (CRITICAL)\n\n**For projects with multiple target languages:**\n\n- **Sequential completion:** Finish ONE target language completely before starting the next\n- **Baseline as source:** Always copy keys from baseline, never between target languages\n- **Verify ALL languages:** Every target language must be checked against baseline before SwiftGen\n\n**Workflow:** `Baseline → Target1 → Target2 → ... → TargetN → Verify ALL → SwiftGen (once)`\n\n### 1. Localization Key Naming\n\n**Core requirements:**\n- Domain-like naming with hierarchical structure\n- **All lowercase** letters, numbers (after first character), and dots (.)\n- **CRITICAL**: Each segment MUST start with a **letter** (a-z), NOT a number\n- Use descriptive, domain-based names for clarity\n\n**Examples:**\n```\n✅ common.ok\n✅ market.header.name\n✅ trade.confirm.title\n✅ futuresrecords.header.amount_usdt\n\n❌ symboldetail.24h.high (number in middle) → Use symboldetail.daily.high\n❌ 2fa.enabled (starts with number) → Use twofa.enabled\n```\n\n### 2. L10n Code Reference Transformation\n\n**SwiftGen auto-transforms keys to code references:**\n\n- **All levels except last**: Title Case (capitalize first letter only)\n- **Last level**:\n  - Contains underscores (`snake_case`) → convert to `camelCase`\n  - Single lowercase word → keep as-is\n  - Compound words without underscores → stay lowercase\n\n**Examples:**\n| Localization Key | L10n Reference | Notes |\n|-----------------|----------------|-------|\n| `common.ok` | `L10n.Common.ok` | Single level |\n| `market.header.name` | `L10n.Market.Header.name` | All Title Case |\n| `futuresrecords.header.amount_usdt` | `L10n.Futuresrecords.Header.amountUsdt` | Last: snake_case → camelCase |\n| `paybridge.error.missingproductid` | `L10n.Paybridge.Error.missingproductid` | Compound stays lowercase |\n| `challenge.status.inprogress.full` | `L10n.Challenge.Status.Inprogress.full` | inprogress → Inprogress |\n\n### 3. Format Strings (with Parameters)\n\n**When localization strings contain format specifiers** (`%@`, `%d`, `%f`, etc.), SwiftGen generates a **FUNCTION**, not a static property.\n\n**Format specifier examples:**\n- `%@` - Any object (String, etc.)\n- `%d` \u002F `%i` - Integer\n- `%f` - Float\u002FDouble\n- `%.2f` - Formatted float\n- `%%` - Literal percent (does NOT create parameter)\n\n**Usage examples:**\n```swift\n\u002F\u002F Static property (no format specifiers)\nbutton.setTitle(L10n.Common.ok, for: .normal)\n\n\u002F\u002F Function call (with format specifiers)\nlabel.text = L10n.Challenge.Progress.stage(phaseText, statusText)\nlabel.text = L10n.Futurestrading.Orderbook.fundingrate(8)\n```\n\n**For detailed examples, troubleshooting, and migration guide:** See [references\u002Fnaming-conventions.md](references\u002Fnaming-conventions.md)\n\n## Helper Scripts\n\nLocated in `scripts\u002F` directory. For detailed usage, see [scripts\u002FREADME.md](scripts\u002FREADME.md).\n\n| Script | Purpose | Command |\n|--------|---------|---------|\n| `check_missing_localizations.py` | Compare files for missing keys | `python3 scripts\u002Fcheck_missing_localizations.py \u003Cbaseline> \u003Ctarget>` |\n| `clean_unused_localizations.py` | Find\u002Fremove unused entries | `python3 scripts\u002Fclean_unused_localizations.py --dry-run` |\n\n## Important Constraints\n\n**For ALL phases:**\n- Only add\u002Fmodify missing or outdated keys identified by scripts or requirements\n- Do NOT edit existing, correct keys and values\n- Preserve file structure, MARK comments, and formatting\n- Maintain alphabetical or logical grouping\n- Only modify the specific language file for that phase\n\n## Best Practices\n\n### For All Scenarios\n- Always verify with scripts before assuming completeness\n- Run SwiftGen after any localization file changes\n- Test translations in actual app context\n\n### For Scenario 1 (Full Workflow)\n- Start with baseline phase first\n- **Complete ALL target language translations before running verification**\n- **Verify EVERY target language against baseline before SwiftGen**\n- Complete each phase fully before next\n\n### For Scenario 2 (Check Missing)\n- Check ALL target languages, not just one\n- Re-run verification after adding missing keys\n- Run SwiftGen if any keys were added\n\n### For Scenario 3 (Cleanup)\n- Always use --dry-run first\n- Review the cleanup report before confirming\n- Clean periodically (e.g., before releases)\n- Keep backup files until verified in app\n\n## Requirements\n\n- Python 3.x\n- SwiftGen (`brew install swiftgen`)\n- iOS project using SwiftGen for localization\n- Access to `*.lproj\u002FLocalizable.strings` files\n\n## Advanced Usage\n\nFor CI\u002FCD integration, automated translation, and performance optimization, see [references\u002Fadvanced-usage.md](references\u002Fadvanced-usage.md).\n","# iOS Internationalization Workflow\n\nComplete workflow for managing iOS app internationalization (i18n) using SwiftGen L10n code generation. Supports any number of target languages. Covers three main scenarios: internationalizing code, verifying translation completeness, and cleaning unused entries.\n\n## When to Use\n\n```dot\ndigraph when_to_use {\n    rankdir=TB;\n    \"User provides code\u002Ffolder for i18n?\" [shape=diamond, style=filled, fillcolor=lightblue];\n    \"User asks to check missing translations?\" [shape=diamond, style=filled, fillcolor=lightgreen];\n    \"User asks to clean unused i18n?\" [shape=diamond, style=filled, fillcolor=lightyellow];\n    \"Standardize\" [shape=box, style=filled, fillcolor=lightcoral];\n    \"CheckMissing\" [shape=box, style=filled, fillcolor=lightcoral];\n    \"CleanUp\" [shape=box, style=filled, fillcolor=lightcoral];\n\n    \"User provides code\u002Ffolder for i18n?\" -> \"Standardize\" [label=\"Yes\\n(Full workflow)\"];\n    \"User asks to check missing translations?\" -> \"CheckMissing\" [label=\"Yes\\n(Verify only)\"];\n    \"User asks to clean unused i18n?\" -> \"CleanUp\" [label=\"Yes\\n(Cleanup only)\"];\n}\n```\n\n**Three main scenarios:**\n\n1. **Internationalize code** - User provides code or folder: \"Here's my view controller, add i18n\"\n   → Run full workflow (baseline → ALL target languages → verify → SwiftGen)\n\n2. **Check missing translations** - User explicitly asks: \"Check if translations are complete\" or \"Find missing i18n keys\"\n   → Run check_missing_localizations.py for each target language and fill gaps\n\n3. **Clean unused entries** - User explicitly asks: \"Clean unused localizations\" or \"Remove unused i18n keys\"\n   → Run clean_unused_localizations.py with dry-run first\n\n**Key principle:** Complete translations for ALL target languages before verification and SwiftGen generation.\n\n**Do NOT use when:**\n- Projects using raw NSLocalizedString without SwiftGen\n- Non-iOS platforms (Android, Web)\n\n## Identifying User Intent\n\n**Determining which scenario applies:**\n\n### Scenario 1: Full Workflow\nUser provides code files or folder paths, says things like \"internationalize this\" or \"add i18n to this code\"\n\n### Scenario 2: Check Missing\nUser asks to verify translation completeness with phrases like \"check if translations complete\" or \"find missing i18n keys\"\n\n### Scenario 3: Cleanup\nUser requests removal of unused entries with phrases like \"clean unused localizations\" or \"remove unused i18n keys\"\n\n**Quick decision guide:**\n- Provides code\u002Ffolder → **Scenario 1** (Full workflow)\n- Asks to check\u002Fverify → **Scenario 2** (Check missing)\n- Asks to clean\u002Fremove → **Scenario 3** (Cleanup)\n\n## Red Flags - STOP and Re-read\n\n**For Scenario 1 (Full internationalization):**\n- \"I'll just run swiftgen real quick\"\n- \"The translations can wait\"\n- \"I'll add the keys manually\"\n- \"This phase doesn't apply to my case\"\n- \"I can skip phase 4 and run it later\"\n- \"No need to verify with scripts, trust me\"\n\n**For Scenario 2 (Check missing):**\n- \"I can just eyeball the files\"\n- \"Checking one target language is enough\"\n- \"I'll add keys later\"\n- \"The other languages look fine\"\n\n**For Scenario 3 (Cleanup):**\n- \"Just delete everything without checking\"\n- \"No need for --dry-run first\"\n\n**All of these mean: Read the skill again and follow the correct workflow.**\n\n## Configuration\n\n**Project-specific variables:**\n```yaml\nproject_root: \"\u002Fpath\u002Fto\u002Fyour\u002FiOS\u002Fproject\"\nlocalization_dir: \"*\u002FLocalization\"\nbaseline_language: \"zh-Hans\"  # Source of truth (can be any language)\ntarget_languages: [\"zh-Hant\", \"en\", \"ja\", \"ko\", \"de\"]  # ALL target languages\ngenerated_file: \"Generated\u002FStrings.swift\"\n```\n\n**Default structure:**\n```\n\u003CProjectRoot>\u002Fpath\u002F\u003Clocalization_dir>\u002F\n├── zh-Hans.lproj\u002FLocalizable.strings  # Baseline (source of truth)\n├── zh-Hant.lproj\u002FLocalizable.strings  # Target 1\n├── en.lproj\u002FLocalizable.strings       # Target 2\n└── ja.lproj\u002FLocalizable.strings       # Target 3 (add more as needed)\n```\n\n**Note:** The baseline language can be any language (zh-Hans, en, ja, etc.). Choose the language you work with most frequently as baseline.\n\n## Scenario 1: Full Internationalization Workflow\n\n**Use when:** User provides code\u002Ffolder for internationalization\n\n**Flow:** Sequential phases with iterative target language processing\n\n```\nPhase 1: Baseline → Phase 2+: Target Languages (repeat for ALL) → Verification → SwiftGen\n```\n\n**Critical:**\n- Complete ALL target language translations sequentially before verification\n- Verification step must confirm ALL languages aligned before SwiftGen\n- If missing keys found, return to incomplete target language phase\n\n### Phase 1: Baseline Localization\n\nUpdate baseline language file and replace hardcoded strings with L10n references.\n\n1. Extract hardcoded strings from Swift\u002FObjC files\n2. Add new\u002Fmodified strings to baseline file following naming conventions\n3. Replace strings with `L10n.xxx` calls\n\n**Completion:** Baseline updated and code references replaced.\n\n### Phase 2+: Target Language Translations (Repeat for ALL Target Languages)\n\n**For EACH target language in your configuration:**\n\n1. **Identify new keys from Phase 1** - Review the keys added to baseline file\n2. **Translate each new key** from baseline language to this target language\n3. **Add translations** to this target language's `.strings` file following the same structure\n\n**Process:**\n- Complete ONE target language fully before moving to the next\n- Copy new\u002Fmodified keys from Phase 1 baseline\n- Translate values (not keys) to target language\n- Maintain same key names and structure as baseline\n- Preserve placeholders like `%@`, `%d`, etc.\n\n### Verification Step (CRITICAL)\n\n**After completing ALL target language translations, verify alignment:**\n\nThis step confirms ALL translations are complete and aligned with baseline.\n\n```bash\n# Check each target language against baseline\nfor target_lang in \"${target_languages[@]}\"; do\n  python3 \u003Cskill_path>\u002Fscripts\u002Fcheck_missing_localizations.py \\\n    \u003Clocalization_dir>\u002F\u003Cbaseline_lang>.lproj\u002FLocalizable.strings \\\n    \u003Clocalization_dir>\u002F${target_lang}.lproj\u002FLocalizable.strings\ndone\n```\n\n**Example:** `python3 scripts\u002Fcheck_missing_localizations.py Localization\u002Fzh-Hans.lproj\u002FLocalizable.strings Localization\u002Fen.lproj\u002FLocalizable.strings`\n\n**Expected output for EACH language:** `✅ [target] 文件没有缺失的键。`\n\n**If missing keys found:** Return to the incomplete target language phase and add missing translations.\n\n**Only proceed to Final Phase after verification confirms ALL languages aligned.**\n\n### Final Phase: Generate Swift Code\n\n**Critical:** Run after ALL changes and verification.\n\n```bash\ncd \u003Cproject_root>\nswiftgen\n```\n\n**Completion:** Code generated with all L10n references available for ALL languages.\n\n## Scenario 2: Check Missing Translations\n\n**Use when:** User explicitly asks \"Check if translations are complete\" or \"Find missing i18n keys\"\n\n### Workflow\n\n1. **Identify baseline language** (usually zh-Hans or en)\n2. **Check EACH target language** against baseline:\n\n```bash\npython3 \u003Cskill_path>\u002Fscripts\u002Fcheck_missing_localizations.py \\\n  \u003Clocalization_dir>\u002F\u003Cbaseline_lang>.lproj\u002FLocalizable.strings \\\n  \u003Clocalization_dir>\u002F\u003Ctarget_lang>.lproj\u002FLocalizable.strings\n```\n\nRepeat for ALL target languages.\n\n3. **Review reports** - Each check shows missing keys for that target language\n4. **Add missing translations** to each target language file\n5. **Re-run verification** for all modified languages to confirm all aligned\n6. **Run SwiftGen** if any translations were added\n\n**Completion:** ALL target languages have complete translations matching baseline.\n\n## Scenario 3: Clean Unused Localizations\n\n**Use when:** User explicitly asks \"Clean unused localizations\" or \"Remove unused i18n keys\"\n\n### Workflow\n\n1. **Dry-run first** (see what would be deleted):\n\n```bash\ncd \u003Cproject_root>\npython3 \u003Cskill_path>\u002Fscripts\u002Fclean_unused_localizations.py --dry-run\n```\n\n2. **Review the report** - Shows unused entries and usage statistics\n3. **Run actual cleanup** (after confirmation):\n\n```bash\npython3 \u003Cskill_path>\u002Fscripts\u002Fclean_unused_localizations.py\n```\n\n4. **Run SwiftGen** to regenerate code:\n\n```bash\nswiftgen\n```\n\n**Safety:**\n- Script creates `.backup` file before deletion\n- Prompts for confirmation before deleting\n- Requires explicit user confirmation\n\n**Completion:** Unused entries removed, SwiftGen regenerated.\n\n## Quick Reference\n\n### Scenario 1: Full Internationalization\n\n| Task | Command\u002FApproach | Phase |\n|------|------------------|-------|\n| Extract hardcoded strings | Manual review of provided code | 1 (Baseline) |\n| Add keys to baseline | Edit baseline `.strings` file | 1 |\n| Replace with L10n | `L10n.Module.key` syntax | 1 |\n| Translate to ALL targets | Copy keys from baseline, translate values sequentially | 2+ |\n| Verify alignment | `python3 scripts\u002Fcheck_missing_localizations.py \u003Cbaseline> \u003Ctarget>` for EACH target | After ALL translations |\n| Generate Swift code | `swiftgen` | Final |\n\n### Scenario 2: Check Missing Only\n\n| Task | Command |\n|------|---------|\n| Check each target | `python3 scripts\u002Fcheck_missing_localizations.py \u003Cbaseline> \u003Ctarget>` for ALL targets |\n| Add missing keys | Edit target `.strings` files |\n| Verify fixed | Re-run check script for all modified targets |\n| Generate (if changed) | `swiftgen` |\n\n### Scenario 3: Cleanup Only\n\n| Task | Command |\n|------|---------|\n| Preview cleanup | `python3 scripts\u002Fclean_unused_localizations.py --dry-run` |\n| Execute cleanup | `python3 scripts\u002Fclean_unused_localizations.py` |\n| Regenerate | `swiftgen` |\n\n## Common Mistakes\n\n| Mistake | Fix | Scenario |\n|---------|-----|----------|\n| Running swiftgen before syncing ALL translations | Always complete ALL target language translations before SwiftGen | 1 |\n| Skipping verification step | Always run check script after ALL target translations to confirm ALL languages aligned | 1 |\n| Only verifying some target languages | Check EVERY target language against baseline before SwiftGen | 1, 2 |\n| Using string interpolation on format functions | Call as function: `L10n.Xxx.func(arg1, arg2)` | 1 |\n| Translating placeholders like %@ | Preserve placeholders exactly: `%@`, `%d`, etc. | 1, 2, 3, 4 |\n| Naming keys starting with numbers | Keys must start with letters: `secure3d` not `3dsecure` | 1, 4 |\n| Skipping final phase for \"later\" | SwiftGen MUST run after all changes or code won't compile | 1, 2, 3 |\n| Cleanup without --dry-run first | Always preview what will be deleted before actual cleanup | 3 |\n| Forgetting SwiftGen after cleanup | Must regenerate code after removing unused keys | 3 |\n\n## Key Rules\n\n### 0. Multi-Language Workflow (CRITICAL)\n\n**For projects with multiple target languages:**\n\n- **Sequential completion:** Finish ONE target language completely before starting the next\n- **Baseline as source:** Always copy keys from baseline, never between target languages\n- **Verify ALL languages:** Every target language must be checked against baseline before SwiftGen\n\n**Workflow:** `Baseline → Target1 → Target2 → ... → TargetN → Verify ALL → SwiftGen (once)`\n\n### 1. Localization Key Naming\n\n**Core requirements:**\n- Domain-like naming with hierarchical structure\n- **All lowercase** letters, numbers (after first character), and dots (.)\n- **CRITICAL**: Each segment MUST start with a **letter** (a-z), NOT a number\n- Use descriptive, domain-based names for clarity\n\n**Examples:**\n```\n✅ common.ok\n✅ market.header.name\n✅ trade.confirm.title\n✅ futuresrecords.header.amount_usdt\n\n❌ symboldetail.24h.high (number in middle) → Use symboldetail.daily.high\n❌ 2fa.enabled (starts with number) → Use twofa.enabled\n```\n\n### 2. L10n Code Reference Transformation\n\n**SwiftGen auto-transforms keys to code references:**\n\n- **All levels except last**: Title Case (capitalize first letter only)\n- **Last level**:\n  - Contains underscores (`snake_case`) → convert to `camelCase`\n  - Single lowercase word → keep as-is\n  - Compound words without underscores → stay lowercase\n\n**Examples:**\n| Localization Key | L10n Reference | Notes |\n|-----------------|----------------|-------|\n| `common.ok` | `L10n.Common.ok` | Single level |\n| `market.header.name` | `L10n.Market.Header.name` | All Title Case |\n| `futuresrecords.header.amount_usdt` | `L10n.Futuresrecords.Header.amountUsdt` | Last: snake_case → camelCase |\n| `paybridge.error.missingproductid` | `L10n.Paybridge.Error.missingproductid` | Compound stays lowercase |\n| `challenge.status.inprogress.full` | `L10n.Challenge.Status.Inprogress.full` | inprogress → Inprogress |\n\n### 3. Format Strings (with Parameters)\n\n**When localization strings contain format specifiers** (`%@`, `%d`, `%f`, etc.), SwiftGen generates a **FUNCTION**, not a static property.\n\n**Format specifier examples:**\n- `%@` - Any object (String, etc.)\n- `%d` \u002F `%i` - Integer\n- `%f` - Float\u002FDouble\n- `%.2f` - Formatted float\n- `%%` - Literal percent (does NOT create parameter)\n\n**Usage examples:**\n```swift\n\u002F\u002F Static property (no format specifiers)\nbutton.setTitle(L10n.Common.ok, for: .normal)\n\n\u002F\u002F Function call (with format specifiers)\nlabel.text = L10n.Challenge.Progress.stage(phaseText, statusText)\nlabel.text = L10n.Futurestrading.Orderbook.fundingrate(8)\n```\n\n**For detailed examples, troubleshooting, and migration guide:** See [references\u002Fnaming-conventions.md](references\u002Fnaming-conventions.md)\n\n## Helper Scripts\n\nLocated in `scripts\u002F` directory. For detailed usage, see [scripts\u002FREADME.md](scripts\u002FREADME.md).\n\n| Script | Purpose | Command |\n|--------|---------|---------|\n| `check_missing_localizations.py` | Compare files for missing keys | `python3 scripts\u002Fcheck_missing_localizations.py \u003Cbaseline> \u003Ctarget>` |\n| `clean_unused_localizations.py` | Find\u002Fremove unused entries | `python3 scripts\u002Fclean_unused_localizations.py --dry-run` |\n\n## Important Constraints\n\n**For ALL phases:**\n- Only add\u002Fmodify missing or outdated keys identified by scripts or requirements\n- Do NOT edit existing, correct keys and values\n- Preserve file structure, MARK comments, and formatting\n- Maintain alphabetical or logical grouping\n- Only modify the specific language file for that phase\n\n## Best Practices\n\n### For All Scenarios\n- Always verify with scripts before assuming completeness\n- Run SwiftGen after any localization file changes\n- Test translations in actual app context\n\n### For Scenario 1 (Full Workflow)\n- Start with baseline phase first\n- **Complete ALL target language translations before running verification**\n- **Verify EVERY target language against baseline before SwiftGen**\n- Complete each phase fully before next\n\n### For Scenario 2 (Check Missing)\n- Check ALL target languages, not just one\n- Re-run verification after adding missing keys\n- Run SwiftGen if any keys were added\n\n### For Scenario 3 (Cleanup)\n- Always use --dry-run first\n- Review the cleanup report before confirming\n- Clean periodically (e.g., before releases)\n- Keep backup files until verified in app\n\n## Requirements\n\n- Python 3.x\n- SwiftGen (`brew install swiftgen`)\n- iOS project using SwiftGen for localization\n- Access to `*.lproj\u002FLocalizable.strings` files\n\n## Advanced Usage\n\nFor CI\u002FCD integration, automated translation, and performance optimization, see [references\u002Fadvanced-usage.md](references\u002Fadvanced-usage.md).\n",{"name":5,"description":7},"master","a12b4ddfc807225744ed4ddecc493e87048dca69","skills\u002Fios-i18n-workflow",0,"https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin","https:\u002F\u002Fgithub.com\u002FHeathWang","iOS \u002F front end \u002F python develper","2026-11-03 17:20:23",{"source":8,"skillName":5,"commands":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add HeathWang\u002Fhw-cc-plugin --skill ios-i18n-workflow",{"tool":50,"command":51},"bunx","bunx skills add HeathWang\u002Fhw-cc-plugin --skill ios-i18n-workflow",{"tool":53,"command":54},"pnpm","pnpm dlx skills add HeathWang\u002Fhw-cc-plugin --skill ios-i18n-workflow","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002FSKILL.md",true,[58,64,68,74,78],{"path":59,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":62,"sourceHtmlUrl":63},"references\u002Fadvanced-usage.md","REFERENCE","参考文档",6391,"https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002Freferences\u002Fadvanced-usage.md",{"path":65,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":66,"sourceHtmlUrl":67},"references\u002Fnaming-conventions.md",9065,"https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002Freferences\u002Fnaming-conventions.md",{"path":69,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":72,"sourceHtmlUrl":73},"scripts\u002Fcheck_missing_localizations.py","SCRIPT","脚本",5861,"https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002Fscripts\u002Fcheck_missing_localizations.py",{"path":75,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":76,"sourceHtmlUrl":77},"scripts\u002Fclean_unused_localizations.py",20611,"https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002Fscripts\u002Fclean_unused_localizations.py",{"path":79,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":80,"sourceHtmlUrl":81},"scripts\u002FREADME.md",2964,"https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fios-i18n-workflow\u002Fscripts\u002FREADME.md",[83,114,135,145,157,180],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":94,"publishedAt":31},"01M6CFBEFHMPFRFM9AQAJVVAR0","reconstructing-ui-from-screenshots","Use when implementing or correcting an app or web UI from a design image, screenshot, mockup, or reference PNG where accurate size, spacing, color, typography, assets, and alignment matter.","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Freconstructing-ui-from-screenshots\u002FSKILL.md",[89],{"categoryNo":90,"categoryName":91,"taxonomyType":92,"taxonomyTypeDesc":93},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,29,111,112,113],"ui","reconstructing ui from screenshots","screenshots","spacing","size","web ui","implementing","color","app","png","typography","mockup","reference","alignment","screenshot","design","image","web","assets",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":118,"categories":119,"keywords":120,"publishedAt":31},"01M6CFBBT8EXTSBHXEFGRWRZ3C","question-answer","Use when the user wants a read-only explanation of existing code behavior, architecture, control flow, data flow, dependencies, or implementation decisions and has not requested project changes.","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fquestion-answer\u002FSKILL.md",[],[121,122,123,29,124,125,126,127,128,129,130,131,132,133,134],"question","question answer","only","decisions","code","architecture","webfetch","behavior","read","grep","flow","data","implementation","user",{"skillNo":136,"name":137,"nameZh":6,"description":138,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":139,"categories":140,"keywords":141,"publishedAt":31},"01M6CFB60X8Q9479W73SJCDEVJ","java-to-swift","Use when converting Java 1.8 classes to Swift 5.0+ Codable structs - handling type mapping, nullability, inheritance flattening, BaseReq exclusions, and property naming conventions.","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fjava-to-swift\u002FSKILL.md",[],[142,143,144,130,129,29],"swift","java","java to swift",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":151,"publishedAt":31},"01M6CFB3DMRW02HSYWMMK3VDPM","java-to-nextjs","Use when converting Java 1.8 classes to Next.js TypeScript interface definitions - handling type mapping, nullability, inheritance, naming conventions, and BaseReq\u002FBaseResponse exclusions.","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fjava-to-nextjs\u002FSKILL.md",[],[143,152,153,154,130,155,129,156,29],"java to nextjs","nextjs","js","typescript","Next.js",{"skillNo":158,"name":159,"nameZh":6,"description":160,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":161,"categories":162,"keywords":166,"publishedAt":31},"01M6CFAXJJZ59SWHZ1RAGQ461N","improve-codebase-architecture","Use when the user wants architectural deepening opportunities for a codebase or named files, shown as a visual HTML report, and when they then pick candidates from that report to implement in the code already reviewed.","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fimprove-codebase-architecture\u002FSKILL.md",[163],{"categoryNo":164,"categoryName":165,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[167,126,168,169,170,171,172,173,174,134,175,125,176,29,177,178,179],"codebase","improve","improve codebase architecture","html","html report","pick","report","as","implement","visual","files","true","for",{"skillNo":181,"name":182,"nameZh":6,"description":183,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":184,"categories":185,"keywords":186,"publishedAt":31},"01M6CFATZXZK0RNE86AEN4AAH3","handoff","Use when the user asks to create a handoff, session summary, context compact, continuation note, 交接文档, 压缩上下文, or instructions for the next agent to resume work later.","https:\u002F\u002Fgithub.com\u002FHeathWang\u002Fhw-cc-plugin\u002Fblob\u002Fmaster\u002Fskills\u002Fhandoff\u002FSKILL.md",[],[182,187,188,134,189,190,191,28,192,193,29,194,195],"instructions","context","压缩","文档","later","create","resume","session","session summary"]