Apple String Catalogs (.xcstrings): Complete Guide to iOS/macOS Localization
Updated: December 05, 2025
What Are Apple String Catalogs (.xcstrings)?
String Catalogs (.xcstrings) are Apple’s modern localization file format, introduced in Xcode 15 at WWDC 2023. This JSON-based format replaces the traditional .strings and .stringsdict files, providing a unified solution for managing all localizations in a single file.
String Catalogs offer powerful features including automatic string extraction, pluralization support, device-specific variations, and a visual editor in Xcode, making iOS and macOS localization more efficient than ever.
Why AZbox Supports .xcstrings Files
At AZbox, we understand that Apple developers need modern tools that work seamlessly with the latest Apple technologies. That’s why AZbox fully supports .xcstrings file import and export, allowing you to:
- Import existing .xcstrings files directly into your AZbox project
- Export translations back to .xcstrings format for use in your Xcode project
- Preserve all metadata including comments, states, and variations
- Manage translations with our powerful cloud-based platform
- Collaborate with translators who can work without needing Xcode
- Update over-the-air without App Store approval
.xcstrings vs Legacy Formats
| Feature | .xcstrings | .strings | .stringsdict |
|---|---|---|---|
| Format | JSON | Key-value pairs | XML plist |
| All languages in one file | ✅ Yes | ❌ No | ❌ No |
| Pluralization | ✅ Built-in | ❌ No | ✅ Yes |
| Device variations | ✅ Built-in | ❌ No | ❌ No |
| Visual editor | ✅ Xcode 15+ | ❌ No | ❌ No |
| Auto string extraction | ✅ Yes | ❌ No | ❌ No |
| Translation state tracking | ✅ Yes | ❌ No | ❌ No |
.xcstrings File Structure
String Catalogs use a JSON structure that organizes all translations, metadata, and variations in a single file:
{
"sourceLanguage": "en",
"version": "1.0",
"strings": {
"welcome_title": {
"comment": "Title shown on the welcome screen",
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Welcome to Our App"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "Bienvenido a Nuestra App"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Bienvenue dans Notre App"
}
}
}
}
}
}
Key Components
| Component | Description |
|---|---|
sourceLanguage | The development language (e.g., “en”) |
version | String Catalog format version |
strings | Dictionary of all localizable strings |
comment | Description for translators |
extractionState | How the string was added (manual, automatic, etc.) |
localizations | Translations for each language |
stringUnit | Container for the translation value and state |
state | Translation status (translated, needs_review, stale, new) |
Translation States
String Catalogs track the state of each translation:
| State | Description | Xcode Display |
|---|---|---|
new | String needs translation | 🔴 Red |
translated | Translation complete | 🟢 Green |
needs_review | Translation needs review | 🟡 Yellow |
stale | Source changed, translation may be outdated | 🟠 Orange |
{
"button_save": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Save"
}
},
"de": {
"stringUnit": {
"state": "needs_review",
"value": "Speichern"
}
},
"ja": {
"stringUnit": {
"state": "new",
"value": ""
}
}
}
}
}
Pluralization in .xcstrings
String Catalogs handle pluralization elegantly using the variations key with plural rules:
{
"items_count": {
"comment": "Number of items in the cart",
"localizations": {
"en": {
"variations": {
"plural": {
"zero": {
"stringUnit": {
"state": "translated",
"value": "No items"
}
},
"one": {
"stringUnit": {
"state": "translated",
"value": "1 item"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "%lld items"
}
}
}
}
},
"es": {
"variations": {
"plural": {
"zero": {
"stringUnit": {
"state": "translated",
"value": "Sin artículos"
}
},
"one": {
"stringUnit": {
"state": "translated",
"value": "1 artículo"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "%lld artículos"
}
}
}
}
}
}
}
}
Plural Categories
| Category | Description | Example Languages |
|---|---|---|
zero | Zero items | Arabic, Latvian, Welsh |
one | Singular | English, Spanish, German |
two | Dual form | Arabic, Welsh, Slovenian |
few | Few items | Russian, Polish, Czech |
many | Many items | Russian, Arabic, Polish |
other | Default/general plural | All languages (required) |
Device Variations
String Catalogs support device-specific translations, perfect for adapting UI text to different screen sizes:
{
"navigation_button": {
"comment": "Main navigation button",
"localizations": {
"en": {
"variations": {
"device": {
"iphone": {
"stringUnit": {
"state": "translated",
"value": "Menu"
}
},
"ipad": {
"stringUnit": {
"state": "translated",
"value": "Navigation Menu"
}
},
"mac": {
"stringUnit": {
"state": "translated",
"value": "Open Navigation Menu"
}
},
"appletv": {
"stringUnit": {
"state": "translated",
"value": "Menu"
}
},
"applewatch": {
"stringUnit": {
"state": "translated",
"value": "☰"
}
}
}
}
}
}
}
}
Supported Devices
| Device Key | Platform |
|---|---|
iphone | iPhone |
ipad | iPad |
mac | macOS |
appletv | tvOS |
applewatch | watchOS |
applevision | visionOS |
Substitutions (Format Specifiers)
String Catalogs support various format specifiers for dynamic content:
{
"greeting_message": {
"comment": "Greeting with user's name",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Hello, %@!"
}
},
"es": {
"stringUnit": {
"state": "translated",
"value": "¡Hola, %@!"
}
}
}
},
"download_progress": {
"comment": "Download progress percentage",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Downloading: %d%%"
}
}
}
}
}
Common Format Specifiers
| Specifier | Type | Example |
|---|---|---|
%@ | String (NSString/String) | “Hello, %@!” |
%d | Integer | ”%d items” |
%lld | Long integer | ”%lld points” |
%f | Float/Double | ”%.2f miles” |
%% | Literal percent sign | ”%d%%“ |
Combining Plural and Device Variations
For complex scenarios, you can combine plural forms with device variations:
{
"photos_count": {
"comment": "Number of photos selected",
"localizations": {
"en": {
"variations": {
"plural": {
"one": {
"variations": {
"device": {
"iphone": {
"stringUnit": {
"state": "translated",
"value": "1 photo"
}
},
"ipad": {
"stringUnit": {
"state": "translated",
"value": "1 photo selected"
}
}
}
}
},
"other": {
"variations": {
"device": {
"iphone": {
"stringUnit": {
"state": "translated",
"value": "%lld photos"
}
},
"ipad": {
"stringUnit": {
"state": "translated",
"value": "%lld photos selected"
}
}
}
}
}
}
}
}
}
}
}
Importing .xcstrings to AZbox
Step 1: Export from Xcode
In Xcode 15+, your String Catalog is located in your project:
MyApp/
├── MyApp.xcodeproj
├── Localizable.xcstrings ← String Catalog
├── Sources/
└── Resources/
Step 2: Import via AZbox Dashboard
- Log in to your AZbox dashboard
- Navigate to your project
- Go to Import/Export section
- Select Import and choose Apple String Catalog (.xcstrings)
- Upload your
.xcstringsfile - AZbox will parse all strings, translations, and metadata
Step 3: Review and Manage
After importing:
- View all strings organized by key
- See translation states (new, translated, needs review)
- Edit translations with context from comments
- Add new languages instantly
- Use machine translation for missing strings
- Track completion percentage per language
Exporting .xcstrings from AZbox
When ready to use translations in your Xcode project:
- Go to Import/Export in your project
- Select Export and choose Apple String Catalog (.xcstrings)
- Select target languages
- Download the generated
.xcstringsfile - Replace or merge with your existing String Catalog in Xcode
Using .xcstrings in Swift
Basic Usage with String(localized:)
// Simple string
let title = String(localized: "welcome_title")
// String with comment
let message = String(localized: "welcome_message",
comment: "Shown on first launch")
Pluralization
// Define in code (auto-extracted to String Catalog)
let itemCount = String(localized: "\(count) items",
comment: "Number of items")
// Or use explicit key
let label = String(localized: "items_count")
SwiftUI Text
struct ContentView: View {
var body: some View {
VStack {
Text("welcome_title")
Text("items_count \(itemCount)")
}
}
}
String Interpolation
// Automatically handles localization
let greeting = String(localized: "Hello, \(username)!")
Using .xcstrings in Objective-C
// Simple string
NSString *title = NSLocalizedString(@"welcome_title", @"Welcome screen title");
// With format
NSString *message = [NSString localizedStringWithFormat:
NSLocalizedString(@"items_count", @"Item count"), itemCount];
Best Practices for .xcstrings
1. Use Descriptive Keys
Bad:
{
"str1": { ... },
"msg": { ... }
}
Good:
{
"welcome_screen_title": { ... },
"error_network_unavailable": { ... }
}
2. Always Add Comments
{
"save_button": {
"comment": "Button to save user profile changes. Appears at bottom of edit screen.",
"localizations": { ... }
}
}
3. Organize Keys by Feature
{
"auth.login.title": { ... },
"auth.login.button": { ... },
"auth.signup.title": { ... },
"settings.profile.title": { ... },
"settings.notifications.title": { ... }
}
4. Handle All Plural Forms
For languages like Russian, Arabic, or Polish that have complex plural rules:
{
"files_count": {
"localizations": {
"ru": {
"variations": {
"plural": {
"one": { "stringUnit": { "value": "%lld файл" } },
"few": { "stringUnit": { "value": "%lld файла" } },
"many": { "stringUnit": { "value": "%lld файлов" } },
"other": { "stringUnit": { "value": "%lld файлов" } }
}
}
}
}
}
}
5. Use Device Variations Sparingly
Only use device variations when truly necessary:
{
"action_button": {
"localizations": {
"en": {
"variations": {
"device": {
"applewatch": {
"stringUnit": { "value": "OK" }
},
"other": {
"stringUnit": { "value": "Continue" }
}
}
}
}
}
}
}
Migrating from .strings to .xcstrings
Automatic Migration in Xcode
- Open your Xcode project
- Select your
.stringsfile - Right-click and choose Migrate to String Catalog
- Xcode will create a
.xcstringsfile with all existing translations
Manual Migration
If migrating manually, convert from:
Localizable.strings (en):
"welcome_title" = "Welcome";
"save_button" = "Save";
To Localizable.xcstrings:
{
"sourceLanguage": "en",
"version": "1.0",
"strings": {
"welcome_title": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Welcome"
}
}
}
},
"save_button": {
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Save"
}
}
}
}
}
}
Common Issues and Solutions
Issue: Strings Not Appearing
Problem: Localized strings show keys instead of values.
Solution: Ensure:
- The
.xcstringsfile is included in your target - The key matches exactly (case-sensitive)
- The language is enabled in project settings
Issue: Plural Forms Not Working
Problem: Wrong plural form displayed.
Solution: Verify you’ve defined all required plural categories for the target language. The other category is always required.
Issue: Extraction State Conflicts
Problem: Xcode keeps re-extracting strings.
Solution: Set extractionState to "manual" for strings you manage manually:
{
"my_string": {
"extractionState": "manual",
"localizations": { ... }
}
}
AZbox .xcstrings Features
When you import .xcstrings to AZbox, you benefit from:
- Full metadata preservation - Comments, states, and extraction info maintained
- Plural form validation - Ensures all required plural categories are present
- Device variation support - Manage iPhone, iPad, Mac variations easily
- Visual state tracking - See translation progress at a glance
- Substitution highlighting - Visual markers for %@ and %d placeholders
- Translation memory - Leverage previous translations for consistency
- Machine translation - Fill gaps with AI-powered translation
- Over-the-air updates - Update translations without App Store review
- Team collaboration - Translators don’t need Xcode
Conclusion
Apple String Catalogs (.xcstrings) represent the future of iOS and macOS localization, offering a modern, unified approach to managing translations. With AZbox’s full .xcstrings support, you can:
- Import existing String Catalogs with all metadata preserved
- Manage translations in a collaborative cloud platform
- Support complex scenarios including plurals and device variations
- Export .xcstrings files ready for use in Xcode
- Update translations over-the-air without App Store approval
Ready to modernize your Apple app localization workflow?
Start Your Free Trial | View Pricing
AZbox provides comprehensive support for Apple String Catalogs (.xcstrings), making it the ideal localization platform for iOS, macOS, watchOS, tvOS, and visionOS developers. Import, manage, and export your translations with ease.
Start Global Growth Today
Join hundreds of successful companies already using AZbox to reach customers worldwide. Start with a free trial, no credit card required.
Get Started - It's Free