feat(intl): use a plain string translation for every plural form and match case - #246
Merged
Conversation
…match case Translation data is untyped JSON at runtime, and a plain string where `plural` or `match` expected an object of forms reached the key resolvers as is: `count in forms` threw a `TypeError` for `plural` and for `match` with `other()`, and a `forms(...)` or `cases(...)` resolver spread the string into its characters. A string translation is now the message for every form and case, which is what a locale without plural distinctions wants to write, and the input types of `plural` and `match` accept it. The `intl` size limits are re-pinned for the extra branch: `All publics` grows by 16 B and `Basic set` by 15 B gzipped.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #246 +/- ##
==========================================
- Coverage 83.32% 83.28% -0.04%
==========================================
Files 98 98
Lines 2554 2554
Branches 549 550 +1
==========================================
- Hits 2128 2127 -1
Misses 314 314
- Partials 112 113 +1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Why
Translation data is
Record<string, any>at runtime, so a locale file can hold a plain string where the scheme usespluralormatch, for example a Japanese translationattendees: '{count}人参加'next to an English{ one, other }object. That string reached the key resolvers untouched:What
matchshort-circuits a string translation: it becomes the message for every case and everypluralform,{param}placeholders included, and thecases(...)/forms(...)resolvers and key resolvers are skipped for it.matchandpluralacceptstring, so typed translation data with a string on such a key passes type-checking.pluralandmatchsections.match(bare, withcases, withother), two forplural(bare, withforms).Wrapping the string as
{ other: input }was considered and rejected: aforms({ one, other })resolver declaresonewith anundefinedvalue, socount: 1would still resolve toundefined, andmatchwithoutother('other')never looks at theotherkey.Size
The extra branch costs bytes in
match, which is part of theAll publicsandBasic setbundles. Limits are re-pinned on the 0.05 kB step:Checks
oxlint,tsc --noEmit,vitest run(122 tests) andsize-limitinpackages/intlpass.