-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unified API for number formatting #215
Comments
What about use cases where i want my locale set to US-en, but I’m originally from Europe and prefer always seeing a I do very much love the idea that the common defaults are so easy and intuitive, but what about the use cases that require maximal configuration? |
I was thinking custom symbols and digits are material for another proposal. #175 adds a On the other hand, I'm happy to propose a single, larger proposal that adds support for symbols, sign display (#163), alternate currency symbols (#200), algorithmic numbering systems (#95), and additional grouping strategies all in one. |
@sffc at first glance this looks very promising. As for changing the spec to align with those eight axes, it seems doable! @littledan can we have this in the agenda for this week? @ljharb there are many things that you cannot do with |
This is no different, as @caridy pointed out, to other intl settings. We hope to start using unicode extension keys soon to allow for building locales with such (or similar) customizations. I like this proposal a lot. |
@caridy @sffc added this topic to the agenda for the Friday meeting. Many of the open feature requests we have are about adding more options to formatters. I'm happy if we can solve these feature requests within a framework that's more cleaned-up and future-proof. Would such a similar design exercise make sense for DateTimeFormat, which also has many feature requests for additional options? |
Overall, I liked the proposal too! I liked the way you grouped the orthogonal settings. Although I (personally) don't like NumberFormat handling the unit group (because API gets too cluttered), currency formatting is already here, so your idea of bringing UnitFormat too has an alibi. Some questions:
Please, (a) why do you consider percent as a unit, but compact as a notation? (b) In your ICU proposal, unit=percent format 1 as "1%", I assume we are not going to change that in
Setting a default currency is an anti-pattern and should be avoided. UTS#35 says "Note: Currency values should never be interchanged without a known currency code. You never want the number 3.5 interpreted as $3.50 by one user and €3.50 by another. Locale data contains localization information for currencies, not a currency value for a country. A currency amount logically consists of a numeric value, plus an accompanying currency code (or equivalent). The currency code may be implicit in a protocol, such as where USD is implicit. But if the raw numeric value is transmitted without any context, then it has no definitive interpretation. " Low level question that perhaps could be saved & defered for later...
Note "maximum significant digits" doesn't always mean "maximum digits", for example maxSig=2 formats 1234 as "1200" (4 digits). I believe this doesn't affect your overall proposal, but wanted to mention/check since it's emphasized in the proposal (Why did you rename Significant Digits to just Digits?).
I agree with you. They could live together as in you examplify with minInt=5 and maxSig=3 should format 1234 as "01230".
For notation, you suggest the style (compact) and form (short) in the same value, but for unit there are two options (measureUnit and measureUnitWidth). Should we have an additional option for form too?
Please, what's the motivation to use |
A notation affects the way that the decimal stem is displayed; a unit affects the thing that is being measured. For example, one could reasonably say something like, "the inflation rate is 2K percent!" (unit = percent, unitWidth = long-name, notation = compact-short), but it makes no sense to combine percent with other units (currency/measure) or compact with other notations (scientific). CLDR also has an active suggestion to add percent as a measure unit.
If we were designing new API, I would suggest removing the x100 for reasons stated in the ICU design document, but I do not feel strongly enough to advocate changing the behavior of old API.
Good catch! I didn't realize that the old API throws an exception in this case. I will update the OP.
I don't see a reason to propose that for Ecma 402 though.
It could be. I put them together because for compact, there are only two options, but for measure, the number of choices is large and will continually grow if combined; for example, it is clunky to say, "distance-meter-narrow", "distance-meter-short", "distance-meter-wide", "distance-inch-narrow", and so on. The width on measure units could also be seen as optional, whereas for compact notation, having two string keys requires that the user make the choice. However, I can be convinced otherwise.
Yes, distinguishing it from currency and percent is the motivation, but I can be convinced otherwise. I put both options in the OP (I called them 1a and 1b). |
Today there was discussion about whether ICU could add a C API to help implementers. Here is an ICU bug to track that discussion. Please comment: |
What are the next steps on this proposal? |
@sffc if I recall from the meeting the plan was for you to start a repo and document your proposal in a README. We offered to help you from there to get the spec draft. |
How do I start the repo? Is there a template? Do I need access to the tc39 organization (which I don't seem to have)? |
https://github.com/tc39/template-for-proposals , you shouldn’t need any access. |
@sffc Just create a repo under your own account; we can then go through the process of transferring to tc39 a little later. |
Did I do it right? https://github.com/sffc/proposal-unified-intl-numberformat |
Seems like the right format for a repo. Next step is for you to put your proposal in there. It can be in form of a .md file with description of proposed changes to the NumberFormat API. Once that's done we can discuss the proposal and one of us will take your proposal and translate it into a spec file as a PR in that repo. |
|
#404 has been merged. |
For the past year and a half, I have done extensive design work on number formatting APIs in ICU. There are many things I have learned, which I believe could lead to a simpler way to integrate the many number formatting features that have been requested for ECMA 402.
For more background, please read my ICU design doc and review my presentation from the 2018 Internationalization and Unicode Conference.
The Eight Orthogonal Settings
Older APIs for number formatting, such as ICU DecimalFormat, are composed of many settings (over 40 of them) that often conflict with one another. For example, the API allows mixing specifications for fraction digits, significant digits, rounding increment, and currency rules, yielding behavior that is often ill-defined. There are also settings that are too broad: for example, the "style" attribute in both ECMA 402 and ICU DecimalFormat supports standard, integer, percent, currency, and scientific formatting (ICU-only), but does not allow for combining them; for example, scientific notation with percent. It's also confusing that even if you set a currency, you need to enable the currency "style" in order for it to be displayed.
I found eight new settings that have full coverage of the DecimalFormat functionality. They are "orthogonal", meaning that your choice for one does not conflict with your choice for any other. You can choose only one option for each of the eight settings.
You can combine these in any way you like: for example, you are able to have scientific notation, a measure unit, round to the nearest integer, enable grouping, using native arabic digits, show the sign on positive numbers, pad with two zeros, and show the decimal separator.
What this can mean for ECMA 402
The Intl.NumberFormat API is clearly inspired by ICU DecimalFormat. Although it has some of the "bad" settings that I pointed out from DecimalFormat, the existing subset is small enough that we can expand Intl.NumberFormat to be more powerful without creating a whole new API and confusing users.
For reference, here are the existing settings that affect number formatting:
Conceptually, consider Intl.NumberFormat to internally be composed of the eight options listed above. The existing settings can control the eight options as follows:
currency
to be specified; throw an exception otherwise. (This is the current behavior)currency
should override a setting instyle
.style: "currency"
in order to display the currency specified in thecurrency
option. This would be a behavior change.style
orcurrency
setting.Now the fun part. With this change to how number formatting is performed conceptually, the following settings can be easily added.
unit: "length-meter"
using the official CLDR name of the unit with the default display width.measureUnit: { name: "length-meter", width: "narrow" }
to customize the display width.{measureUnit: "length-meter", measureUnitWidth: "narrow" }
. This clutters the top-level namespace but is closer to the precedent set by currencies.measureUnit: { usage: "length" }
in the future to automatically select the appropriate unit for a locale (miles in the US, kilometers elsewhere).unit
instead ofmeasureUnit
.unit
orperUnit
notation: { type: "scientific", minimumExponentDigits: 2 }
More can be added, but these two are a good place to start. You will be able to do this (Option 1a):
Or, option 1b:
Summary of changes
currency
should not require that you also setstyle: "currency"
.unit
ormeasureUnit
key as an option as described above.perUnit
orperMeasureUnit
key as an option as described above.unitWidth
ormesasureUnitWidth
key as described above.notation
key as an option, with choices for scientific and compact notation, as described above.Option 2: Fewer changes to existing behavior
Although it still seems conterintuitive to me that
Intl.NumberFormat("en",{currency:"EUR"})
doesn't display the currency symbol, I understand that there is a desire to maintain backwards compatibility. Another option, which would be more consistent with the current design, would be to add "measure" as an option to thestyle
key. Thestyle
key could be seen as a mandatory option for Ecma 402 to toggle between the four flavors of units that we support (no unit, percent, currency, and measure). That is,Even with Option 2, I advocate decoupling
minimumIntegerDigits
from significant digits. That simply looks like a mistake to me in the original specification.To-do items
The text was updated successfully, but these errors were encountered: