Skip to content
Development

Fixing pluralization, and why I almost picked the wrong Apple API

By Victor Da Luz
swiftiosi18ndev-logdeep-cut-atlas

I found this bug while triaging Deep Cut Atlas’s backlog: a design review from last week flagged that the album card hand-rolls its track-count pluralization with count == 1 ? "" : "s". The example given was Spanish “canción/canciones” needing a different word shape than English’s suffix trick. When I actually opened the code and the shipped translation, the story was a bit different, and more interesting.

The visible label was fine on the surface: “1 track” / “3 tracks” in English, correctly wired through a ternary. But the accessibility label, two lines below, had no ternary at all. It just always said “N tracks”, so a single-track album read “1 tracks” to VoiceOver. That’s a plain English bug, no translation involved.

The Spanish side had a twist too. The design review’s example assumed the noun would be “canción” (song), which really does need a different plural shape than English’s add-an-s trick. But the actual shipped translation uses “pista” (track), and “pista” pluralizes to “pistas” exactly like English does. So nothing looked broken in the Spanish UI today. The bug was structural, not visible, which is a worse kind of bug to have sitting in a codebase, because nobody notices it until the day someone picks a word that doesn’t pluralize by suffix.

I reached for Apple’s Automatic Grammar Agreement first, the Text("^[\(count) track](inflect: true)") syntax that lets Foundation infer a noun’s correct plural form at runtime instead of writing it out by hand. It’s clever, and Spanish has been supported since iOS 15. But support is per-language and keeps expanding by OS version. Portuguese doesn’t get it until iOS 18. This app’s minimum target is iOS 17.6, and Portuguese localization is already queued as a separate issue. Shipping inflection now would mean the first Portuguese speaker on an older device to hit this label gets silently wrong output, exactly the class of bug I was trying to close.

So I switched to String Catalog’s “Vary by Plural” instead, the CLDR-category mechanism that’s the modern equivalent of .stringsdict. It’s less magic: you write out the singular and plural form yourself, per language. But it works identically on every OS version, and it turned out to make the accessibility fix simpler too, since it resolves through a plain String(localized:) call rather than the AttributedString conversion inflection would have needed.

One wrinkle: “Vary by Plural” is normally a right-click action in Xcode’s String Catalog editor, not something you can drive from a terminal. But .xcstrings is just JSON with a documented schema, so I hand-wrote the plural-variation structure directly into the file. A CLI test run’s “Compile XCStrings” build step processed it without complaint, and the simulator rendered the correct singular and plural form in both English and Spanish.

Small bug, but it’s the kind that’s cheap to fix well and expensive to leave. Every future noun this app picks for a count label was one bad word choice away from repeating it.

Related reading