Note that testing a translation needs the bundle, not the locale

Fixing the Czech plurals turned up a trap worth recording: String(localized:
locale:) reads the language from the bundle, while locale: only drives
number and date formatting. A test that passes a Czech locale and nothing
else quietly compares English strings — ours failed with "1 coupon" ==
"1 kupón", which reads as broken plurals when the plurals were fine and
the test was looking in the wrong place.

Also that a plural variation must reference the number, so a key
extracted as "%@" cannot carry one and the build says so outright.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
TomUviandClaude Opus 5 committed 2026-08-18 15:42:28 +02:00
1 parent 3ad73df76a
commit a7f5d352ef
3 files changed
+27 -2

No files matched your search

+1 -1
View File
@@ -12,7 +12,7 @@
"name": "pdat-swift-practice", "name": "pdat-swift-practice",
"source": "./pdat-swift-practice", "source": "./pdat-swift-practice",
"description": "Curated Apple platform findings with sources, plus practices learned from production incidents.", "description": "Curated Apple platform findings with sources, plus practices learned from production incidents.",
"version": "0.5.0", "version": "0.6.0",
"author": { "author": {
"name": "PDAT s.r.o." "name": "PDAT s.r.o."
}, },
@@ -1,6 +1,6 @@
{ {
"name": "pdat-swift-practice", "name": "pdat-swift-practice",
"version": "0.5.0", "version": "0.6.0",
"description": "Curated Apple platform findings with sources, plus practices learned from production incidents.", "description": "Curated Apple platform findings with sources, plus practices learned from production incidents.",
"author": { "author": {
"name": "PDAT s.r.o.", "name": "PDAT s.r.o.",
@@ -43,6 +43,31 @@ count wrapped in parentheses — "Send unsent receipts (3)" — dodges the
problem entirely and is a reasonable fallback where a plural form would problem entirely and is a reasonable fallback where a plural form would
be awkward. be awkward.
## Testing a translation needs the right bundle, not the right locale
`String(localized:locale:)` looks like it renders a given language. It does
not: `locale:` drives number and date formatting, while the language comes
from the **bundle**. A test that passes `locale: Locale(identifier: "cs")`
and nothing else reads the English strings and reports them as if they
were Czech.
```swift
let path = Bundle.main.path(forResource: "cs", ofType: "lproj")!
let czech = Bundle(path: path)!
String(localized: "\(1) coupons", bundle: czech, locale: Locale(identifier: "cs"))
```
Our first attempt at the plural test got this wrong and failed with
`"1 coupon" == "1 kupón"` — which at a glance reads as "the plurals are
broken" when in fact the English plurals were working and the test was
looking in the wrong place.
Also: a plural variation must reference the number. A key extracted as
`%@ coupons` cannot carry one, and the build fails outright with "Plural
variation requires referencing the number in the string" — usable
feedback, and a reason to keep counts typed as `Int` so the key comes out
as `%lld`.
**Step forward?** Yes, and overdue. This is the kind of defect that never **Step forward?** Yes, and overdue. This is the kind of defect that never
shows up in a test and that a Czech speaker notices immediately. shows up in a test and that a Czech speaker notices immediately.