@@ -192,6 +192,25 @@ The following options and their values are required to be available on the funct
192192 - ([digit size option](#digit-size-options))
193193- `maximumSignificantDigits`
194194 - ([digit size option](#digit-size-options))
195+ - `trailingZeroDisplay`
196+ - `auto` (default)
197+ - `stripIfInteger`
198+ - `roundingPriority`
199+ - `auto` (default)
200+ - `morePrecision`
201+ - `lessPrecision`
202+ - `roundingIncrement`
203+ - 1 (default), 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, and 5000
204+ - `roundingMode`
205+ - `ceil`
206+ - `floor`
207+ - `expand`
208+ - `trunc`
209+ - `halfCeil`
210+ - `halfFloor`
211+ - `halfExpand` (default)
212+ - `halfTrunc`
213+ - `halfEven`
195214
196215If the _operand_ of the _expression_ is an implementation-defined type,
197216such as the _resolved value_ of an _expression_ with a `:number` or `:integer` _annotation_,
@@ -207,37 +226,6 @@ with _options_ on the _expression_ taking priority over any option values of the
207226> would be formatted with the resolved options
208227> `{ notation: 'scientific', minimumFractionDigits: '1' }`.
209228
210- > [!NOTE]
211- > The following options and option values are being developed during the Technical Preview
212- > period.
213-
214- The following values for the option `style` are _not_ part of the default registry.
215- Implementations SHOULD avoid creating options that conflict with these, but
216- are encouraged to track development of these options during Tech Preview:
217- - `currency`
218- - `unit`
219-
220- The following options are _not_ part of the default registry.
221- Implementations SHOULD avoid creating options that conflict with these, but
222- are encouraged to track development of these options during Tech Preview:
223- - `currency`
224- - valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
225- (no default)
226- - `currencyDisplay`
227- - `symbol` (default)
228- - `narrowSymbol`
229- - `code`
230- - `name`
231- - `currencySign`
232- - `accounting`
233- - `standard` (default)
234- - `unit`
235- - (anything not empty)
236- - `unitDisplay`
237- - `long`
238- - `short` (default)
239- - `narrow`
240-
241229##### Default Value of `select` Option
242230
243231The value `plural` is the default for the option `select`
@@ -343,37 +331,6 @@ Option values with the following names are however discarded if included in the
343331- `maximumFractionDigits`
344332- `minimumSignificantDigits`
345333
346- > [!NOTE]
347- > The following options and option values are being developed during the Technical Preview
348- > period.
349-
350- The following values for the option `style` are _not_ part of the default registry.
351- Implementations SHOULD avoid creating options that conflict with these, but
352- are encouraged to track development of these options during Tech Preview:
353- - `currency`
354- - `unit`
355-
356- The following options are _not_ part of the default registry.
357- Implementations SHOULD avoid creating options that conflict with these, but
358- are encouraged to track development of these options during Tech Preview:
359- - `currency`
360- - valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
361- (no default)
362- - `currencyDisplay`
363- - `symbol` (default)
364- - `narrowSymbol`
365- - `code`
366- - `name`
367- - `currencySign`
368- - `accounting`
369- - `standard` (default)
370- - `unit`
371- - (anything not empty)
372- - `unitDisplay`
373- - `long`
374- - `short` (default)
375- - `narrow`
376-
377334##### Default Value of `select` Option
378335
379336The value `plural` is the default for the option `select`
@@ -418,6 +375,190 @@ together with the resolved options' values.
418375
419376The _function_ `:integer` performs selection as described in [Number Selection](#number-selection) below.
420377
378+ ### The `:currency` function
379+
380+ The function `:currency` is a selector and formatter for currency values,
381+ which are a specialized form of numeric selection and formatting.
382+
383+ #### Operands
384+
385+ The _operand_ of the `:currency` function can be one of any number of
386+ implementation-defined types,
387+ each of which contains a numerical `value` and a `currency`;
388+ or it can be a [Number Operand](#number-operands), as long as the option
389+ `currency` is provided.
390+ The option `currency` MUST NOT be used to override the currency of an implementation-defined type.
391+ Using this option in such a case results in a _Bad Option_ error.
392+
393+ The value of the _operand_'s `currency` MUST be either a string containing a
394+ well-formed [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
395+ or an implementation-defined currency type.
396+ Although currency codes are expected to be uppercase,
397+ implementations SHOULD treat them in a case-insensitive manner.
398+ A well-formed Unicode Currency Identifier matches the production `currency_code` in this ABNF:
399+ ```abnf
400+ currency_code = 3ALPHA
401+ ```
402+
403+ A [ Number Operand] ( #number-operands ) without a ` currency ` _ option_ results in a _ Bad Operand_ error.
404+
405+ > [ !NOTE]
406+ > For example, in ICU4J, the type ` com.ibm.icu.util.CurrencyAmount ` can be used
407+ > to set the amount and currency.
408+
409+ > [ !NOTE]
410+ > The ` currency ` is only required to be well-formed rather than checked for validity.
411+ > This allows new currency codes to be defined
412+ > (there are many recent examples of this occuring).
413+ > It also avoids requiring implementations to check currency codes for validity,
414+ > although implementations are permitted to emit _ Bad Option_ or _ Bad Operand_ for invalid codes.
415+
416+ > [ !NOTE]
417+ > For runtime environments that do not provide a ready-made data structure,
418+ > class, or type for currency values, the implementation ought to provide
419+ > a data structure, convenience function, or documentation on how to encode
420+ > the value and currency code for formatting.
421+ > For example, such an implementation might define a "currency operand"
422+ > to include a key-value structure with specific keys to be the
423+ > local currency operand, which might look like the following:
424+ > ```
425+ > {
426+ > "value": 123.45,
427+ > "currency": "EUR"
428+ > }
429+ > ```
430+
431+ #### Options
432+
433+ Some options do not have default values defined in this specification.
434+ The defaults for these options are implementation-dependent.
435+ In general, the default values for such options depend on the locale,
436+ the currency,
437+ the value of other options, or all of these.
438+
439+ Fraction digits for currency values behave differently than for other numeric formatters.
440+ The number of fraction digits displayed is usually set by the currency used.
441+ For example, USD uses 2 fraction digits, while JPY uses none.
442+ Setting some other number of `fractionDigits` allows greater precision display
443+ (such as when performing currency conversions or other specialized operations)
444+ or disabling fraction digits if set to `0`.
445+
446+ The _option_ `trailingZeroDisplay` has a value `stripIfInteger` that is useful
447+ for displaying currencies with their fraction digits removed when the fraction
448+ part of the _operand_ is zero.
449+ This is sometimes used in _messages_ to make the displayed value omit the fraction part
450+ automatically.
451+ > For example, this _message_:
452+ > ```
453+ > The special price is {$price :currency trailingZeroDisplay=stripIfInteger}.
454+ > ```
455+ > When used with the value `5.00 USD` in the `en-US` locale displays as:
456+ > ```
457+ > The special price is $5.
458+ > ```
459+ > But like this when when value is `5.01 USD`:
460+ > ```
461+ > The special price is $5.01.
462+ > ```
463+
464+ Implementations MAY internally alias option values that they do not have data or a backing implementation for.
465+ Notably, the `currencyDisplay` option has a rich set of values that mirrors developments in CLDR data.
466+ Some implementations might not be able to produce all of these formats for every currency.
467+
468+ > [!NOTE]
469+ > Except where noted otherwise, the names of _options_ and their _values_ were derived from the
470+ > [options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options)
471+ > in JavaScript's `Intl.NumberFormat`.
472+
473+ > [!NOTE]
474+ > The option `select` does not accept the value `ordinal` because selecting
475+ > currency values using ordinal rules makes no sense.
476+
477+ The following options and their values are required to be available on the function `:currency`:
478+ - `select`
479+ - `plural` (default)
480+ - `exact`
481+ - `currency`
482+ - well-formed [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
483+ (no default)
484+ - `compactDisplay` (this option only has meaning when combined with the option `notation=compact`)
485+ - `short` (default)
486+ - `long`
487+ - `notation`
488+ - `standard` (default)
489+ - `compact`
490+ - `numberingSystem`
491+ - valid [Unicode Number System Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeNumberSystemIdentifier)
492+ (default is locale-specific)
493+ - `currencySign`
494+ - `accounting`
495+ - `standard` (default)
496+ - `currencyDisplay`
497+ - `narrowSymbol`
498+ - `symbol` (default)
499+ - `name`
500+ - `code`
501+ - `formalSymbol`
502+ - `never` (this is called `hidden` in ICU)
503+ - `useGrouping`
504+ - `auto` (default)
505+ - `always`
506+ - `never`
507+ - `min2`
508+ - `minimumIntegerDigits`
509+ - ([digit size option](#digit-size-options), default: `1`)
510+ - `fractionDigits` (unlike number/integer formats, the fraction digits for currency formatting are fixed)
511+ - `auto` (default) (the number of digits used by the currency)
512+ - ([digit size option](#digit-size-options))
513+ - `minimumSignificantDigits`
514+ - ([digit size option](#digit-size-options))
515+ - `maximumSignificantDigits`
516+ - ([digit size option](#digit-size-options))
517+ - `trailingZeroDisplay`
518+ - `auto` (default)
519+ - `stripIfInteger`
520+ - `roundingPriority`
521+ - `auto` (default)
522+ - `morePrecision`
523+ - `lessPrecision`
524+ - `roundingIncrement`
525+ - 1 (default), 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, and 5000
526+ - `roundingMode`
527+ - `ceil`
528+ - `floor`
529+ - `expand`
530+ - `trunc`
531+ - `halfCeil`
532+ - `halfFloor`
533+ - `halfExpand` (default)
534+ - `halfTrunc`
535+ - `halfEven`
536+
537+ If the _operand_ of the _expression_ is an implementation-defined type,
538+ such as the _resolved value_ of an _expression_ with a `:currency` _annotation_,
539+ it can include option values.
540+ These are included in the resolved option values of the _expression_,
541+ with _options_ on the _expression_ taking priority over any option values of the _operand_.
542+
543+ > For example, the _placeholder_ in this _message_:
544+ > ```
545+ > .input {$n :currency currency=USD trailingZeroDisplay=stripIfInteger}
546+ > {{{$n :currency currencySign=accounting}}}
547+ > ```
548+ > would be formatted with the resolved options
549+ > `{ currencySign: 'accounting', trailingZeroDisplay: 'stripIfInteger', currency: 'USD' }`.
550+
551+ #### Resolved Value
552+
553+ The _resolved value_ of an _expression_ with a `:currency` _function_
554+ contains an implementation-defined currency value
555+ of the _operand_ of the annotated _expression_,
556+ together with the resolved options' values.
557+
558+ #### Selection
559+
560+ The _function_ `:currency` performs selection as described in [Number Selection](#number-selection) below.
561+
421562### Number Operands
422563
423564The _operand_ of a number function is either an implementation-defined type or
0 commit comments