Skip to content

Commit 6ede41b

Browse files
aphillipsgithub-actions[bot]stasmcatamorphism
authored
(Design) Extending functions/options/namespacing (#475)
* Create 0475-overriding-extending-namespacing.md * style: Apply Prettier * Update 0475-overriding-extending-namespacing.md * style: Apply Prettier * Fleshing out * style: Apply Prettier * Fix the ABNF and description * Update exploration/0475-overriding-extending-namespacing.md Co-authored-by: Stanisław Małolepszy <sta@malolepszy.org> * Address @stasm's comments * style: Apply Prettier * Update 0475-overriding-extending-namespacing.md * style: Apply Prettier * Remove the `:std` namespace * Rename file to remove PR number * Address @catamorphism and @stasm's comments * Update exploration/overriding-extending-namespacing.md Co-authored-by: Tim Chevalier <tjc@igalia.com> * Update exploration/overriding-extending-namespacing.md --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Stanisław Małolepszy <sta@malolepszy.org> Co-authored-by: Tim Chevalier <tjc@igalia.com>
1 parent 9a900ae commit 6ede41b

File tree

1 file changed

+336
-0
lines changed

1 file changed

+336
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
# Design Proposal: Namespaces for Extending Functions, Options, etc.
2+
3+
Status: **Accepted**
4+
5+
<details>
6+
<summary>Metadata</summary>
7+
<dl>
8+
<dt>Contributors</dt>
9+
<dd>@aphillips</dd>
10+
<dt>First proposed</dt>
11+
<dd>2023-09-13</dd>
12+
<dt>Pull Request</dt>
13+
<dd>#475</dd>
14+
</dl>
15+
</details>
16+
17+
## Objective
18+
19+
_What is this proposal trying to achieve?_
20+
21+
This design defines how externally-authored functions can appear in a _message_;
22+
how externally-authored function options (and their values) can be supported;
23+
and what, if any, effects this has on the namespace of functions and options.
24+
25+
Implementations will provide the functionality for selection and formatting,
26+
including options and option values.
27+
Much of this functionality will be mandated by the default registry.
28+
We expect that default registry entries will serve the core needs for MF2 users.
29+
However, there are many capabilities available in platform, library,
30+
or operating environment APIs that could be useful to developers and translators
31+
or which might be expected on a specific platform or in a specific programming language.
32+
In addition, we expect to provide support for markup and templating regimes.
33+
These need to be implemented using values not found in the default registry.
34+
35+
An additional hope is that a robust ecosystem of function libraries will be created.
36+
A successful ecosystem will allow users to pick-and-choose or cherry-pick functions or
37+
options to use in a given development environment.
38+
Each function, option, or option value extension needs to work as seamlessly as possible
39+
with other add-ons and with the built-in functionality.
40+
41+
## Background
42+
43+
_What context is helpful to understand this proposal?_
44+
45+
One example of potential add-on functionality that can help readers understand this proposal
46+
is the use of _skeletons_ for date and number formatting.
47+
48+
The JavaScript `Intl.DateTimeFormat` API provides for the customization of date and time values
49+
through the use of "option bags". For example:
50+
51+
```js
52+
new Intl.DateTimeFormat("en-GB", {
53+
weekday: "long",
54+
year: "numeric",
55+
month: "short",
56+
day: "numeric",
57+
hour: "numeric",
58+
minute: "numeric",
59+
});
60+
```
61+
62+
This might be expressed in MessageFormat as:
63+
64+
```
65+
Today is {$today :datetime weekday=long year=numeric month=short day=numeric hour=numeric minute=numeric}
66+
```
67+
68+
The ICU family of libraries provide a shorthand mechanism called _skeletons_ for accessing
69+
date and time format options without needing a verbose list of options.
70+
The same message might look like this with a skeleton:
71+
72+
```
73+
Today is {$today :datetime skeleton=EEEEyMdjm}
74+
```
75+
76+
Skeletons are not proposed for inclusion in the default registry
77+
because they are not universally available in all datetime formatting
78+
libraries.
79+
80+
## Use-Cases
81+
82+
_What use-cases do we see? Ideally, quote concrete examples._
83+
84+
- Developers need to add options to the base functions to suit local needs.
85+
For example, ICU's skeletons as part of the `:datetime` function
86+
Support for this option needs to be specified for local implemented versions.
87+
88+
- Developers want to write a function and access it from messages.
89+
90+
- Developers want to import 3rd party formatting packages and use the package's
91+
features from within messages.
92+
93+
- Users want to import two or more formatting packages
94+
and these might have the same-named functions.
95+
For example, there might be both an HTML `p` and TTS `p`
96+
function.
97+
98+
- Users want to control how extensions are referenced in their messages.
99+
For example, they might wish to make a long namespace name shorter.
100+
101+
- Translators and tools would like a machine-readable way to find out the names
102+
and option values for add-on packages.
103+
104+
## Requirements
105+
106+
_What properties does the solution have to manifest to enable the use-cases above?_
107+
108+
- Developers must be able to write functions that do not later collide with items in the default registry.
109+
- Developers must be able to write function add-ons that do not later collide with items in the default registry.
110+
- Users should be able to tell visually when an add-on feature has been used vs. a built-in feature
111+
- Users should be able to resolve conflicts between add-on packages that use the same
112+
function names without altering add-on packages
113+
114+
## Constraints
115+
116+
_What prior decisions and existing conditions limit the possible design?_
117+
118+
- A syntactical prefix or its separator(s) must not collide with characters valid in either
119+
the prefix or in any of the name productions.
120+
121+
- A prefix must not collide with unquoted literal values.
122+
123+
## Proposed Design
124+
125+
_Describe the proposed solution. Consider syntax, formatting, errors, registry, tooling, interchange._
126+
127+
The actual addition and provisioning of features to an implementation is implementation specific.
128+
Implementations are not required to read the registry format defined by MFv2
129+
or use it for any particular purpose.
130+
131+
> For example, a Java implementation might use the `ServiceProvider` interface to load
132+
> functionality, while a Node application might use `import`.
133+
134+
If an implementation supports user-installed formatters, selectors, function options,
135+
or expression annotations, it must also support providing "namespace" prefixes for
136+
each installed set of functionality.
137+
138+
In this design, each namespace prefix is a short string and is associated with a URL.
139+
The URL is intended to point to some publically-available copy of the add-on library's
140+
registry description, for use by tooling and as a reference to users such as translators.
141+
142+
There is no requirement that an implementation read the document at the end of the URL,
143+
nor validate the contents in general or against the actual functionality installed.
144+
145+
> [!NOTE]
146+
> It is a good idea to use ASCII strings for namespace identifiers.
147+
> Remember that translators (and others) in many different languages and
148+
> with many different keyboards need to be able to enter the prefix.
149+
150+
The namespace prefix is part of the `name` production.
151+
The prefix must be at least one character in length.
152+
It may be as long as desired, although users are cautioned that brevity
153+
is desirable.
154+
The prefix is separated from the name by a colon (U+003A COLON).
155+
156+
The default namespace is called the _anonymous namespace_.
157+
Names without a namespace prefix are in the anonymous namespace.
158+
Resolution of which function (or option, annotation, or spannable) is used
159+
for a name in the anonymous namesapce is implementation defined.
160+
Generally it will consist of the value in the default registry
161+
or the implementation's default.
162+
163+
The choice of a `:` is intentional, as it already used for function identification
164+
and might be familiar from similar usage in XML namespaces
165+
as well as slightly similar to C++, e.g. `ns::function`.
166+
This design leverages these sorts of "application familiarity"
167+
as well as the current syntax's use of colon as the function sigil.
168+
169+
```abnf
170+
name = [namespace] name-body
171+
namespace = name-start *name-char namespace-sep
172+
namespace-sep = ":"
173+
name-body = name-start *name-char
174+
```
175+
176+
> [!NOTE]
177+
> The `name-start` and `name-char` productions will have to be altered to
178+
> **_not_** permit U+003A COLON in a name and to otherwise address
179+
> naming concerns.
180+
> This design document does not show the naming changes because there are
181+
> other issues in play for these names.
182+
> For now, just consider that `name-char` will have no colon.
183+
184+
The `name` production as defined here applies to:
185+
186+
- function (selector/formatting) names
187+
- option names
188+
- spannable names
189+
- expression annotation names (if approved)
190+
191+
Examples:
192+
193+
> Add-on function:
194+
>
195+
> ```
196+
> Today is {$today :icu:datetime dateStyle=long}
197+
> ```
198+
>
199+
> Add-on option:
200+
>
201+
> ```
202+
> Today is {$today :datetime icu:skeleton=EEEEyMdjm}
203+
> ```
204+
>
205+
> Add-on spannables (such as markup):
206+
>
207+
> ```
208+
> Today is {+html:a}{$today}{-html:a}
209+
> ```
210+
>
211+
> Add-on expression annotation:
212+
>
213+
> ```
214+
> Today is {$today :datetime @my:annotation}
215+
> ```
216+
>
217+
> Everything altogether all at once. This probably does not work
218+
> correctly, since `:foo:datetime` may not understand `icu:skeleton`:
219+
>
220+
> ```
221+
> Today is {+html:a}{$today :foo:datetime icu:skeleton=EEEEyMdjm @my:annotation}{-html:a}
222+
> ```
223+
224+
Users, such as developers writing messages or translators creating translations,
225+
are not required to type the namespace prefix in message patterns unless there
226+
is ambiguity in the given formatting content or in the runtime.
227+
However, tooling might reject or have difficulty processing values without
228+
the prefix being present.
229+
230+
> For example, if an implementation is using the ICU4J library, any of the
231+
> following messages might be acceptable alternatives:
232+
>
233+
> ```
234+
> Today is {$today :datetime skeleton=EEEEMd}
235+
> Today is {$today :datetime icu:skeleton=EEEEMd}
236+
> Today is {$today :icu:datetime skeleton=EEEEMd}
237+
> Today is {$today :icu:datetime icu:skeleton=EEEEMd}
238+
> ```
239+
240+
### Changes Required by This Design
241+
242+
Implementation of this design will require the following changes:
243+
244+
- Update the ABNF syntax and corresponding text in the syntax.md spec
245+
- Changes to the `name`/`name-char` productions and related naming productions
246+
- Additions to the formatting.md spec regarding namespace resolution
247+
to ensure that the correct function is called
248+
- Additional error type for namespace resolution failure; alternatively
249+
this might take the form of the existing resolution error
250+
- Addition of namespace to the data model for all relative items
251+
252+
It is possible that the registry description will need to include slots for URL
253+
and default namespace name.
254+
255+
### Potential Negatives
256+
257+
This design is based on the assertion that implementors will provide an
258+
extension mechanism and that users will want to use that mechanism to install formatting
259+
or selection functionality.
260+
Any non-standard functions, options, option values, or expressions have the potential
261+
to be disruptive or fragmenting to the overall tooling or localization space.
262+
Any extension that is widely adopted would thus be better off in the default registry
263+
if at all possible.
264+
On the other hand, language- or platform-specific extensions can make MFv2 feel
265+
more "fluent" or consistent for users in a given environment.
266+
267+
## Alternatives Considered
268+
269+
_What other solutions are available?_
270+
_How do they compare against the requirements?_
271+
_What other properties they have?_
272+
273+
### Choice of namespace separator
274+
275+
The choice of the `:` character as a separator is, as noted above, a considered part
276+
of the design, but it is not required.
277+
Other characters are possible for the same purpose.
278+
279+
A concern is that `name-char` reserves `:`, `-`, and `.`, which are probably the
280+
most likely candidates.
281+
Choosing one of these characters would require altering the `name-char` (and
282+
thus `name`) production.
283+
Moving to use `NCName` instead of `Nmtoken` as a basis for `name` would address
284+
the use of `:`.
285+
Moving to `-` or `.` would not require alterations of the syntax if we decided
286+
that namespacing is not formally a part of the specification but, rather, is
287+
just a convention.
288+
289+
Of the remaining characters not currently in use, the most obvious candidates would
290+
be `/` and `~`.
291+
292+
> Here are examples of the options:
293+
>
294+
> ```
295+
> {$today :ns:function ns:option=foo}{+ns:a}{-ns:a}
296+
> {$today :ns-function ns-option=foo}{+ns-a}{-ns-a}
297+
> {$today :ns.function ns.option=foo}{+ns.a}{-ns.a}
298+
> {$today :ns/function ns/option=foo}{+ns/a}{-ns/a}
299+
> {$today :ns~function ns~option=foo}{+ns~a}{-ns~a}
300+
> ```
301+
302+
### No namespacing
303+
304+
Each implementation can install whatever additional functionality.
305+
It is up to the implementation to describe what is permitted and to check messages.
306+
Users will have to RTFM.
307+
308+
- **+** Flexible
309+
- **-** Does not promote a healthy ecosystem of add-on packages
310+
- **-** Does not supply a mechanism for tooling to leverage
311+
312+
### Reverse-domain-name namespacing
313+
314+
Use `com.foo.bar.baz.Function` type naming for functions, options, or expressions.
315+
316+
> ```
317+
> Today is {$today :com.example.foo.datetime dateStyle=short}
318+
> Today is {$today :datetime com.example.foo.skeleton=EEEEMd}
319+
> ```
320+
321+
- **+** Familiarity. This is a familiar structure for developers.
322+
- **-** Verbose. The resulting names are long and difficult to parse visually
323+
324+
### Namespacing sigils are customary not normative
325+
326+
Imported namespace names are agglutinated to the function/option/spannable/attribute
327+
name with no separator.
328+
The use of a separator, such as `:` or `.` is a convention used by developers
329+
or users when importing the namespace.
330+
Thus, a user could import a library as `foo` or as `foo:`, resulting in examples like:
331+
332+
> ```
333+
> {$today :foofunction foooption=foo}{+fooa}{-fooa} with just "foo"
334+
> {$today :foo:function foo:option=foo}{+foo:a}{-foo:a} with prefix "foo:"
335+
> {$today :foo:-:function foo:-:option=foo}{+foo:-:a}{-foo:-:a} users can use any legal characters
336+
> ```

0 commit comments

Comments
 (0)