Ios Localization

作者 dpearson26998d90fd121a26無授權條款1.1K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫2 個月前更新

Implement, review, or improve localization and internationalization in iOS/macOS apps — String Catalogs (.xcstrings), generated localizable symbols, stable key naming, LocalizedStringKey, LocalizedStringResource, pluralization, FormatStyle for numbers/dates/measurements, right-to-left layout, Dynamic Type, and locale-aware formatting. Use when adding multi-language support, setting up String Catalogs, enabling generated symbols for compile-time-safe localization keys, handling plural forms, formatting dates/numbers/currencies for different locales, testing localizations, or making UI work correctly in RTL languages like Arabic and Hebrew.

AI 產生的概覽

指導 iOS/macOS 應用程式的在地化與國際化,涵蓋字串目錄、地區感知格式化和 RTL 版面配置。

功能
此技能提供在 Apple 平台應用程式中實作、審查與改善在地化的說明。內容涵蓋字串目錄與產生的符號、LocalizedStringKey、String(localized:) 與 LocalizedStringResource 的選擇、複數形式、用於日期、數字、貨幣和度量單位的 FormatStyle,以及由右至左版面配置。它也包含審查清單和常見錯誤指引,並附有兩份參考文件。
適用情境
適用於為 iOS 或 macOS 應用程式加入多語言支援、設定字串目錄、處理複數形式、依地區格式化日期、數字或貨幣,或讓介面在阿拉伯文、希伯來文等 RTL 語言下正確顯示。
執行需求
不含指令碼,僅提供說明和參考文件。需要 Apple 平台開發環境,使用 Xcode 15+(產生符號需 Xcode 26)以及 Swift/SwiftUI 程式碼。

iOS Localization & Internationalization

Localize Apple-platform apps with String Catalogs, modern string types, locale-aware formatting, and right-to-left layout.

Contents

String Catalogs and Generated Symbols

String Catalogs are the recommended Xcode 15+ workflow for new localization work. They keep localizable strings, pluralization rules, and device variations together in an Xcode-managed JSON file with a visual editor. Legacy .strings and .stringsdict files can coexist during migration, but new Swift and SwiftUI code should default to String Catalogs.

How automatic extraction works:

Xcode scans for these patterns on each build:

swift
// SwiftUI -- automatically extracted (LocalizedStringKey)Text("Welcome back")              // key: "Welcome back"Label("Settings", systemImage: "gear")Button("Save") { }Toggle("Dark Mode", isOn: $dark)
// Programmatic -- automatically extractedString(localized: "No items found")LocalizedStringResource("Order placed")
// Plain String: not extracted or localizedlet msg = "Hello"

Xcode adds discovered keys to the String Catalog automatically. Mark translations as Needs Review, Translated, or Stale in the editor.

For detailed String Catalog workflows, migration, and testing strategies, see references/string-catalogs.md [blocked].

Generated symbols are an Xcode 26 typed-access layer on top of String Catalogs; they do not change the catalog's Xcode 15 availability.

Enable: Build Settings > Localization > Generate String Catalog Symbols → Yes (on by default in new Xcode 26 projects). Requires catalog format version 1.1.

Workflow: Add a key manually via the (+) button in the String Catalog editor — manual keys have the Generate Swift Symbol checkbox enabled by default. Auto-extracted keys can also opt in via Refactor > Convert Strings to Symbols. Use stable manual keys for generated-symbol strings. Avoid source-copy-derived keys for API-facing strings because wording edits can rename generated identifiers and churn call sites.

swift
// Generated from key "room_available" in Localizable.xcstringsText(.roomAvailable)
// Parameterized key "landmarks_count" with %1$(count)lldText(.landmarksCount(count: 42))
// Non-default table "Booking.xcstrings"Text(.Booking.confirmBookingCta)

Xcode derives symbol names by camelCasing the key: settings.notifications.toggle → .settingsNotificationsToggle. You can convert existing extracted strings to symbols via Refactor > Convert Strings to Symbols (reversible).

Generated symbols are internal. For cross-module access, create a public wrapper extension. For heavier multi-module setups, use xcstrings-tool instead.

For the full generated symbols reference — extraction states, symbol derivation rules, and cross-module patterns — see references/string-catalogs.md [blocked].

String Types -- Decision Guide

ContextTypeWhy
SwiftUI view textLocalizedStringKey (implicit)SwiftUI performs lookup
View models, services, and errorsString(localized:)Resolves to String now
App Intents, widgets, deferred system UILocalizedStringResourceCarries localization until display
Non-user-facing logs and analyticsPlain StringNo localization needed

LocalizedStringKey (SwiftUI default)

SwiftUI views accept LocalizedStringKey for their text parameters. String literals are implicitly converted -- no extra work needed.

swift
Text("Welcome back")Button("Delete") { deleteItem() }

Use LocalizedStringKey when passing strings directly to SwiftUI view initializers. Do not construct LocalizedStringKey manually in most cases.

String(localized:) -- Modern NSLocalizedString replacement

Use for any localized string outside a SwiftUI view initializer. Returns a plain String. The literal/interpolated initializer is available iOS 15+; resolving a LocalizedStringResource is iOS 16+.

