Skip to content

Commit 7f9a4de

Browse files
eemeliaphillipscatamorphism
authored
Add u: options namespace (#846)
* Move spec/registry.md -> spec/registry/default.md * Add Unicode Registry definition * Refer to BCP47, add note about only requiring normal tags * Call it a namespace * Apply suggestions from code review Co-authored-by: Addison Phillips <addison@unicode.org> * Fix test file reference Co-authored-by: Tim Chevalier <tjc@igalia.com> * Apply suggestions from code review * Update spec/u-namespace.md Co-authored-by: Eemeli Aro <eemeli@mozilla.com> * Apply suggestions from code review Co-authored-by: Addison Phillips <addison@unicode.org> * Apply suggestions from code review Co-authored-by: Addison Phillips <addison@unicode.org> * Add mention of functions to namespace description --------- Co-authored-by: Addison Phillips <addison@unicode.org> Co-authored-by: Tim Chevalier <tjc@igalia.com>
1 parent efde4ff commit 7f9a4de

File tree

6 files changed

+240
-3
lines changed

6 files changed

+240
-3
lines changed

spec/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
1. [Resolution Errors](errors.md#resolution-errors)
1818
1. [Message Function Errors](errors.md#message-function-errors)
1919
1. [Default Function Registry](registry.md)
20+
1. [`u:` Namespace](u-namespace.md)
2021
1. [Formatting](formatting.md)
2122
1. [Interchange data model](data-model/README.md)
2223

spec/formatting.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,22 @@ the following steps are taken:
260260
261261
3. Perform _option resolution_.
262262
263-
4. Call the _function handler_ with the following arguments:
263+
4. Determine the _function context_ for calling the _function handler_.
264264
265-
- The current _locale_.
265+
The **_<dfn>function context</dfn>_** contains the context necessary for
266+
the _function handler_ to resolve the _expression_. This includes:
267+
268+
- The current _locale_,
269+
potentially including a fallback chain of locales.
270+
- The base directionality of the _message_ and its _text_ tokens.
271+
272+
If the resolved mapping of _options_ includes any _`u:` options_
273+
supported by the implementation, process them as specified.
274+
Such `u:` options MAY be removed from the resolved mapping of _options_.
275+
276+
5. Call the function implementation with the following arguments:
277+
278+
- The _function context_.
266279
- The resolved mapping of _options_.
267280
- If the _expression_ includes an _operand_, its _resolved value_.
268281
@@ -272,7 +285,7 @@ the following steps are taken:
272285
as long as reasonable precautions are taken to keep the function interface
273286
simple and minimal, and avoid introducing potential security vulnerabilities.
274287
275-
5. If the call succeeds,
288+
6. If the call succeeds,
276289
resolve the value of the _expression_ as the result of that function call.
277290
278291
If the call fails or does not return a valid value,
@@ -345,6 +358,10 @@ The _resolved value_ of _markup_ includes the following fields:
345358
- The _identifier_ of the _markup_
346359
- The resolved _options_ values after _option resolution_.
347360
361+
If the resolved mapping of _options_ includes any _`u:` options_
362+
supported by the implementation, process them as specified.
363+
Such `u:` options MAY be removed from the resolved mapping of _options_.
364+
348365
The resolution of _markup_ MUST always succeed.
349366
350367
### Fallback Resolution

spec/u-namespace.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# MessageFormat 2.0 Unicode Namespace
2+
3+
The `u:` _namespace_ is reserved for the definition of _options_
4+
which affect the _function context_ of the specific _expressions_
5+
in which they appear,
6+
or for the definition of _options_ that are universally applicable
7+
rather than function-specific.
8+
It might also be used to define _functions_ in a future release.
9+
10+
The CLDR Technical Committee of the Unicode Consortium
11+
manages the specification for this namespace, hence the name `u:`.
12+
13+
## Options
14+
15+
This section describes common **_<dfn>`u:` options</dfn>_** which each implementation SHOULD support
16+
for all _functions_ and _markup_.
17+
18+
### `u:id`
19+
20+
A string value that is included as an `id` or other suitable value
21+
in the formatted parts for the _placeholder_,
22+
or any other structured formatted results.
23+
24+
Ignored when formatting a message to a string.
25+
26+
The value of the `u:id` _option_ MUST be a _literal_ or a
27+
_variable_ whose _resolved value_ is either a string
28+
or can be resolved to a string without error.
29+
For other values, a _Bad Option_ error is emitted
30+
and the `u:id` option is ignored.
31+
32+
### `u:locale`
33+
34+
Replaces the _locale_ defined in the _function context_ for this _expression_.
35+
36+
A comma-delimited list consisting of
37+
well-formed [BCP 47](https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
38+
language tags,
39+
or an implementation-defined list of such tags.
40+
41+
If this option is set on _markup_, a _Bad Option_ error is emitted
42+
and the value of the `u:locale` option is ignored.
43+
44+
During processing, the `u:locale` option
45+
MUST be removed from the resolved mapping of _options_
46+
before calling the _function handler_.
47+
48+
Values matching the following ABNF are always accepted:
49+
```abnf
50+
u-locale-option = unicode_bcp47_locale_id *(o "," o unicode_bcp47_locale_id)
51+
```
52+
using `unicode_bcp47_locale_id` as defined for
53+
[Unicode Locale Identifier](https://cldr-smoke.unicode.org/spec/main/ldml/tr35.html#unicode_bcp47_locale_id).
54+
55+
Implementations MAY support additional language tags,
56+
such as private-use or grandfathered tags,
57+
or tags using `_` instead of `-` as a separator.
58+
When the value of `u:locale` is set by a _variable_,
59+
implementations MAY support non-string values otherwise representing locales.
60+
61+
Implementations MAY emit a _Bad Option_ error
62+
and MAY ignore the value of the `u:locale` _option_ as a whole
63+
or any of the entries in the list of language tags.
64+
This might be because the locale specified is not supported
65+
or because the language tag is not well-formed,
66+
not valid, or some other reason.
67+
68+
### `u:dir`
69+
70+
Replaces the base directionality defined in
71+
the _function context_ for this _expression_.
72+
73+
If this option is set on _markup_, a _Bad Option_ error is emitted
74+
and the value of the `u:dir` option is ignored.
75+
76+
During processing, the `u:dir` option
77+
MUST be removed from the resolved mapping of _options_
78+
before calling the _function handler_.
79+
80+
The value of the `u:dir` _option_ MUST be one of the following _literal_ values
81+
or a _variable_ whose _resolved value_ is one of these _literals_:
82+
- `ltr`: left-to-right directionality
83+
- `rtl`: right-to-left directionality
84+
- `auto`: directionality determined from _expression_ contents
85+
86+
For other values, a _Bad Option_ error is emitted
87+
and the value of the `u:dir` option is ignored.

test/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ These test files are intended to be useful for testing multiple different messag
1010
- `data-model-errors.json` - Strings that should produce a Data Model Error when processed.
1111
Error names are defined in ["MessageFormat 2.0 Errors"](../spec/errors.md) in the spec.
1212

13+
- `u-options.json` — Test cases for the `u:` options, using built-in functions.
14+
1315
- `functions/` — Test cases that correspond to built-in functions.
1416
The behaviour of the built-in formatters is implementation-specific so the `exp` field is often
1517
omitted and assertions are made on error cases.
@@ -21,6 +23,7 @@ Some examples of test harnesses using these tests, from the source repository:
2123
- [Formatting tests](https://github.com/messageformat/messageformat/blob/11c95dab2b25db8454e49ff4daadb817e1d5b770/packages/mf2-messageformat/src/messageformat.test.ts)
2224

2325
A [JSON schema](./schemas/) is included for the test files in this repository.
26+
2427
## Error Codes
2528

2629
The following table relates the error names used in the [JSON schema](./schemas/)

test/schemas/v0/tests.schema.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@
269269
"name": {
270270
"type": "string"
271271
},
272+
"id": {
273+
"type": "string"
274+
},
272275
"options": {
273276
"type": "object"
274277
}

test/tests/u-options.json

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/unicode-org/message-format-wg/main/test/schemas/v0/tests.schema.json",
3+
"scenario": "u: Options",
4+
"description": "Common options affecting the function context",
5+
"defaultTestProperties": {
6+
"locale": "en-US"
7+
},
8+
"tests": [
9+
{
10+
"src": "{#tag u:id=x}content{/ns:tag u:id=x}",
11+
"exp": "content",
12+
"expParts": [
13+
{
14+
"type": "markup",
15+
"kind": "open",
16+
"id": "x",
17+
"name": "tag"
18+
},
19+
{
20+
"type": "literal",
21+
"value": "content"
22+
},
23+
{
24+
"type": "markup",
25+
"kind": "close",
26+
"id": "x",
27+
"name": "tag"
28+
}
29+
]
30+
},
31+
{
32+
"src": "{#tag u:dir=rtl u:locale=ar}content{/ns:tag}",
33+
"exp": "content",
34+
"expErrors": [{ "type": "bad-option" }, { "type": "bad-option" }],
35+
"expParts": [
36+
{
37+
"type": "markup",
38+
"kind": "open",
39+
"name": "tag"
40+
},
41+
{
42+
"type": "literal",
43+
"value": "content"
44+
},
45+
{
46+
"type": "markup",
47+
"kind": "close",
48+
"name": "tag"
49+
}
50+
]
51+
},
52+
{
53+
"src": "hello {4.2 :number u:locale=fr}",
54+
"exp": "hello 4,2"
55+
},
56+
{
57+
"src": "hello {world :string u:dir=ltr u:id=foo}",
58+
"exp": "hello world",
59+
"expParts": [
60+
{
61+
"type": "literal",
62+
"value": "hello "
63+
},
64+
{
65+
"type": "string",
66+
"source": "|world|",
67+
"dir": "ltr",
68+
"id": "foo",
69+
"value": "world"
70+
}
71+
]
72+
},
73+
{
74+
"src": "hello {world :string u:dir=rtl}",
75+
"exp": "hello \u2067world\u2069",
76+
"expParts": [
77+
{
78+
"type": "literal",
79+
"value": "hello "
80+
},
81+
{
82+
"type": "string",
83+
"source": "|world|",
84+
"dir": "rtl",
85+
"value": "world"
86+
}
87+
]
88+
},
89+
{
90+
"src": "hello {world :string u:dir=auto}",
91+
"exp": "hello \u2068world\u2069",
92+
"expParts": [
93+
{
94+
"type": "literal",
95+
"value": "hello "
96+
},
97+
{
98+
"type": "string",
99+
"source": "|world|",
100+
"dir": "auto",
101+
"value": "world"
102+
}
103+
]
104+
},
105+
{
106+
"locale": "ar",
107+
"src": "أهلاً {بالعالم :string u:dir=rtl}",
108+
"exp": "أهلاً \u2067بالعالم\u2069"
109+
},
110+
{
111+
"locale": "ar",
112+
"src": "أهلاً {بالعالم :string u:dir=auto}",
113+
"exp": "أهلاً \u2068بالعالم\u2069"
114+
},
115+
{
116+
"locale": "ar",
117+
"src": "أهلاً {world :string u:dir=ltr}",
118+
"exp": "أهلاً \u2066world\u2069"
119+
},
120+
{
121+
"locale": "ar",
122+
"src": "أهلاً {بالعالم :string}",
123+
"exp": "أهلاً \u2067بالعالم\u2069"
124+
}
125+
]
126+
}

0 commit comments

Comments
 (0)