Skip to content
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

Define currency & unit formatting #908

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 65 additions & 78 deletions spec/registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ the value of other options, or both.
> [options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options)
> in JavaScript's `Intl.NumberFormat`.

The following options and their values are required to be available on the function `:number`:
Except where indicated otherwise,
the following options and their values are
REQUIRED to be available on the function `:number`:
Comment on lines +111 to +113
Copy link
Member

Choose a reason for hiding this comment

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

In this case, some option values are optional, but none of the options are. This reads in a kind of chewy way. Perhaps:

Suggested change
Except where indicated otherwise,
the following options and their values are
REQUIRED to be available on the function `:number`:
The following _options_ MUST be available on the function `:number`.
Except where marked `OPTIONAL`, _option_ values MUST be available
on the function `:number`:

- `select`
- `plural` (default; see [Default Value of `select` Option](#default-value-of-select-option) below)
- `ordinal`
Expand All @@ -132,7 +134,9 @@ The following options and their values are required to be available on the funct
- `never`
- `style`
- `decimal` (default)
- `percent` (see [Percent Style](#percent-style) below)
- `percent` (see [Percent Formatting](#percent-formatting) below)
- `currency` (OPTIONAL, see [Currency Formatting](#currency-formatting) below)
- `unit` (OPTIONAL, see [Unit Formatting](#unit-formatting) below)
Comment on lines +138 to +139
Copy link
Member

Choose a reason for hiding this comment

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

In my comment on 838, I suggested that we might want to break these into separate functions. There is a certain appeal to that, particularly since the options interact and since we want to encourage structured monetary and unit types.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Eh, that probably works for me too. What about percent formatting? Should that have its own function as well?

Copy link
Member

Choose a reason for hiding this comment

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

I think percent is fine where it is? It's more like scientific or other presentational gorp for formatting a pure number (you never really see a Percent type walking about). I could be convinced otherwise, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We do also apply this transform to percentage values:

When implementing `style=percent`, the numeric value of the _operand_
MUST be multiplied by 100 for the purposes of formatting.

If there's reason enough to define :unit and :currency, it would make it much easier to also define :percent, and not allow any of these to be used as operands.

Copy link
Member

Choose a reason for hiding this comment

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

The transformation for percents is multiplying a number/moving the radix. It doesn't require changing the type or any external data. We could add a per-mille formattnig too and @macchiati has proposed adding offset. These are all pure number things, which is why I'd keep them together with :number/:integer.

Units and currencies have a host of specialized options and accept different types. That's why I'd separate them: they are only numbers because they contain numeric values and want to select like numbers.

I wouldn't object to providing a :percent function. I don't think it is required that we do so, obviously. But maybe we do it for consistency?

- `useGrouping`
- `auto` (default)
- `always`
Expand Down Expand Up @@ -163,37 +167,6 @@ with _options_ on the _expression_ taking priority over any option values of the
> would be formatted with the resolved options
> `{ notation: 'scientific', minimumFractionDigits: '1' }`.

> [!NOTE]
> The following options and option values are being developed during the Technical Preview
> period.

The following values for the option `style` are _not_ part of the default registry.
Implementations SHOULD avoid creating options that conflict with these, but
are encouraged to track development of these options during Tech Preview:
- `currency`
- `unit`

The following options are _not_ part of the default registry.
Implementations SHOULD avoid creating options that conflict with these, but
are encouraged to track development of these options during Tech Preview:
- `currency`
- valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
(no default)
- `currencyDisplay`
- `symbol` (default)
- `narrowSymbol`
- `code`
- `name`
- `currencySign`
- `accounting`
- `standard` (default)
- `unit`
- (anything not empty)
- `unitDisplay`
- `long`
- `short` (default)
- `narrow`

##### Default Value of `select` Option

The value `plural` is the default for the option `select`
Expand All @@ -216,7 +189,8 @@ but can cause problems in target locales that the original developer is not cons
> The `one` variant is needed by languages such as Polish or Russian.
> Such locales typically also require other keywords such as `two`, `few`, and `many`.

##### Percent Style
##### Percent Formatting

When implementing `style=percent`, the numeric value of the _operand_
MUST be multiplied by 100 for the purposes of formatting.

Expand All @@ -227,6 +201,58 @@ MUST be multiplied by 100 for the purposes of formatting.
> should format in a manner similar to:
> > The total was 50%.

##### Currency Formatting

Implementations MAY support formatting a numeric value together with its currency
when the option `style` is assigned the value `currency`.

If an implementation supports currency formatting,
it SHOULD define and support an implementation-defined _operand_ value
that combines a value together with its currency
expressed as a valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier).
eemeli marked this conversation as resolved.
Show resolved Hide resolved

If an implementation supports currency formatting,
the following options and their values are REQUIRED to be available on the function `:number`
when `style=currency` is set:
- `currencyDisplay`
- `symbol` (default)
- `narrowSymbol`
- `code`
- `name`
- `currencySign`
- `accounting`
- `standard` (default)

If an implementation supports currency formatting,
it MAY make the following option available on the function `:number`
Copy link
Member

Choose a reason for hiding this comment

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

This should not be optional for implementation for the reasons I cited in #838. Best practices are cool, but users should not be require to box up currency values in their legacy applications.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not sure that I understand your comment here. Do you mean that we ought to require all implementations to support an option specifying a currency code?

Copy link
Member

Choose a reason for hiding this comment

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

No, but if you support style=currency then you must support the currency option. This says MAY.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't see why such a requirement ought to be placed on all implementations that support currency formatting. I agree with @macchiati in #838 (comment) that this can be solved in user-space instead.

Copy link
Member

Choose a reason for hiding this comment

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

It might be solved in the user space. Users are encouraged to do so.

But my experience is that there are many applications that are mono-currency or which provide the currency contextually (at the document/record/transaction level). I see these people who are somewhere along the internationalization curve and it is a hard sell to get them to refactor their application just to format a number as a currency.

There are many runtime environments in which there is no currency value class/object/structure built-in: people have invented their own. Providing a way for these applications to work reasonably I think is important too.

But, finally, I think the key thing is that our functions/option sets should be as portable as possible. It simplifies the work for tools and editors and the learning curve of developers. Where we have optional functionality, the package should be as consistent as possible. Implementations can extend it, but those options will (we hope) be namespaced.

when `style=currency` is set:
- `currency`
- valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
eemeli marked this conversation as resolved.
Show resolved Hide resolved
(no default)

##### Unit Formatting

Implementations MAY support formatting a value together with its unit
eemeli marked this conversation as resolved.
Show resolved Hide resolved
when the option `style` is assigned the value `unit`.

If an implementation supports unit formatting,
it SHOULD define and support an implementation-defined _operand_ value
that combines a value together with its unit identifier.

If an implementation supports unit formatting,
the following option is REQUIRED to be available on the function `:number`
when `style=unit` is set:
- `unitDisplay`
- `long`
- `short` (default)
- `narrow`

If an implementation supports unit formatting,
it MAY make the following option available on the function `:number`
when `style=unit` is set:
- `unit`
- (anything not empty)

#### Selection

The _function_ `:number` performs selection as described in [Number Selection](#number-selection) below.
Expand Down Expand Up @@ -260,7 +286,7 @@ the value of other options, or both.
> [options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options)
> in JavaScript's `Intl.NumberFormat`.

The following options and their values are required in the default registry to be available on the
The following options and their values are REQUIRED in the default registry to be available on the
function `:integer`:
- `select`
- `plural` (default)
Expand All @@ -275,9 +301,6 @@ function `:integer`:
- `exceptZero`
- `negative`
- `never`
- `style`
- `decimal` (default)
- `percent` (see [Percent Style](#percent-style) below)
- `useGrouping`
- `auto` (default)
- `always`
Expand All @@ -294,41 +317,16 @@ In general, these are included in the resolved option values of the _expression_
with _options_ on the _expression_ taking priority over any option values of the _operand_.
Option values with the following names are however discarded if included in the _operand_:
- `compactDisplay`
- `currency`
- `currencyDisplay`
- `currencySign`
- `notation`
- `minimumFractionDigits`
- `maximumFractionDigits`
- `minimumSignificantDigits`

> [!NOTE]
> The following options and option values are being developed during the Technical Preview
> period.

The following values for the option `style` are _not_ part of the default registry.
Implementations SHOULD avoid creating options that conflict with these, but
are encouraged to track development of these options during Tech Preview:
- `currency`
- `unit`

The following options are _not_ part of the default registry.
Implementations SHOULD avoid creating options that conflict with these, but
are encouraged to track development of these options during Tech Preview:
- `currency`
- valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
(no default)
- `currencyDisplay`
- `symbol` (default)
- `narrowSymbol`
- `code`
- `name`
- `currencySign`
- `accounting`
- `standard` (default)
- `style`
- `unit`
- (anything not empty)
- `unitDisplay`
- `long`
- `short` (default)
- `narrow`

##### Default Value of `select` Option

Expand All @@ -352,17 +350,6 @@ but can cause problems in target locales that the original developer is not cons
> The `one` variant is needed by languages such as Polish or Russian.
> Such locales typically also require other keywords such as `two`, `few`, and `many`.

##### Percent Style
When implementing `style=percent`, the numeric value of the _operand_
MUST be multiplied by 100 for the purposes of formatting.

> For example,
> ```
> The total was {0.5 :number style=percent}.
> ```
> should format in a manner similar to:
> > The total was 50%.

#### Selection

The _function_ `:integer` performs selection as described in [Number Selection](#number-selection) below.
Expand Down