swift
let title = String(localized: "Welcome back")let msg = String(localized: "error.network",                 defaultValue: "Check your internet connection")

For Swift package localization failures, answer with this explicit resource checklist before bundle debugging:

  1. Package.swift declares defaultLocalization.
  2. The target resources list processes the catalog location, such as .process("Resources").
  3. Localizable.xcstrings is actually inside that processed target-resource path. Only after those pass, debug lookup with bundle: .module or Text(..., bundle: .module).

Existing NSLocalizedString literal keys can still be exported or migrated by Xcode tooling, but new Swift code should prefer String(localized:), SwiftUI literals, LocalizedStringResource, or generated symbols.

LocalizedStringResource -- Pass localization info without resolving

Use when a string must be carried as a localizable value for later resolution, especially for App Intents, widgets, notifications, generated localizable symbols, and system APIs that accept LocalizedStringResource directly. Use String(localized:) when code needs the resolved string immediately. Available iOS 16+.

swift
struct OrderCoffeeIntent: AppIntent {    static var title: LocalizedStringResource = "Order Coffee"}
func showAlert(title: LocalizedStringResource, message: LocalizedStringResource) {    let resolved = String(localized: title)}

String Interpolation in Localized Strings

Interpolated values in localized strings become positional arguments that translators can reorder.

swift
// English: "Welcome, Alice! You have 3 new messages."// German:  "Willkommen, Alice! Sie haben 3 neue Nachrichten."// Japanese: "Alice さん、新しいメッセージが 3 件あります。"let text = String(localized: "Welcome, \(name)! You have \(count) new messages.")

In the String Catalog, this appears with %@ and %lld placeholders that translators can reorder:

  • English: "Welcome, %@! You have %lld new messages."
  • Japanese: "%@さん、新しいメッセージが%lld件あります。"

Type-safe interpolation (preferred over format specifiers):

swift
// Interpolation provides type safetyString(localized: "Score: \(score, format: .number)")String(localized: "Due: \(date, format: .dateTime.month().day())")

Pluralization

String Catalogs handle pluralization natively -- no .stringsdict XML required.

Setup in String Catalog

When a localized string contains an integer interpolation, Xcode detects it and offers plural variants in the String Catalog editor. Supply translations for each CLDR plural category:

CategoryEnglish exampleArabic example
zero(not used)0 items
one1 item1 item
two(not used)2 items (dual)
few(not used)3-10 items
many(not used)11-99 items
other2+ items100+ items

English uses only one and other. Arabic uses all six. Always supply other as the fallback.

swift
// Code -- single interpolation triggers plural supportText("\(unreadCount) unread messages")
// String Catalog entries (English)://   one:   "%lld unread message"//   other: "%lld unread messages"

Device Variations

String Catalogs support device-specific text (iPhone vs iPad vs Mac):

swift
// In String Catalog editor, enable "Vary by Device" for a key// iPhone: "Tap to continue"// iPad:   "Tap or click to continue"// Mac:    "Click to continue"

Use Foundation's automatic grammar agreement markup when nearby words must inflect for a value's number or gender. Preserve the complete inflecting phrase for translators; see Automatic Grammar Agreement.

FormatStyle -- Locale-Aware Formatting

Never hard-code user-facing formats. Use FormatStyle and test output under contrasting locales such as en_US, de_DE, ar_SA, and ja_JP.

ios-localization owns FormatStyle guidance when the issue is locale-aware user-facing display, including numbers, dates, currency, units, names, lists, calendars, separators, and locale preview/testing. For custom FormatStyle, ParseableFormatStyle, parsing, Date.IntervalFormatStyle, URL.FormatStyle, or reusable formatter API design, route to swift-formatstyle; keep ios-localization advice to locale risks and testing unless implementation is explicitly requested.

Dates

swift
let now = Date.now
// Preset stylesnow.formatted(date: .long, time: .shortened)// US: "January 15, 2026 at 3:30 PM"// DE: "15. Januar 2026 um 15:30"// JP: "2026年1月15日 15:30"
// Component-basednow.formatted(.dateTime.month(.wide).day().year())// US: "January 15, 2026"
// In SwiftUIText(now, format: .dateTime.month().day().year())

Numbers

swift
let count = 1234567count.formatted()                     // "1,234,567" (US) / "1.234.567" (DE)count.formatted(.number.precision(.fractionLength(2)))count.formatted(.percent)             // For 0.85 -> "85%" (US) / "85 %" (FR)
// Currencylet price = Decimal(29.99)price.formatted(.currency(code: "USD"))  // "$29.99" (US) / "29,99 $US" (FR)price.formatted(.currency(code: "EUR"))  // "29,99 EUR" (DE)

Measurements

swift
let distance = Measurement(value: 5, unit: UnitLength.kilometers)distance.formatted(.measurement(width: .wide))// US: "3.1 miles" (auto-converts!) / DE: "5 Kilometer"
let temp = Measurement(value: 22, unit: UnitTemperature.celsius)temp.formatted(.measurement(width: .abbreviated))// US: "72 F" (auto-converts!) / FR: "22 C"

