| name | ios-localization |
| description | iOS localization expert for internationalization. Use when working with String Catalogs, XLIFF, localized strings, date/number formatting, pluralization, or multi-language support. |
iOS Localization
Expert guidance for localizing iOS applications.
String Catalogs (Xcode 15+)
Create String Catalog
- File > New > File > String Catalog
- Name it
Localizable.xcstrings
Basic Usage
Text("Hello, World!")
Text("Welcome to the app")
String Interpolation
Text("Hello, \(username)!")
Text("Score: \(points) points in \(level)")
Comments for Translators
Text("Save", comment: "Button to save the current document")
Text("Book", comment: "Noun - a written publication, not the verb")
Pluralization
Automatic Pluralization
Text("^[\(itemCount) item](inflect: true)")
Manual Pluralization (String Catalog)
Text("\(count) files selected")
Complex Pluralization
Text("\(unreadCount) unread messages from \(senderCount) senders")
Localized Resources
Localized Images
Image("welcome", bundle: .main)
.resizable()
Localized Colors
Color("brandColor")
Info.plist Localization
"CFBundleDisplayName" = "My App";
"NSCameraUsageDescription" = "Take photos for your profile";
"CFBundleDisplayName" = "マイアプリ";
"NSCameraUsageDescription" = "プロフィール写真を撮影";
Formatters
Date Formatting
Text(date, style: .date)
Text(date, style: .time)
Text(date, format: .dateTime.day().month().year())
let formatter = DateFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .short
Text(date, format: .relative(presentation: .named))
Number Formatting
Text(price, format: .currency(code: "USD"))
Text(progress, format: .percent)
Text(value, format: .number.precision(.fractionLength(2)))
let distance = Measurement(value: 5, unit: UnitLength.kilometers)
Text(distance, format: .measurement(width: .abbreviated))
List Formatting
let items = ["Apple", "Banana", "Orange"]
Text(items, format: .list(type: .and))
Layout Considerations
Right-to-Left Languages
HStack {
Image(systemName: "arrow.left")
Text("Back")
}
Image(systemName: "checkmark")
.flipsForRightToLeftLayoutDirection(false)
Check Layout Direction
struct AdaptiveView: View {
@Environment(\.layoutDirection) var layoutDirection
var body: some View {
HStack {
if layoutDirection == .rightToLeft {
trailingContent
leadingContent
} else {
leadingContent
trailingContent
}
}
}
}
Text Alignment
Text("Content")
.frame(maxWidth: .infinity, alignment: .leading)
Text("Long text content here")
.multilineTextAlignment(.leading)
Language-Specific Adjustments
Check Current Language
let currentLanguage = Locale.current.language.languageCode?.identifier
if currentLanguage == "ja" {
}
Override Locale
Text(date, format: .dateTime)
.environment(\.locale, Locale(identifier: "ja_JP"))
#Preview {
ContentView()
.environment(\.locale, Locale(identifier: "ar"))
.environment(\.layoutDirection, .rightToLeft)
}
Export/Import
Export for Translation
xcodebuild -exportLocalizations -project MyApp.xcodeproj -localizationPath ./Localizations
Import Translations
xcodebuild -importLocalizations -project MyApp.xcodeproj -localizationPath ./Localizations/ja.xcloc
Testing Localization
Preview Different Languages
#Preview("English") {
ContentView()
.environment(\.locale, Locale(identifier: "en"))
}
#Preview("Japanese") {
ContentView()
.environment(\.locale, Locale(identifier: "ja"))
}
#Preview("Arabic RTL") {
ContentView()
.environment(\.locale, Locale(identifier: "ar"))
.environment(\.layoutDirection, .rightToLeft)
}
Pseudo-Localization
UI Tests for Localization
func testLocalizedUI() {
let app = XCUIApplication()
app.launchArguments += ["-AppleLanguages", "(ja)"]
app.launchArguments += ["-AppleLocale", "ja_JP"]
app.launch()
XCTAssertTrue(app.buttons["保存"].exists)
}
Best Practices
String Keys
Text("welcome.message")
Text("button.save")
Text("error.network.unavailable")
Avoid Concatenation
Text("Hello, ") + Text(username) + Text("!")
Text("Hello, \(username)!")
Context for Translators
Text("Post", comment: "Verb - action to publish content")
Text("Post", comment: "Noun - a published article")
Text("settings.save.button")
Text("document.save.action")
Apple Documentation