From apple-dev-skills
Default localization scope AND execution playbook for Apple-platform Apps — 7 locales (en, zh-Hant, zh-Hans, ja, ko, es, th) translated via AI agent flow using `Localizable.xcstrings`. Source = en, primary = zh-Hant. Minimum set zh-Hant + en. Invoke when (1) deciding L10n scope / catalog format / translation flow at project setup, OR (2) actually executing a translation pass to add or refresh strings.
How this skill is triggered — by the user, by Claude, or both
Slash command
/apple-dev-skills:ai-translated-localizationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Scope decisions:**
Scope decisions:
.strings vs .xcstrings).Execution:
extractionState: stale entries in xcstrings).<TRANSLATE> placeholders shipping).| Locale | Code | Notes |
|---|---|---|
| English | en | Catalog sourceLanguage; translation source for the fan-out |
| Traditional Chinese | zh-Hant | Primary language — author-written alongside en, never AI-translated |
| Japanese | ja | Largest adjacent market outside the Chinese sphere |
| Simplified Chinese | zh-Hans | Converted from zh-Hant + Mainland phrasing review |
| Spanish | es | World's second largest native-speaker base |
| Thai | th | Southeast Asia representative |
| Korean | ko | High-penetration Asian market |
zh-Hant / zh-Hans), not region
forms (zh-TW / zh-CN) — matches the committed catalogs and your repo's L10n completeness gate.plan.md: "author en + zh-Hant by hand, fan out the other 5 locales from en, write into Localizable.xcstrings" (see Execution playbook Step 1).Localizable.xcstrings (String Catalog, introduced in Xcode 15+)..strings / .stringsdict (unless an external tool forces it).zh-Hant as primary reflects the author's native-language accuracy; en is the
fan-out source because translator competence is broader from English (see Field notes).extractionState: stale for later.plan.md.Use when actually performing a translation pass. The flow is source-pair seed → AI fan-out → tricky-case review → completeness check.
en.en + zh-Hant populated and extractionState: manual.ja, zh-Hans, es, th, ko) start either absent or with the placeholder string <TRANSLATE> so the fan-out pass can find them with a single grep.For each target locale, translate each key from en (source-of-truth) into the target locale. The AI doing the translation should:
%@, %lld, %1$@, \n, markdown markers (**, _), and any ${...} interpolation tokens are copied verbatim.en, all forms must exist in the target locale (zero / one / two / few / many / other) per CLDR plural categories for that locale — don't blindly copy English's two forms.en's tone. Buttons are imperative, descriptions are neutral, error messages are direct. Don't add politeness markers absent in source (see locale gotchas below).After translation, set extractionState: translated (per Apple xcstrings convention) so Xcode no longer flags the key as needing attention.
Lessons captured from real translation passes. Apply these as a second-pass review after the bulk AI fan-out.
Japanese (ja):
です / ます) in button labels and short UI strings — Japanese app UIs are typically declarative/imperative, not polite.Thai (th):
ครับ / ค่ะ) in UI strings unless the app's voice is deliberately conversational. Calm/neutral apps drop them.Korean (ko):
을/를, 이/가, 은/는.Spanish (es):
es-ES). Avoid vosotros forms; use ustedes.Simplified Chinese (zh-Hans):
zh-Hant (not from en) for terminology consistency; the AI still needs to substitute Mainland-preferred terms (软件 vs 軟體, 移动 vs 行動, 视频 vs 影片).tongwen character conversion — phrase choice differs (e.g., zh-Hant 「設定」 → zh-Hans 「设置」, not 「設定 → 设定」).English (en):
colour, centre, analyse) only if explicitly targeted.Beyond per-string correctness, enforce a project-level glossary so the same concept renders identically across locales and screens:
Maintain the glossary as either inline comments in xcstrings, or a sidecar Localization-Glossary.md in docs/ if it grows.
Verification gates before merging a translation pass:
<TRANSLATE> count across xcstrings = 0 (none shipped).extractionState: stale count = 0 (all stale entries refreshed).localizations dict has every declared locale).en has N %@ → all locales have N %@ (or locale-specific reordering via %1$@ / %2$@).Scheme → Run → Options → App Language.Your repo's L10n completeness gate (CI-enforced) checks per-key locale
completeness: every key present in a catalog has all declared locales, no <TRANSLATE>.
Two things it does NOT catch — both have shipped English-fallback bugs in real projects:
leave.game.close, att.primer.title) referenced from a shared UI module
(SharedUI / SettingsUI / any shared UI module) must exist in every app
catalog or CI fails. Scope it to dotted keys to avoid app-conditional
English-phrase false positives — English-phrase shared keys are a separate,
harder case (no dotted namespace to anchor on; track them with a dedicated
audit rather than this gate).When adding keys to a Localizable.xcstrings, text-splice the new entries
into the file — do not round-trip the whole catalog through a Python/JSON
load → dump. The round-trip reformats Xcode's style ("k" : v space-before-
colon + Xcode key order) and produces a multi-thousand-line noise diff that
buries the real change. Splicing keeps a clean, reviewable diff (real example:
4400-line noise diff collapsed to 192 lines after switching to splice approach).
{"sourceLanguage": "en", "strings": {<key>: {"localizations": {<locale>: {"stringUnit": {"state": "translated", "value": "..."}}}}}}.{"variations": {"plural": {<cldr-form>: {"stringUnit": {...}}}}} instead of a single stringUnit.Localizable.xcstrings exists and each key has 7 locale entries (2 for the minimum set).PrivacyInfo.xcprivacy description itself doesn't need to be multi-locale, but the corresponding App Store privacy policy page does.apple-platform-targets: xcstrings requires Xcode 15+; aligns with the deployment target's toolchain.spec-phase-orchestration: "translation" should be an explicit step in plan.md.Real translation passes have surfaced these recurring decisions:
en, primary = zh-Hant — both written by author. The other 5 fan out from en because translator competence is broader from English than from Chinese for th / ko / es.npx claudepluginhub wei18/apple-dev-skills --plugin apple-dev-skillsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.