Load references/formatstyle-locale.md [blocked] for duration, names, lists, custom styles, variant matrices, and deeper RTL testing.

Right-to-Left (RTL) Layout

SwiftUI automatically mirrors layouts for RTL languages (Arabic, Hebrew, Urdu, Persian). Most views require zero changes.

What SwiftUI auto-mirrors

  • HStack children reverse order
  • .leading / .trailing alignment and padding swap sides
  • NavigationStack back button moves to trailing edge
  • List disclosure indicators flip
  • Text alignment follows reading direction

What needs manual attention

swift
// Testing RTL in previewsMyView()    .environment(\.layoutDirection, .rightToLeft)    .environment(\.locale, Locale(identifier: "ar"))
// Images that should mirror (directional arrows, progress indicators)Image(systemName: "chevron.right")    .flipsForRightToLeftLayoutDirection(true)
// Images that should NOT mirror: logos, photos, clocks, music notes
// Forced LTR for specific content (phone numbers, code)Text("+1 (555) 123-4567")    .environment(\.layoutDirection, .leftToRight)

Layout rules

  • DO use .leading / .trailing -- they auto-flip for RTL
  • DON'T use .left / .right -- they are fixed and break RTL
  • DO use HStack / VStack -- they respect layout direction
  • DON'T use absolute offset(x:) for directional positioning

Common Mistakes

DON'T: Use fixed-width layouts

swift
// WRONG -- German text is ~30% longer than EnglishText(title).frame(width: 120)

DO: Use flexible layouts

swift
// CORRECTText(title).fixedSize(horizontal: false, vertical: true)// Or use VStack/wrapping that accommodates expansion

DON'T: Skip pseudolocalization testing

Testing only in English hides truncation, layout, and RTL bugs.

DO: Test with German (long) and Arabic (RTL) at minimum

Use Xcode scheme settings to override the app language without changing device locale.

Review Checklist

  • All user-facing strings use localization (LocalizedStringKey in SwiftUI or String(localized:))
  • No string concatenation for user-visible text
  • Dates and numbers use FormatStyle, not hardcoded formats
  • Pluralization handled via String Catalog plural variants (not manual if/else)
  • Layout uses .leading / .trailing, not .left / .right
  • UI tested with long text (German) and RTL (Arabic)
  • String Catalog includes all target languages
  • Images needing RTL mirroring use .flipsForRightToLeftLayoutDirection(true)
  • App Intents and widgets use LocalizedStringResource
  • No NSLocalizedString usage in new code
  • Comments provided for ambiguous keys (context for translators)
  • @ScaledMetric used for spacing that must scale with Dynamic Type
  • Currency formatting uses explicit currency code, not locale default
  • Pseudolocalization tested (accented, right-to-left, double-length)
  • Manually-managed keys use stable symbol-style names, not English text as the key
  • Generate String Catalog Symbols enabled for targets with manually-managed keys
  • Ensure localized string types are Sendable; use @MainActor for locale-change UI updates

References

  • FormatStyle patterns: references/formatstyle-locale.md [blocked]
  • String Catalogs guide: references/string-catalogs.md [blocked]

來源與署名

來源:dpearson2699/swift-ios-skills位於skills/ios-localization提交8d90fd1

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架

更多來自 dpearson2699/swift-ios-skills 的技能

Widgetkit

dpearson2699

指導實作、審查與改進 iOS、iPadOS、watchOS 與 CarPlay 上的 WidgetKit 小工具與控制項。

Software Development1.1K2 個月前更新

Weatherkit

dpearson2699

指導 iOS 開發者使用 WeatherService 取得 WeatherKit 預報、警報與署名資訊。

Software Development1.1K2 個月前更新

Vision Framework

dpearson2699

Implement computer vision features including text recognition (OCR), face detection, barcode scanning, image segmentation, object tracking, and document scanning in iOS apps. Covers both the modern Swift-native Vision API (iOS 18+) and legacy VNRequest patterns, VisionKit DataScannerViewController for live camera scanning, and CoreMLRequest/VNCoreMLRequest for custom model inference. Use when adding OCR, barcode scanning, face detection, or custom Core ML model inference with Vision.

待分類1.1K2 個月前更新

Tipkit

dpearson2699

Implement and review Apple TipKit feature-discovery UI for iOS 17+ apps. Use when adding or auditing in-app tips, contextual help, coach marks, Tip, TipView, popoverTip, rules, events, actions, display frequency, testing overrides, reusable tip identifiers, or iOS 18+ TipGroup and CloudKit tip sync; avoid for generic SwiftUI navigation or layout outside tip presentation.

待分類1.1K2 個月前更新

Tabletopkit

dpearson2699

指導使用 TabletopKit 在 visionOS 上打造多人空間桌遊,涵蓋棋具、座位、動作與 RealityKit 算繪。

Software Development1.1K2 個月前更新

Swiftui Webkit

dpearson2699

指導在 iOS 26 及更新版本的 SwiftUI App 中使用 WebKit for SwiftUI 嵌入與控制網頁內容。

Software Development1.1K2 個月前更新