Pluralization on iOS is powerful, flexible — and notoriously easy to get wrong.
If you’ve ever opened a .stringsdict file and wondered how anyone ships apps this way, you’re not alone. The syntax is verbose, the rules are implicit, and most mistakes don’t show up until you add a second or third language.
This guide explains how iOS pluralization actually works, how .stringsdict files are evaluated, and how to structure them so they don’t become a long-term liability.
Why iOS Uses .stringsdict
Unlike Android, iOS doesn’t treat plurals as a first-class resource type. Instead, it uses format dictionaries that combine:
- ICU plural rules
- Variable substitution
- Language-specific grammar
This flexibility is powerful — but it also means you’re responsible for correctness.
A Minimal .stringsdict Example
Here’s the smallest useful shape of a plural entry:
<dict>
<key>item_count</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@items@</string>
<key>items</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>%d item</string>
<key>other</key>
<string>%d items</string>
</dict>
</dict>
</dict>
This works for English — but like Android, it’s incomplete for many languages.
What Actually Happens at Runtime
When a .stringsdict entry is malformed, iOS often fails in ways that are easy to miss:
- You may get the key back (for example,
item_count) instead of a formatted string
- You may get an unformatted template with placeholders still present
- You may hit a formatting exception when specifiers don’t match the provided value
This is why .stringsdict issues can survive code review and QA: the happy path in English often works, and the broken branches only appear for specific counts and specific languages.
Languages That Stress-Test Your .stringsdict
If you only test English-style rules (one / other), you’re not really testing pluralization.
These languages tend to surface issues quickly:
- Polish / Russian / Ukrainian – multiple categories that depend on both the last digit and the last two digits
- Arabic – additional categories such as zero and two
- Czech / Slovak – categories English never uses
If those branches don’t exist in your base structure, translations can’t safely fill them in later.
The Traps Teams Fall Into
1. Treating .stringsdict as “Advanced .strings”
It isn’t.
.stringsdict files encode logic, not just copy. Missing keys, wrong spec types, or inconsistent placeholders don’t always crash — they often degrade silently.
2. Missing Required Plural Categories
Languages like Polish or Arabic require more than one and other. If the category isn’t defined, iOS may fall back incorrectly or return the key itself.
Unlike Android, there’s no build-time warning by default.
3. Placeholder Mismatches (The Fastest Way to Ship a Crash)
Plural entries almost always include %d, %f, or %@.
A common failure mode looks like this:
- Base string: %d items
- Translation accidentally drops %d or changes it to %@
- Everything looks fine in screenshots
- The app crashes when formatting happens at runtime
This is especially common when translations are updated frequently or generated by AI without validation.
Structuring .stringsdict Files Safely
A defensive approach is to:
- Define all plural categories you might need in the base language, even if English doesn’t use them
- Keep placeholder usage consistent across all branches
- Validate structure automatically before shipping
This mirrors the approach we recommend for Android plurals, covered in Android Plurals Explained.
Why These Bugs Show Up in CI
Plural issues on iOS tend to surface when a new language is added, when translations are updated independently, or during last-minute release prep.
The reason is simple: CI is often the first place where structural validation and placeholder consistency are enforced across all locales.
Treating localization as a continuous process — where diffs are translated, validated, and synced automatically — makes .stringsdict failures predictable instead of surprising. This is the heart of continuous localization workflows.
Further Reading
Apple’s documentation on string format dictionaries is worth skimming once so the key names stop feeling like magic. Our guide on modern localization workflows covers how teams validate plurals and placeholders continuously instead of at release time.
Takeaway
.stringsdict gives iOS incredible flexibility — but no safety net.
If pluralization logic lives only in developers’ heads, bugs are inevitable. Treat plural files as executable configuration, validate them early, and don’t assume English rules apply globally.
Ready to localize your app?
Get started free — no credit card required.
Start Translating →