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
FormatJSONKey-value pairsXML 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

ComponentDescription
sourceLanguageThe development language (e.g., “en”)
versionString Catalog format version
stringsDictionary of all localizable strings
commentDescription for translators
extractionStateHow the string was added (manual, automatic, etc.)
localizationsTranslations for each language
stringUnitContainer for the translation value and state
stateTranslation status (translated, needs_review, stale, new)

Translation States

String Catalogs track the state of each translation:

StateDescriptionXcode Display
newString needs translation🔴 Red
translatedTranslation complete🟢 Green
needs_reviewTranslation needs review🟡 Yellow
staleSource 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

CategoryDescriptionExample Languages
zeroZero itemsArabic, Latvian, Welsh
oneSingularEnglish, Spanish, German
twoDual formArabic, Welsh, Slovenian
fewFew itemsRussian, Polish, Czech
manyMany itemsRussian, Arabic, Polish
otherDefault/general pluralAll 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 KeyPlatform
iphoneiPhone
ipadiPad
macmacOS
appletvtvOS
applewatchwatchOS
applevisionvisionOS

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

SpecifierTypeExample
%@String (NSString/String)“Hello, %@!”
%dInteger”%d items”
%lldLong integer”%lld points”
%fFloat/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

  1. Log in to your AZbox dashboard
  2. Navigate to your project
  3. Go to Import/Export section
  4. Select Import and choose Apple String Catalog (.xcstrings)
  5. Upload your .xcstrings file
  6. 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:

  1. Go to Import/Export in your project
  2. Select Export and choose Apple String Catalog (.xcstrings)
  3. Select target languages
  4. Download the generated .xcstrings file
  5. 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

  1. Open your Xcode project
  2. Select your .strings file
  3. Right-click and choose Migrate to String Catalog
  4. Xcode will create a .xcstrings file 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 .xcstrings file 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:

  1. Import existing String Catalogs with all metadata preserved
  2. Manage translations in a collaborative cloud platform
  3. Support complex scenarios including plurals and device variations
  4. Export .xcstrings files ready for use in Xcode
  5. 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.

Call to action background

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