Closed carystanley closed 9 years ago
@carystanley that's exactly right. To implement ordinals we need to use CLDR to produce the logic per locale. this is not the first time we get this feature requests, we will evaluate it, but it doesn't belong to this repo for sure since ICU message format does not support ordinals, just like it doesn't support relative time, we can also push for that in that front.
I did some research and the CLDR has Rule-Based Number Format (RBNF) data, which includes spellout
("three"
) and ordinal
("3rd"
). As of CLDR v26, these rules are defined in ICU Message syntax — which is just like how our Intl RelativeFormat's data is defined and works.
I see a few ways we could implement ordinals:
selectordinal
to IntlMessageFormat
:This would be the easiest to implement, and not add any extra locale data to the library, but it would force the translators to add the correct ordinal suffix inside the optional parts of the messages, e.g.:
Go to the {floor, selectordinal,
=0 {ground}
one {#st}
two {#nd}
few {#rd}
other {#th}
} floor.
IntlRuleBasedNumberFormat
lib, use externally:To support automatic ordinal formatting leveraging the rules built into CLDR, we could create a new IntlRuleBasedNumberFormat
, and like IntlRelativeFormat
it would be used externally from the ICU Message string; i.e., you would format the value using IntlRuleBasedNumberFormat
before passing it to the IntlMessageFormat
instance, e.g.:
Go to the {floor} floor.
var msg = new IntlMessageFormat('Go to the {floor} floor.', 'en');
var rbnf = new IntlRuleBasedNumberFormat('en', {style: 'ordinal'});
var output = msg.format({
floor: rbnf.format(3)
});
console.log(output); // => "Go to the 3rd floor."
The benefit of this approach is that it doesn't add k-weight to IntlMessageFormat
— just like how relative time formatting is separate. The downside is that it's not built into IntlMessageFormat
, therefore deviates from the standard ICU Message. That said, at the end of the day, it would still be built into react-intl
, handlebars-intl
, and dust-intl
:-/
Using this external approach in templates would look like this; e.g., in Handlebars:
{{formatMessage (intlGet "messages.floor")
floor=(formatOrdinal 3)
}}
IntlRuleBasedNumberFormat
lib, use internally:The last option would be like option 2) and create a new IntlRuleBasedNumberFormat
lib, but also have IntlRelativeFormat
depend on it and use it internally — just like it does for Intl.NumberFormat
and Intl.DateTimeFormat
.
The difference with this approach is that it would add k-weight to the intl-messageformat
package both in terms of the runtime, and the locale data. This approach would allow for the ordinal
argument type to be used within the ICU Message strings; e.g.:
Go to the {floor, ordinal} floor.
_Edit: The ICU Message syntax defines ordinal
as an argument type; we just don't currently support it in our implementation._
What do you guys think?
It looks like Intl.MessageFormat needs a plugin system.
@juandopazo we don't need a plugin system, we just need to convince ICU folks that {floor, ordinal}
makes sense, just like {floor, number}
does it :)
@ericf my vote goes to option 2, which will pave the way to option 3, just like we did for relative
, and we can engage with ICU to try the waters there.
@caridy @juandopazo I wasn't clear before, but ordinal
is an argument type defined by the ICU Message syntax; we just don't currently support it in our implementation. I edited option 3 above to make this clear. So there's no need to convince the ICU folks, they already support it :smile:
If you look at the details of the ICU Message syntax, you'll see they have support for selectordinal
, ordinal
, and spellout
argument types — all of which we don't currently support. Note that choiceStyle
and ChoiceFormat
have been deprecated.
awesome, lets plan for that then, we need an implementer now :)
/cc @lwelti
So we can stage this by first easily adding support for selectordinal
arguments, option 1 above. @carystanley do you think that would work to unblock you?
Then we work on the automatic ordinal
argument formatting via a new IntlRuleBasedNumberFormat
lib, which will take a lot more time and effort for us to implement.
By the way, concerning ICU please reach out to us if needed, not so hard to convince, and code does talk :) icu-project.org
well, they can do that today without anything new:
Go to the {floor, select,
=0 {ground}
one {#st}
two {#nd}
few {#rd}
other {#th}
} floor.
not ideal, but at least this unblock them.
@srl295, lets start the conversation about relative time, e.g.: {dateValue, relative}
@caridy relative time sounds good to me, but probably best started at http://bugs.icu-project.org/trac/newticket . Apologies if you knew this, but the select
format in ICU was itself a Yahoo! contribution. Actually there's this ticket (note: follow the trail of 'xref' fields to find related tix) that might be interesting.
edit on consideration, I think a new ticket would be best, and reference any relevant ones you dig up, or even this thread. This is a great time to suggest changes in msgformat.
ICU ticket for relative time in messages: http://bugs.icu-project.org/trac/ticket/11409
@caridy :+1: . added a backlink here and an xref
@caridy and, the ICU ticket was moved to unscheduled. Is someone interested in contributing a C++ and Java design and implementation?
@srl295 we will try :)
@lwelti, do we have someone from your team that can work with us on this effort?
I realized that we do not have that data to support selectordinal
as I mentioned above. We could get this data from the make-plural.js
project which would give us basic ordinal support without needing to implement RBNF.
@caridy what you wrote in https://github.com/yahoo/intl-messageformat/issues/84#issuecomment-64905934 is not actually correct — select
argument types use exact matches. We currently have the cardinal pluralization rules, but we also need the ordinal ones, and with those we can support the selectordinal
argument type option #1.
I feel we should add basic ordinal support to this project by adding support for selectordinal
arguments, option #1 above. Here the tasks to implement this:
grunt-extract-cldr-data
to use make-plural
which properly supports extracting ordinal pluralization rules from the CLDR.
PR https://github.com/yahoo/grunt-extract-cldr-data/pull/2intl-messageformat-parser
so it parses selectordinal
argument types and adds a new node type to its AST.
PR https://github.com/yahoo/intl-messageformat-parser/issues/7grunt-extract-cldr-data
and intl-messageformat-parser
.
PR: #102selectordinal
argument types, and have it call the new pluralization functions created by make-plural
with true
as the second argument to the function, causing it to perform ordinal pluralization on the numeric value.
PR: #102PR #102 Implements these selectordinal
arguments, plus vast improvements to the locale data used by this package.
@ericf sorry to dig up this old issue again but the current selectordinal
only works for numbers up to 20
{rank, selectordinal,
one {#st}
two {#nd}
few {#rd}
other {#th}
}
with {rank: 21}
generates 21th
which should instead be 21st
. Same goes for all numbers ending with 1
, 2
, 3
bigger than 20
.
I'm not sure if you want to track this problem somehow.
@piuccio I tried numbers going up to 40. All work as expected. 21 generates 21st
.
I'm using latest react-intl
, don't know if you are of if that makes a difference.
Here's my code so you can try and see what's different:
export const floorMessages = (positionLowestFloor, positionHighestFloor) => {
const ordinals = 'selectordinal, one {#st} two {#nd} few {#rd} other {#th}';
return defineMessages({
singleFloor: { id: 'Floor.singleFloor', defaultMessage: `{positionLowestFloor, ${ordinals} } floor`, values: { positionLowestFloor } },
});
};
You're right, I messed up my translation files
On Wed, 7 Feb 2018, 00:03 Martin Alex Philip Dawson, < notifications@github.com> wrote:
@piuccio https://github.com/piuccio I tried numbers going up to 40. All work as expected.
Are you using latest react-intl?
Here's my code so you can try and see different:
export const floorMessages = (positionLowestFloor, positionHighestFloor) => { const ordinals = 'selectordinal, one {#st} two {#nd} few {#rd} other {#th}';
return defineMessages({ singleFloor: { id: 'Floor.singleFloor', defaultMessage:
{positionLowestFloor, ${ordinals} } floor
, values: { positionLowestFloor } }, multiFloor: { id: 'Floor.multiFloor', defaultMessage:{positionLowestFloor, ${ordinals}} to {positionHighestFloor, ${ordinals}} floor
, values: { positionLowestFloor, positionHighestFloor } }, }); };— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/yahoo/intl-messageformat/issues/84#issuecomment-363449263, or mute the thread https://github.com/notifications/unsubscribe-auth/AAphXAOBXAPp1M6bamLdX6h4F_odBPiVks5tSGmrgaJpZM4DBMRy .
It would be great if intl-messageformat supported ordinal numbers:
1st, 2nd, 3rd, 4th, 10th, 11th, 12th, 13th, 52nd, 53rd, etc...
Here is a really simple version of the logic:
I am unsure if ordinal works differently in other languages besides english