Repository navigation
Convert every printf specifier in .stringsdict plural forms to ICU arguments - #134
Merged
Merged
Conversation
…guments
The .stringsdict to ICU MessageFormat conversion only mapped positional %N$@
and %N$d to {N-1}, so Xcode's default plural form "%lld files" rendered as
"%lld files", and literal braces, apostrophes or # broke the pattern. Every
specifier now becomes an argument: integer conversions as {n,number,#},
which formats without grouping like Darwin, the rest as {n}. %% becomes %,
and ICU syntax characters in the literal text are quoted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
piercifani
added a commit
to piercifani/skip-android-bridge
that referenced
this pull request
Oct 8, 2026
…rmat Replace the bridge's own ICU pattern parser and PluralCategoryAccess with a call to String.localizedStringWithFormat, so native String(localized:) and transpiled code share one plural path. Requires skiptools/skip-foundation#134 for Xcode's default non-positional specifiers (%lld). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
piercifani
added a commit
to piercifani/skip-android-bridge
that referenced
this pull request
Oct 8, 2026
…rmat Replace the bridge's own ICU pattern parser and PluralCategoryAccess with a call to String.localizedStringWithFormat, so native String(localized:) and transpiled code share one plural path. Pin skip-foundation to skiptools/skip-foundation#134, which this needs for Xcode's default non-positional specifiers (%lld), until it ships in a release. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
marcprux
approved these changes
Oct 8, 2026
marcprux
left a comment
Member
There was a problem hiding this comment.
Nice fix, thanks! Feel free to merge.
piercifani
added a commit
to piercifani/skip-android-bridge
that referenced
this pull request
Oct 9, 2026
…rmat Replace the bridge's own ICU pattern parser and PluralCategoryAccess with a call to String.localizedStringWithFormat, so native String(localized:) and transpiled code share one plural path. Requires skip-foundation 1.4.7 (skiptools/skip-foundation#134) for Xcode's default non-positional specifiers (%lld). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #102, from the discussion in skiptools/skip-android-bridge#39.
The
.stringsdict→ ICU MessageFormat conversion only mapped positional%N$@and%N$dto{N-1}. Xcode writes String Catalog plural variations with non-positional specifiers by default ("%lld files"), and those passed through as literal text, soString.localizedStringWithFormatrendered "%lld files". Literal{,},'or#in a plural form also changed the meaning of the ICU pattern, and braces madeMessageFormatthrow.Each plural form is now converted specifier by specifier:
%d,%i,%u, with any length modifier, positional or not) become{n,number,#}, which formats without grouping, like Darwin (1234 files, not1,234 files).%@,%f, …) become{n}.%N$…keeps its index.%%becomes%, and ICU syntax characters in the literal text are quoted.Plural selection is unchanged:
MessageFormatwith the current locale, andzeroas=0.This makes
localizedStringWithFormatthe single plural path on Android. skiptools/skip-android-bridge#39 will call it for the nativeString(localized:)instead of parsing the pattern itself.Testing
testLocalizableStringsDictPrintfSpecifiers(Robolectric): a%lldform withzero/one/other, an apostrophe and#in one form, braces and%%in another, and 1234 without grouping. Before this change it fails withIllegalArgumentExceptionon the braces.swift test --filter XCSkipTestspasses, includingtestLocalizedPluralStringFormattingfrom Added string pluralization support #102.Skip Pull Request Checklist:
swift test🤖 Generated with Claude Code