Skip to content

Use %1$d in the plural word count - #26261

Open
mokagio wants to merge 3 commits into
trunkfrom
ainfra-3482-use-1d-instead-of-1ld-in-wordpress-ios-plural-word-count
Open

mokagio wants to merge 3 commits into
trunkfrom
ainfra-3482-use-1d-instead-of-1ld-in-wordpress-ios-plural-word-count

Conversation

@mokagio

@mokagio mokagio commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Description

Switches the English word-count plural in Plurals.xcstrings from %1$ld to %1$d (AINFRA-3482).

Caution

@jkmassel @crazytonyli With your work setting the new localization pipeline, you know more about xcstrings than I do. I'm not entirely sure changing what I assume was the default Apple format for something different just to please GlotPress is a good approach. But maybe the difference is small enough that we can accept it?

GlotPress highlights only %1$l as the placeholder and shows the d as text to translate, so translators drop it: ko, zh-cn and zh-tw currently have %1$l, which fails lint_localizations on every beta and is why apply_glotpress_translation_patch patches them by hand.
GlotPress highlights %1$d whole.
The count never comes near Int32.max, so %d formats an Int correctly.

Gotchas:

  • GlotPress treats the edited English as a new string, so every locale re-translates it. Until then, the plural fold falls back to English (needs_review) for this key, because its validator treats %d and %ld as different. Nothing reads Plurals.xcstrings at runtime yet, so users see no change.
  • The fold currently carries over existing machine cells (%1$ld) without re-checking them against the new English; Re-check kept plural machine cells against English #26263 fixes that.
  • The patch table now writes %1$d, so patched values match the new English. ro's entries need this regardless of GlotPress, because Romanian omits the number in those forms and re-translating won't change that. The ko and zh-* entries stay until the new original is on GlotPress, which needs a code freeze after this lands; removing them is the last step of AINFRA-3482.

Testing instructions

PR CI doesn't run the plural lanes for an .xcstrings-only change, so they ran on a throwaway stacked PR (#26262, closed) — build 35363:

  • generate_strings_file_for_glotpress (as at code freeze) emitted all six word-count originals with %1$d; the same assertion fails on trunk's catalog.
  • download_localized_plurals (as at every beta, without ANTHROPIC_API_KEY) kept English %1$d, the folded catalog compiles, and it rejected the 48 existing human %1$ld translations, falling back to English until GlotPress re-translates.

Locally: the catalog compiles with xcrun xcstringstool compile, the forward flattening emits %1$d for all six categories, and bundle exec fastlane download_localized_plurals folds into a catalog that still compiles.

The patch table has no permanent test because it's temporary. Running the real apply_glotpress_translation_patch on the broken ko, ro, zh-Hans and zh-Hant values, then the fold's placeholder check against the catalog English, rejected 6 of 6 sampled cells before the retarget and 0 of 6 after.

GlotPress highlights only `%1$l` in `%1$ld` and shows the `d` as translatable text, so translators drop it: `ko`, `zh-cn` and `zh-tw` currently have `%1$l`, and `nl` had `%1$l d` in July.
That fails `lint_localizations` on every beta.
`%1$d` is highlighted whole.
See AINFRA-3482.

The word count never comes near `Int32.max`, so `%d` formats an `Int` correctly.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mokagio mokagio self-assigned this Oct 28, 2026
@dangermattic

Copy link
Copy Markdown
Collaborator
1 Message
📖 This PR is still a Draft: some checks will be skipped.

Generated by 🚫 Danger

The patch table still rewrote translations to `%1$ld`, which the plural fold now rejects against the `%1$d` English, so `ro`'s `one` and `zero` forms would stay rejected even after translators re-translate them.
The `ko`, `zh-Hans` and `zh-Hant` entries stay until the new original is on GlotPress, which only happens after the next code freeze.
Until then, downloads still return the old `%1$l` values, and removing the entries would fail `lint_localizations`.

---

Generated with the help of Claude Code (Opus 5.5), https://code.claude.com
So the next plural doesn't reintroduce the placeholder translators keep breaking in GlotPress.

---

Generated with the help of Claude Code (Opus 5.5), https://code.claude.com
@mokagio mokagio added Tooling Build, Release, and Validation Tools i18n labels Nov 3, 2026
@mokagio mokagio added this to the 27.5 milestone Nov 3, 2026
@mokagio
mokagio marked this pull request as ready for review November 5, 2026 03:30
@mokagio
mokagio requested review from a team and a balanced review from Copilot November 5, 2026 03:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The word-count placeholder update has no active review issues.

No open issues 🎉

What changed in this PR

Updates word-count plural placeholders to %1$d so GlotPress recognizes the full placeholder and translators do not accidentally drop its final character. This changes localization preparation; the catalog is not yet read at runtime.

Changes:

  • Switches English word-count plurals and their translator comment from %1$ld to %1$d.
  • Aligns Korean, Romanian, and Chinese translation patches with the new English placeholder.
  • Documents %1$d as the preferred placeholder for counts.
File Description
WordPress/​Classes/​Plurals.xcstrings Updates English word-count placeholders and the translator comment.
fastlane/​lanes/​localization.rb Retargets word-count translation patches to %1$d.
docs/​localization.md Adds count-placeholder guidance explaining the GlotPress limitation.

Review effort: Balanced

@AliSoftware AliSoftware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks good and makes sense to me (but indeed it's be nice to have @jkmassel and @crazytonyli validate with their better comprehension of the new translation process/automation they put in place.

Obviously it'd be even better to have our agents fix GlotPress itself at the source to fix that annoying placeholder highlighting bug they have on %ld. And I think such a fix would be worth it to do upstream anyway. But it might take time for such a fix to be shipped in a new version then deployed on translate.wordpress.org so it's still important to workaround that here too by using %d in the meantime.

Comment thread docs/localization.md
3. **Use positional placeholders**: `%1$@`, `%2$d` not just `%@`, `%d`
4. **No variables in NSLocalizedString**: All parameters must be string literals
5. **Use String.localizedStringWithFormat**: Don't use string interpolation
6. **Use `%1$d` for counts, not `%1$ld`**: GlotPress highlights only `%1$l` as the placeholder, so translators drop the `d`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
6. **Use `%1$d` for counts, not `%1$ld`**: GlotPress highlights only `%1$l` as the placeholder, so translators drop the `d`
6. **Use `%1$d` for counts, not `%1$ld`**: GlotPress highlights only `%1$l` as the placeholder, which makes translators often incorrectly drop the `d`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

i18n Tooling Build, Release, and Validation Tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants