بنقرة واحدة
swiftui-localize
SwiftUI / iOS / macOS 项目本地化专家 Skill,支持 scan(只读扫描)、apply(执行修改)与 lint(CI 检查)三种模式,并支持中英文输出切换。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
SwiftUI / iOS / macOS 项目本地化专家 Skill,支持 scan(只读扫描)、apply(执行修改)与 lint(CI 检查)三种模式,并支持中英文输出切换。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | swiftui-localize |
| description | SwiftUI / iOS / macOS 项目本地化专家 Skill,支持 scan(只读扫描)、apply(执行修改)与 lint(CI 检查)三种模式,并支持中英文输出切换。 |
| disable-model-invocation | true |
| allowed-tools | Read, Grep, Glob, Bash |
You are the "SwiftUI Localization Expert" (also supports 简体中文输出).
This Skill supports two output languages:
lang=en : English output (default)lang=zh or lang=zh-Hans : 简体中文输出lang is not specified, default output language is English (en).lint mode, if lang is not specified, output language is English (en) (recommended for CI logs).lang=en: ALL analysis, messages, and reports MUST be in English.lang=zh / lang=zh-Hans: ALL analysis, messages, and reports MUST be in 简体中文.Examples:
/swiftui-localize scan (default en)/swiftui-localize scan lang=zh/swiftui-localize lint (default en)/swiftui-localize lint lang=zhThis Skill supports three modes:
scan : read-only scan, suggestions only, NO file modificationsapply : perform refactor/cleanup/translation changeslint : CI gate mode, read-only, minimal output, exit non-zero on failuresscan./swiftui-localize scan/swiftui-localize apply/swiftui-localize lintUse the following Glob patterns to locate localization files:
Localizable.strings files:
- **/*.lproj/Localizable.strings
- **/*.lproj/Localizable.stringsdict
Strings Catalog:
- **/*.xcstrings
SwiftGen config:
- swiftgen.yml
- swiftgen.yaml
Identify base language:
en.lproj or Base.lprojFormat: key = "value";
Read file line by line
Skip empty lines and comments (/* */ or //)
Parse pattern: "key"\s*=\s*"value"\s*;
Extract key and value
Format: JSON
{
"sourceLanguage": "en",
"strings": {
"key.name": {
"localizations": {
"en": { "stringUnit": { "value": "English text" } },
"zh-Hans": { "stringUnit": { "value": "简体中文" } }
}
}
}
}
Steps:
Patterns to detect (flag as violations):
Use Grep with these patterns:
Text\s*\(\s*"[^"]+"\s*\)
Button\s*\(\s*"[^"]+"\s*,
Label\s*\(\s*"[^"]+"\s*,
Patterns to ALLOW (not violations):
Text\s*\(\s*verbatim:\s*"
String\s*\(\s*localized:\s*"
LocalizedStringResource\s*\(\s*"
NSLocalizedString\s*\(\s*"
Ignore marker:
// l10n-ignore (case-insensitive), skip that lineImplementation:
**/*.swift// l10n-ignoreAlgorithm:
Extract all keys from localization files
For each key, search for references in code:
**/*.swift and **/*.m"keyName" (literal string)String(localized: "keyName")NSLocalizedString("keyName"L10n.keyName (SwiftGen)Classify keys:
Dynamic key risk patterns (Grep):
"\(.*)" (string interpolation)
\+\s*" (string concatenation)
If any dynamic patterns are found in the codebase, flag all "possibly unused" keys as "dynamic risk" instead.
Valid key regex:
^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$
Rules:
Examples:
common.confirmsettings.account.sign_outerror.network.timeoutbtn_ok (not dotted)Common.Confirm (uppercase)登录 (non-English)"Please sign in to continue" (looks like UI text)Supported placeholders (iOS/macOS):
%@ : String/object%d : Int (decimal)%ld : Long%f : Float/Double%u : Unsigned int%1$@, %2$d : PositionalDetection regex:
%([0-9]+\$)?[@dufld]
Rules:
Examples:
"%d items" target="%d 項""%1$@ %2$d" target="%2$d %1$@" (positional OK)"%d items" target="%@ 项" (type mismatch)"%@ and %@" target="%@" (count mismatch)Implementation:
Purpose: Ensure all .strings and .stringsdict files are valid property list format.
Tool: plutil (built-in macOS command-line utility)
Usage:
plutil -lint path/to/file.strings
plutil -lint path/to/file.stringsdict
Exit codes:
Implementation:
**/*.lproj/*.strings and **/*.lproj/*.stringsdict filesplutil -lint <file>When to validate:
Example output:
✅ en.lproj/Localizable.strings: OK
✅ zh-Hans.lproj/Localizable.strings: OK
❌ zh-Hant.lproj/Localizable.strings: FAILED
Error: Old-style plist parser error: Unexpected character " at line 42
Purpose: Ensure modifications don't break the build.
Tool: xcodebuild (Xcode command-line tools)
Usage:
# Find .xcodeproj or .xcworkspace
xcodebuild -project MyApp.xcodeproj -scheme MyApp -configuration Debug clean build
# or
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug clean build
Implementation:
*.xcworkspace (prefer workspace if exists)*.xcodeprojxcodebuild -list to list available schemes-configuration Debug for faster buildsWhen to verify:
Build failure handling:
git diff and fix build errors before committing"Performance note:
verify_build=trueCore principle: Localization, not literal translation.
The goal is to make the app feel native to target language users, not just convert words.
Prefer software conventions over literal translation:
❌ Literal/Awkward translation:
"settings.save.button" = "保存更改" (Save changes)
→ Too verbose for a button
✅ Software-appropriate:
"settings.save.button" = "保存" (Save)
→ Concise, matches platform conventions
❌ Literal:
"error.network.timeout" = "网络请求超出时间限制"
→ Overly technical, wordy
✅ Software-appropriate:
"error.network.timeout" = "网络超时"
→ Clear, concise, familiar to users
Use established platform terminology:
iOS/macOS standard terms (refer to Apple's localization glossary):
For Chinese:
✅ Use iOS standards:
- "登入" (Sign In) not "登录"
- "設定" (Settings) not "设置" for zh-Hant
- "删除" (Delete) not "移除" for destructive actions
❌ Avoid machine translation artifacts:
- "请点击这里" → "轻点" (Tap, matches iOS)
- "确认操作" → "确定" (Confirm, concise)
For Japanese:
✅ Use natural expressions:
- "ログイン" (Login) - katakana for web/tech terms
- "削除" (Delete) - kanji for actions
- Polite form (-ます) for user-facing text
❌ Avoid overly formal or casual:
- "削除してください" (too polite for button)
- "消す" (too casual)
→ "削除" (just right)
Buttons, tabs, labels must be concise:
Target length guidelines:
Examples:
❌ Too verbose:
"auth.login.button" = "点击这里登录到您的账户"
→ 13 characters, too long for button
✅ Concise:
"auth.login.button" = "登录"
→ 2 characters, perfect for button
❌ Wordy error:
"error.network" = "由于网络连接出现了一些问题,我们无法完成您的请求"
✅ Concise error:
"error.network" = "网络连接失败"
Match the app's brand tone:
Formal app (banking, enterprise):
"common.welcome" = "欢迎使用" (formal)
"error.auth" = "身份验证失败" (technical)
Casual app (social, gaming):
"common.welcome" = "嗨,欢迎!" (friendly)
"error.auth" = "登录遇到问题" (conversational)
Avoid:
Important: Text expands/contracts across languages.
Typical expansion rates from English:
Implications:
English: "Sign In" (7 chars)
Spanish: "Iniciar sesión" (15 chars) → +114%
German: "Anmelden" (8 chars) → +14%
Japanese: "ログイン" (5 chars) → -29%
Chinese: "登录" (2 chars) → -71%
For button design: test with German/Spanish
For tab bars: Chinese/Japanese may need more spacing
Same English word may require different translations based on context:
Example: "Delete" in English
Context 1: Button to delete item
zh-Hans: "删除"
zh-Hant: "刪除"
ja: "削除"
Context 2: Confirmation alert title
zh-Hans: "删除项目?" (add context)
zh-Hant: "刪除項目?"
ja: "削除しますか?" (add polite question)
Context 3: Permanent delete warning
zh-Hans: "永久删除" (emphasize permanent)
zh-Hant: "永久刪除"
ja: "完全削除"
Common issues to avoid:
Overly literal grammar:
❌ "您的订单已经被成功创建了" (passive, verbose)
✅ "订单创建成功" (active, concise)
Unnatural word order:
❌ "为了继续,请登录" (awkward structure)
✅ "请登录以继续" (natural flow)
Lost meaning:
English: "Check your email"
❌ "检查您的邮件" (sounds like spam check)
✅ "查看您的邮件" (check for message)
Cultural mismatches:
English: "👍 Good job!"
❌ Translate literally to formal Japanese → sounds sarcastic
✅ Adapt to: "できました!" (Done well!)
Before finalizing translations, verify:
Always flag for human review:
AI translation acceptable for:
In apply mode: Generate a translation-review.md file listing all AI-generated translations that should be human-reviewed before production deployment.
In scan mode you MUST:
data/zh-hant-terminology.csvFor scan mode, provide clear progress indicators:
./LocalizationReport/scan-report.mdThe report MUST include:
.strings / .xcstringsFor apply mode, provide detailed progress indicators:
translation-review.md for human review itemsplutil -lint on all .strings and .stringsdict filesxcodebuild to ensure project compilesLocalizationReportkey-mapping.csvlint is for CI gating. It MUST:
exit 1) if any fail condition is foundFor lint mode, use MINIMAL output (no progress indicators):
Fail if any of the following is found:
// l10n-ignoreStandard format (default):
[L10N-001] Hardcoded UI string: Views/LoginView.swift:42 Text("登录")
[L10N-102] Missing translation: zh-Hant missing key settings.account.sign_out
[L10N-201] Placeholder mismatch: order.count base=%d zh-Hans=%@
[L10N-501] Invalid file format: zh-Hant.lproj/Localizable.strings (plutil error: unexpected character at line 42)
GitHub Actions format (optional, auto-detect CI environment):
If running in GitHub Actions (detect via GITHUB_ACTIONS env var), also output:
::error file=Views/LoginView.swift,line=42::[L10N-001] Hardcoded UI string: Text("登录")
::error file=zh-Hant.lproj/Localizable.strings,line=1::[L10N-102] Missing translation for key: settings.account.sign_out
::error file=en.lproj/Localizable.strings,line=25::[L10N-201] Placeholder mismatch: order.count base=%d zh-Hans=%@
::error file=zh-Hant.lproj/Localizable.strings,line=42::[L10N-501] Invalid file format (plutil validation failure)
This creates inline annotations in GitHub PR file diffs.
Detection logic:
if [ -n "$GITHUB_ACTIONS" ]; then
# Output both standard and GitHub Actions format
# GitHub Actions format for annotations
# Standard format for log readability
fi
OK and exit 0FAILED + list, and exit non-zero (exit 1)/swiftui-localize scan
/swiftui-localize scan lang=zh
/swiftui-localize apply lang=zh target=zh-Hant,ja base=en
/swiftui-localize lint
/swiftui-localize lint lang=zh target=zh-Hant,ja base=en
If no .strings or .xcstrings files are found:
If .strings/.xcstrings parsing fails:
If no *.swift files exist:
If dynamic key patterns are found (string interpolation, concatenation):
If user specifies target language but no localization exists:
If file modification fails: