Skip to content

Commit d008062

Browse files
authored
Merge branch 'main' into math-func
2 parents 6fce5f5 + bf65321 commit d008062

File tree

2 files changed

+268
-81
lines changed

2 files changed

+268
-81
lines changed

spec/errors.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,9 @@ does not match the expected implementation-defined format.
382382
> horse {{The value is a horse.}}
383383
> * {{The value is not one.}}
384384
> ```
385+
386+
### Unsupported Operation
387+
388+
A **_<dfn>Unsupported Operation</dfn>_** error is an implementation-specific error
389+
that occurs when a given _option_, _option_ value, _operand_ value, or some combination
390+
of these are incompatible or not supported by a given _function_ or its _function handler_.

spec/registry.md

Lines changed: 262 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,57 @@
11
# MessageFormat 2.0 Default Function Registry
22

3-
This section describes the functions for which each implementation MUST provide
4-
a _function handler_ to be conformant with this specification.
5-
6-
Implementations MAY implement additional _functions_ or additional _options_.
7-
In particular, implementations are encouraged to provide feedback on proposed
8-
_options_ and their values.
9-
10-
> [!NOTE]
11-
> The [Stability Policy](/spec#stability-policy) allows for updates to
12-
> Default Registry functions to add support for new options.
13-
> As implementations are permitted to ignore options that they do not support,
14-
> it is possible to write messages using options not defined below
15-
> which currently format with no error, but which could produce errors
16-
> when formatted with a later edition of the Default Registry.
17-
> Therefore, using options not explicitly defined here is NOT RECOMMENDED.
3+
This section defines the **standard** _functions_ which are REQUIRED for conformance with this specification,
4+
along with **optional** _functions_ that SHOULD be implemented to support
5+
additional functionality.
6+
7+
To **_<dfn>accept</dfn>_** a function means that an implementation MUST NOT
8+
emit an _Unknown Function_ error for that _function_'s _identifier_.
9+
To _accept_ an _option_ means that a _function handler_ MUST NOT
10+
emit a _Bad Option_ error for that _option_'s _identifier_ when used with the _function_
11+
it is defined for
12+
and MUST NOT emit a _Bad Option_ error for any of the _option_ values
13+
defined for that _option_.
14+
Accepting a _function_ or its _options_ does not mean that a particular output is produced.
15+
Implementations MAY emit an _Unsupported Operation_ error for _options_
16+
or _option_ values that they cannot support.
17+
18+
_Functions_ can define _options_.
19+
An _option_ can be **standard** or **optional**.
20+
21+
Implementations MUST _accept_ each **standard** _function_ and
22+
MUST _accept_ all _options_ defined as **standard** for those _functions_.
23+
24+
Implementations SHOULD _accept_ each **optional** _function_.
25+
For each such _function_, the implementation MUST accept all _options_
26+
listed as **standard** for that _function_.
27+
28+
Implementations SHOULD _accept_ _options_ that are marked as **optional**.
29+
30+
Implementations MAY _accept_ _functions_ not defined in this specification.
31+
In addition, implementations SHOULD provide mechanisms for users to
32+
register and use user-defined _functions_ and their associated _functional handlers_.
33+
Functions not defined by any version of this specification SHOULD use
34+
an implementation-defined or user-defined _namespace_.
35+
36+
Implementations MAY implement additional _options_ not defined
37+
by any version of this specification
38+
for **standard** and **optional** functions.
39+
Such _options_ MUST use an implementation-specific _namespace_.
40+
41+
Implementations MAY _accept_ additional _option_ values for _options_ defined here.
42+
However, such values might become defined with a different meaning in the future,
43+
including with a different, incompatible name
44+
or using an incompatible value space.
45+
Supporting implementation-specific _option_ values for **standard** or **optional** functions is NOT RECOMMENDED.
46+
47+
Future versions of this specification MAY define additional _options_ and _option_ values,
48+
subject to the rules in the [Stability Policy](#stability-policy),
49+
for _functions_ found in this specification.
50+
As implementations are permitted to ignore _options_ that they do not support,
51+
it is possible to write _messages_ using _options_ not defined below
52+
which currently format with no error, but which could produce errors
53+
when formatted with a later edition of this specification.
54+
Therefore, using _options_ not explicitly defined here is NOT RECOMMENDED.
1855

1956
## String Value Selection and Formatting
2057

@@ -42,12 +79,15 @@ All other values produce a _Bad Operand_ error.
4279
4380
#### Options
4481

45-
The function `:string` has no options.
82+
The function `:string` has no _options_.
4683

4784
> [!NOTE]
48-
> Proposals for string transformation options or implementation
49-
> experience with user requirements is desired during the Tech Preview.
50-
85+
> While `:string` has no built- in _options_,
86+
> _options_ in the `u:` _namespace_ can be used.
87+
> For example:
88+
>```
89+
> {$s :string u:dir=ltr u:locale=fr-CA}
90+
>```
5191
#### Resolved Value
5292
5393
The _resolved value_ of an _expression_ with a `:string` _function_
@@ -155,6 +195,25 @@ The following options and their values are required to be available on the funct
155195
- ([digit size option](#digit-size-options))
156196
- `maximumSignificantDigits`
157197
- ([digit size option](#digit-size-options))
198+
- `trailingZeroDisplay`
199+
- `auto` (default)
200+
- `stripIfInteger`
201+
- `roundingPriority`
202+
- `auto` (default)
203+
- `morePrecision`
204+
- `lessPrecision`
205+
- `roundingIncrement`
206+
- 1 (default), 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, and 5000
207+
- `roundingMode`
208+
- `ceil`
209+
- `floor`
210+
- `expand`
211+
- `trunc`
212+
- `halfCeil`
213+
- `halfFloor`
214+
- `halfExpand` (default)
215+
- `halfTrunc`
216+
- `halfEven`
158217
159218
If the _operand_ of the _expression_ is an implementation-defined type,
160219
such as the _resolved value_ of an _expression_ with a `:number` or `:integer` _annotation_,
@@ -170,37 +229,6 @@ with _options_ on the _expression_ taking priority over any option values of the
170229
> would be formatted with the resolved options
171230
> `{ notation: 'scientific', minimumFractionDigits: '1' }`.
172231
173-
> [!NOTE]
174-
> The following options and option values are being developed during the Technical Preview
175-
> period.
176-
177-
The following values for the option `style` are _not_ part of the default registry.
178-
Implementations SHOULD avoid creating options that conflict with these, but
179-
are encouraged to track development of these options during Tech Preview:
180-
- `currency`
181-
- `unit`
182-
183-
The following options are _not_ part of the default registry.
184-
Implementations SHOULD avoid creating options that conflict with these, but
185-
are encouraged to track development of these options during Tech Preview:
186-
- `currency`
187-
- valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
188-
(no default)
189-
- `currencyDisplay`
190-
- `symbol` (default)
191-
- `narrowSymbol`
192-
- `code`
193-
- `name`
194-
- `currencySign`
195-
- `accounting`
196-
- `standard` (default)
197-
- `unit`
198-
- (anything not empty)
199-
- `unitDisplay`
200-
- `long`
201-
- `short` (default)
202-
- `narrow`
203-
204232
##### Default Value of `select` Option
205233
206234
The value `plural` is the default for the option `select`
@@ -306,37 +334,6 @@ Option values with the following names are however discarded if included in the
306334
- `maximumFractionDigits`
307335
- `minimumSignificantDigits`
308336
309-
> [!NOTE]
310-
> The following options and option values are being developed during the Technical Preview
311-
> period.
312-
313-
The following values for the option `style` are _not_ part of the default registry.
314-
Implementations SHOULD avoid creating options that conflict with these, but
315-
are encouraged to track development of these options during Tech Preview:
316-
- `currency`
317-
- `unit`
318-
319-
The following options are _not_ part of the default registry.
320-
Implementations SHOULD avoid creating options that conflict with these, but
321-
are encouraged to track development of these options during Tech Preview:
322-
- `currency`
323-
- valid [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
324-
(no default)
325-
- `currencyDisplay`
326-
- `symbol` (default)
327-
- `narrowSymbol`
328-
- `code`
329-
- `name`
330-
- `currencySign`
331-
- `accounting`
332-
- `standard` (default)
333-
- `unit`
334-
- (anything not empty)
335-
- `unitDisplay`
336-
- `long`
337-
- `short` (default)
338-
- `narrow`
339-
340337
##### Default Value of `select` Option
341338
342339
The value `plural` is the default for the option `select`
@@ -445,6 +442,190 @@ The `:math` _options_ are not included in the resolved option values.
445442
446443
The _function_ `:math` performs selection as described in [Number Selection](#number-selection) below.
447444
445+
### The `:currency` function
446+
447+
The function `:currency` is a selector and formatter for currency values,
448+
which are a specialized form of numeric selection and formatting.
449+
450+
#### Operands
451+
452+
The _operand_ of the `:currency` function can be one of any number of
453+
implementation-defined types,
454+
each of which contains a numerical `value` and a `currency`;
455+
or it can be a [Number Operand](#number-operands), as long as the option
456+
`currency` is provided.
457+
The option `currency` MUST NOT be used to override the currency of an implementation-defined type.
458+
Using this option in such a case results in a _Bad Option_ error.
459+
460+
The value of the _operand_'s `currency` MUST be either a string containing a
461+
well-formed [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
462+
or an implementation-defined currency type.
463+
Although currency codes are expected to be uppercase,
464+
implementations SHOULD treat them in a case-insensitive manner.
465+
A well-formed Unicode Currency Identifier matches the production `currency_code` in this ABNF:
466+
```abnf
467+
currency_code = 3ALPHA
468+
```
469+
470+
A [Number Operand](#number-operands) without a `currency` _option_ results in a _Bad Operand_ error.
471+
472+
> [!NOTE]
473+
> For example, in ICU4J, the type `com.ibm.icu.util.CurrencyAmount` can be used
474+
> to set the amount and currency.
475+
476+
> [!NOTE]
477+
> The `currency` is only required to be well-formed rather than checked for validity.
478+
> This allows new currency codes to be defined
479+
> (there are many recent examples of this occuring).
480+
> It also avoids requiring implementations to check currency codes for validity,
481+
> although implementations are permitted to emit _Bad Option_ or _Bad Operand_ for invalid codes.
482+
483+
> [!NOTE]
484+
> For runtime environments that do not provide a ready-made data structure,
485+
> class, or type for currency values, the implementation ought to provide
486+
> a data structure, convenience function, or documentation on how to encode
487+
> the value and currency code for formatting.
488+
> For example, such an implementation might define a "currency operand"
489+
> to include a key-value structure with specific keys to be the
490+
> local currency operand, which might look like the following:
491+
> ```
492+
> {
493+
> "value": 123.45,
494+
> "currency": "EUR"
495+
> }
496+
> ```
497+
498+
#### Options
499+
500+
Some options do not have default values defined in this specification.
501+
The defaults for these options are implementation-dependent.
502+
In general, the default values for such options depend on the locale,
503+
the currency,
504+
the value of other options, or all of these.
505+
506+
Fraction digits for currency values behave differently than for other numeric formatters.
507+
The number of fraction digits displayed is usually set by the currency used.
508+
For example, USD uses 2 fraction digits, while JPY uses none.
509+
Setting some other number of `fractionDigits` allows greater precision display
510+
(such as when performing currency conversions or other specialized operations)
511+
or disabling fraction digits if set to `0`.
512+
513+
The _option_ `trailingZeroDisplay` has a value `stripIfInteger` that is useful
514+
for displaying currencies with their fraction digits removed when the fraction
515+
part of the _operand_ is zero.
516+
This is sometimes used in _messages_ to make the displayed value omit the fraction part
517+
automatically.
518+
> For example, this _message_:
519+
> ```
520+
> The special price is {$price :currency trailingZeroDisplay=stripIfInteger}.
521+
> ```
522+
> When used with the value `5.00 USD` in the `en-US` locale displays as:
523+
> ```
524+
> The special price is $5.
525+
> ```
526+
> But like this when when value is `5.01 USD`:
527+
> ```
528+
> The special price is $5.01.
529+
> ```
530+
531+
Implementations MAY internally alias option values that they do not have data or a backing implementation for.
532+
Notably, the `currencyDisplay` option has a rich set of values that mirrors developments in CLDR data.
533+
Some implementations might not be able to produce all of these formats for every currency.
534+
535+
> [!NOTE]
536+
> Except where noted otherwise, the names of _options_ and their _values_ were derived from the
537+
> [options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options)
538+
> in JavaScript's `Intl.NumberFormat`.
539+
540+
> [!NOTE]
541+
> The option `select` does not accept the value `ordinal` because selecting
542+
> currency values using ordinal rules makes no sense.
543+
544+
The following options and their values are required to be available on the function `:currency`:
545+
- `select`
546+
- `plural` (default)
547+
- `exact`
548+
- `currency`
549+
- well-formed [Unicode Currency Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeCurrencyIdentifier)
550+
(no default)
551+
- `compactDisplay` (this option only has meaning when combined with the option `notation=compact`)
552+
- `short` (default)
553+
- `long`
554+
- `notation`
555+
- `standard` (default)
556+
- `compact`
557+
- `numberingSystem`
558+
- valid [Unicode Number System Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#UnicodeNumberSystemIdentifier)
559+
(default is locale-specific)
560+
- `currencySign`
561+
- `accounting`
562+
- `standard` (default)
563+
- `currencyDisplay`
564+
- `narrowSymbol`
565+
- `symbol` (default)
566+
- `name`
567+
- `code`
568+
- `formalSymbol`
569+
- `never` (this is called `hidden` in ICU)
570+
- `useGrouping`
571+
- `auto` (default)
572+
- `always`
573+
- `never`
574+
- `min2`
575+
- `minimumIntegerDigits`
576+
- ([digit size option](#digit-size-options), default: `1`)
577+
- `fractionDigits` (unlike number/integer formats, the fraction digits for currency formatting are fixed)
578+
- `auto` (default) (the number of digits used by the currency)
579+
- ([digit size option](#digit-size-options))
580+
- `minimumSignificantDigits`
581+
- ([digit size option](#digit-size-options))
582+
- `maximumSignificantDigits`
583+
- ([digit size option](#digit-size-options))
584+
- `trailingZeroDisplay`
585+
- `auto` (default)
586+
- `stripIfInteger`
587+
- `roundingPriority`
588+
- `auto` (default)
589+
- `morePrecision`
590+
- `lessPrecision`
591+
- `roundingIncrement`
592+
- 1 (default), 2, 5, 10, 20, 25, 50, 100, 200, 250, 500, 1000, 2000, 2500, and 5000
593+
- `roundingMode`
594+
- `ceil`
595+
- `floor`
596+
- `expand`
597+
- `trunc`
598+
- `halfCeil`
599+
- `halfFloor`
600+
- `halfExpand` (default)
601+
- `halfTrunc`
602+
- `halfEven`
603+
604+
If the _operand_ of the _expression_ is an implementation-defined type,
605+
such as the _resolved value_ of an _expression_ with a `:currency` _annotation_,
606+
it can include option values.
607+
These are included in the resolved option values of the _expression_,
608+
with _options_ on the _expression_ taking priority over any option values of the _operand_.
609+
610+
> For example, the _placeholder_ in this _message_:
611+
> ```
612+
> .input {$n :currency currency=USD trailingZeroDisplay=stripIfInteger}
613+
> {{{$n :currency currencySign=accounting}}}
614+
> ```
615+
> would be formatted with the resolved options
616+
> `{ currencySign: 'accounting', trailingZeroDisplay: 'stripIfInteger', currency: 'USD' }`.
617+
618+
#### Resolved Value
619+
620+
The _resolved value_ of an _expression_ with a `:currency` _function_
621+
contains an implementation-defined currency value
622+
of the _operand_ of the annotated _expression_,
623+
together with the resolved options' values.
624+
625+
#### Selection
626+
627+
The _function_ `:currency` performs selection as described in [Number Selection](#number-selection) below.
628+
448629
### Number Operands
449630
450631
The _operand_ of a number function is either an implementation-defined type or

0 commit comments

Comments
 (0)