360 Secure SkillHub
360 安全技能中心

I18n Swift

核心功能:提供Swift应用国际化全套规范,包括String(localized:)用法、domain.feature.key语义化键命名、Localizable.strings组织方式,还有最佳实践、坑点规避及测试方案。典型场景:给SwiftUI视图加本地化文本、创建新本地化键、整理字符串文件、评审项目国际化实现。输出规范代码示例、文件模板与测试代码,助力高效适配多语言。

soponcd
soponcd
热度 42.25
最近更新 2026-05-11 17:36:23
分类:开发依赖:纯提示词应用场景:代码生成 / 代码审查 / 概念解释 / 教学辅导

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add i18n-swift
Metadata
name
i18n-swift
description
Swift internationalization patterns, String(localized:) usage, and semantic key naming for macOS/iOS apps
domain
ios-macos
homepage
https://github.com/soponcd/timeflow-skills/tree/main/teams/skills/i18n-swift
metadata
{"clawdbot":{"emoji":"🌐"}}

Swift Internationalization

Expert-level Swift i18n patterns for macOS/iOS applications. Covers string localization, semantic key naming, and best practices.

When: to Use

Use this skill when:

  • Adding localized strings to SwiftUI views
  • Creating new localization keys
  • Writing String(localized:) calls
  • Organizing Localizable.strings files
  • Reviewing i18n implementation in Swift projects

Core Principles

1. String(localized:) Pattern

// Always use String(localized:) for user-facing text
Text(String(localized: "common.save"))
Button(String(localized: "sidebar.today"))

// Never hardcode strings
Text("Save")  // ❌ Wrong

2. Semantic Key Naming

Use domain.feature.key pattern:

// Good: Semantic keys
"app.name" = "TimeFlow"
"common.save" = "Save"
"sidebar.today" = "Today"
"settings.theme.title" = "Theme"

// Bad: Non-semantic keys
"saveButton" = "Save"
"viewTitle1" = "Today"
"themeTitle" = "Theme"

3. Localizable.strings Organization

Group by domain with MARK comments:

/*
 Localizable.strings
 TimeFlow
*/

// MARK: - App
"app.name" = "TimeFlow";

// MARK: - Common
"common.delete" = "Delete";
"common.save" = "Save";
"common.cancel" = "Cancel";

// MARK: - Sidebar
"sidebar.today" = "Today";
"sidebar.settings" = "Settings";
"sidebar.daily_note" = "Daily Note";

// MARK: - GTD Navigation
"gtd.inbox" = "Inbox";
"gtd.today" = "Today";
"gtd.projects" = "Projects";

Key Naming Conventions

Domain Feature Examples
app - app.name
common delete, save, cancel common.delete, common.save
sidebar today, settings, search sidebar.today, sidebar.settings
`home`` today, progress, timeline home.today, home.progress
gtd inbox, next, projects gtd.inbox, gtd.next
settings theme, language, sync settings.theme.title
sync idle, syncing, failed sync.idle, sync.syncing

SwiftUI Usage Patterns

Text Component

struct TodayView: View {
    var body: some View {
        VStack {
            Text(String(localized: "home.today"))
                .font(.title)

            Text(String(localized: "home.no_events"))
                .foregroundStyle(.secondary)
        }
    }
}

Button with Localized String

Button(String(localized: "common.save")) {
    // Save action
}
.disabled(isSaving)

Navigation Titles

NavigationLink(destination: SettingsView()) {
    Label(String(localized: "sidebar.settings"), systemImage: .gear)
}

Best Practices

Practice Reason
Use String(localized:) Prevents hardcoding, enables i18n
Semantic key names Self-documenting, easier maintenance
Group with // MARK: Organized, searchable strings files
Use domain.feature.key Clear ownership, prevents collisions
Update all languages together Prevents missing translations
Avoid format strings in keys Use Swift interpolation instead

String Interpolation

// Good: Use Swift interpolation
let message = String(localized: "sync.completed.count")
    .replacingOccurrences(of: "{count}", with: "\(count)")

// Alternative: Use String(format:) for localized format strings
let formatted = String(
    localized: "sync.completed.count",
    comment: "Number of items synced"
)

// Localizable.strings entry:
// "sync.completed.count" = "Synced %d items";

Common Pitfalls

Pitfall Consequence Prevention
Hardcoded strings Can't localize Always use String(localized:)
Non-semantic keys Difficult to maintain Use domain.feature.key pattern
Missing translations Shows key name Add entries to all .strings files
Format strings in keys Ambiguous values Use Swift interpolation
Duplicate keys Confusing maintenance Search before adding

Testing Patterns

func testLocalizationKeys() {
    // Verify all keys exist in Localizable.strings
    let keys = ["app.name", "common.save", "sidebar.today"]
    for key in keys {
        let localized = String(localized: key)
        XCTAssertNotEqual(localized, key, "Key not found: \(key)")
    }
}

Running Tests

# Test localization
xcodebuild test -scheme YourApp \
  -destination 'platform=macOS' \
  -only-testing:'YourAppTests/LocalizationTests/testKeysExist'