-
-
Notifications
You must be signed in to change notification settings - Fork 36
Define @attributes on expressions #450
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -159,6 +159,9 @@ its resolved value is defined by _literal resolution_. | |||||||
> {You have {42 :number}} | ||||||||
> ``` | ||||||||
|
||||||||
_Expression attribute resolution_ defines the handling of _expression attributes_ | ||||||||
that have an impact on _message_ formatting. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this part of the sentence doesn't belong. The attributes need to be resolved if they are present. Whether they have an impact on formatting is up to the functions or processing involved in the formatting itself. Also, it should be noted that the attributes almost certainly "pass down" to parts during formatting (so that the caller can access them, if needed). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not so sure about attributes getting passed as such to formatting or selection functions. If that makes sense, then why not pass them as function options? Locale is special because
I can see how e.g. timezone could be handled similarly specially by setting up some aspect of the environment before a formatter call rather than considering it as a function option, but for that I'd expect it to be a thing that the implementation does, and which affects the formatter only indirectly.
That's not really in line with what we're saying about other ignored code. For example, we allow an implementation to ignore errors in expressions that aren't needed for the current formatting. Similarly, we should ignore errors in attributes that don't impact the formatting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The attributes need to be parsed, even if they are not recognized. The parser does not necessarily know what is supported downstream or in an implementation.
Depends on what "error" means. If there is a syntax error, we can't ignore that, no? (some of this is about what "we" means here: It is up to the function to decide if an attribute is "bad" or just to ignore it. "Our" job is to get the options and variables to the function.) |
||||||||
|
||||||||
### Literal Resolution | ||||||||
|
||||||||
The resolved value of a _text_ or a _literal_ is | ||||||||
|
@@ -205,9 +208,13 @@ the following steps are taken: | |||||||
- If its right-hand side successfully resolves to a value, | ||||||||
aphillips marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
bind the _name_ of the _option_ to the resolved value in the mapping. | ||||||||
- Otherwise, do not bind the _name_ of the _option_ to any value in the mapping. | ||||||||
eemeli marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
4. Call the function implementation with the following arguments: | ||||||||
4. Determine the _expression_ _locale_. | ||||||||
If the _expression_ has a valid `@locale` _expression attribute_, | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Define "valid" here. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's defined in the expression attribute resolution section. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem here is that "valid" isn't clearly attached to @Locale or expression attribute. If this were written upside down, it might be clearer, e.g.
|
||||||||
use its resolved value as the _expression_ _locale_. | ||||||||
Otherwise, look up the _message_ _locale_ from the _formatting context_. | ||||||||
5. Call the function implementation with the following arguments: | ||||||||
|
||||||||
- The current _locale_. | ||||||||
- The _expression_ _locale_. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would expose the expression attributes here also. Locale may not be the only one--I certainly have timezone in mind and other attributes may be provided by the implementation or our specification that affect the formatter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At least for the JS For other attributes, there is this below:
Should the text here make a reference to that as well, or is that implicit permission sufficiently clear? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You're permitting implementations to assign meaning, but here I'm suggesting that functions can assign meaning to attribute values, including those unknown to the implementation. They can only do this if they have access to the values, of course. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why would such a value be defined in the syntax as an expression attribute rather than as a function option? |
||||||||
- The resolved mapping of _options_. | ||||||||
- If the _expression_ includes an _operand_, its resolved value. | ||||||||
|
||||||||
|
@@ -221,7 +228,7 @@ the following steps are taken: | |||||||
their access to the _formatting context_ SHOULD be minimal and read-only, | ||||||||
and their execution time SHOULD be limited. | ||||||||
|
||||||||
5. If the call succeeds, | ||||||||
6. If the call succeeds, | ||||||||
resolve the value of the _expression_ as the result of that function call. | ||||||||
If the call fails or does not return a valid value, | ||||||||
emit a Resolution error and use a _fallback value_ for the _expression_. | ||||||||
|
@@ -286,6 +293,24 @@ rather than the _expression_ in the _selector_ or _pattern_. | |||||||
|
||||||||
_Pattern selection_ is not supported for _fallback values_. | ||||||||
|
||||||||
### Expression Attribute Resolution | ||||||||
|
||||||||
Implementations MUST support the _expression attribute_ `@locale`. | ||||||||
The value of `@locale` MUST be a sequence of | ||||||||
one or more well-formed IETF BCP47 language tags. | ||||||||
If the value is set by a _literal_, | ||||||||
the _literal_ MUST consist of a comma-delimited sequence of | ||||||||
well-formed IETF BCP47 language tags. | ||||||||
|
||||||||
The resolved value of a valid `@locale` _expression attribute_ | ||||||||
is a sequence of IETF BCP 47 language tags. | ||||||||
If a `@locale` has an invalid value, | ||||||||
emit a Resolution error and ignore the _expression attribute_ in further processing. | ||||||||
Comment on lines
+307
to
+308
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we say that the value reverts to that of the message? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need, because that's implicit in what happens if an expression has no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also need to be careful here. Does "invalid" include the language tag's validity? That is, are we requiring that the implementation check the tag's contents? I think that's a job for e.g. If you made the change I suggested on the previous paragraph, some of this paragraph would become irrelevant (we'd have already said that the value was a sequence of language tags). Then this paragraph could say:
Suggested change
Then we probably need to add somewhere:
|
||||||||
|
||||||||
Implementations MAY ignore all other _expression attributes_ during formatting. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does "ignore" mean? Not process them? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect this is wrong. Implementations should not be required to support attributes that they don't recognize or impute meaning. So they are "ignoring" them from that perspective. But they have already parsed them. If I implement |
||||||||
Implementations MAY assign meaning during formatting to other _expression attributes_ | ||||||||
which use a _name_ that contains at least one U+002D HYPHEN-MINUS `-` character. | ||||||||
Comment on lines
+311
to
+312
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where did this come from? Why is the hyphen important? Why can't implementations "assign meaning" to unhyphenated values? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we allow implementations to use any attribute names, then we won't be able to introduce any additional attributes later without a danger of breaking userspace. With the |
||||||||
|
||||||||
## Pattern Selection | ||||||||
|
||||||||
When a _message_ contains a _match_ construct with one or more _expressions_, | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -355,18 +355,21 @@ and end with U+007D RIGHT CURLY BRACKET `}`. | |
An _expression_ MUST NOT be empty. | ||
|
||
A **_<dfn>literal-expression</dfn>_** contains a _literal_, | ||
optionally followed by an _annotation_. | ||
optionally followed by an _annotation_ | ||
and optionally one or more _expression attributes_. | ||
|
||
A **_<dfn>variable-expression</dfn>_** contains a _variable_, | ||
optionally followed by an _annotation_. | ||
optionally followed by an _annotation_ | ||
and optionally one or more _expression attributes_. | ||
|
||
A **_<dfn>function-expression</dfn>_** contains only an _annotation_. | ||
A **_<dfn>function-expression</dfn>_** contains only an _annotation_, | ||
optionally followed by one or more _expression attributes_. | ||
|
||
```abnf | ||
expression = literal-expression / variable-expression / function-expression | ||
literal-expression = "{" [s] literal [s annotation] [s] "}" | ||
variable-expression = "{" [s] variable [s annotation] [s] "}" | ||
function-expression = "{" [s] annotation [s] "}" | ||
literal-expression = "{" [s] literal [s annotation] *(s expression-attribute) [s] "}" | ||
variable-expression = "{" [s] variable [s annotation] *(s expression-attribute) [s] "}" | ||
function-expression = "{" [s] annotation *(s expression-attribute) [s] "}" | ||
annotation = (function *(s option)) / private-use / reserved | ||
``` | ||
|
||
|
@@ -571,18 +574,74 @@ unrecognized reserved sequences have no meaning and MAY result in errors during | |
|
||
```abnf | ||
reserved = reserved-start reserved-body | ||
reserved-start = "!" / "@" / "#" / "%" / "*" / "<" / ">" / "/" / "?" / "~" | ||
reserved-start = "!" / "#" / "%" / "*" / "<" / ">" / "/" / "?" / "~" | ||
|
||
reserved-body = *( [s] 1*(reserved-char / reserved-escape / quoted)) | ||
reserved-char = %x00-08 ; omit HTAB and LF | ||
/ %x0B-0C ; omit CR | ||
/ %x0E-19 ; omit SP | ||
/ %x21-5B ; omit \ | ||
/ %x21-3F ; omit @ | ||
/ %x41-5B ; omit \ | ||
/ %x5D-7A ; omit { | } | ||
/ %x7E-D7FF ; omit surrogates | ||
/ %xE000-10FFFF | ||
``` | ||
|
||
### Expression Attributes | ||
|
||
An **_<dfn>expression attribute</dfn>_** is a key-value pair | ||
containing a named argument that is attached to the _expression_ as a whole. | ||
These might be used to convey information about the _expression_ | ||
that are not necessarily applicable as _function_ _options_, | ||
such as attributes related to handling during the translation process. | ||
They might also be used to override contextual or implementation-specific values | ||
used by a _function_ during formatting, such as the locale. | ||
For example, the `@locale` attribute overrides the locale of the _message_ for its _expression_. | ||
Attributes like `@can-delete` and `@translate` might not have any impact on formatting, | ||
acting instead as instructions to translators. | ||
Comment on lines
+600
to
+601
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The syntax specification should only include attributes that we formally define all the way through. If these are examples, they should be treated as such, e.g. "If an implementation supported attributes such as..." |
||
|
||
_Expression attributes_ are prefixed by a U+0040 COMMERCIAL AT `@` sign, | ||
but otherwise use the same syntax as _options_. | ||
|
||
The _name_ of an _expression attribute_ MUST either be one of the following, | ||
or it MUST contain at least one U+002D HYPHEN-MINUS `-` character: | ||
eemeli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- `locale`: a sequence of well-formed IETF BCP47 language tags | ||
see _expression attribute resolution_. | ||
- `translate`: a literal value of either `yes` or `no` | ||
|
||
To ensure future extensibility of this specification, | ||
all other _expression attributes_ with a _name_ not containing `-` MUST be ignored. | ||
Comment on lines
+613
to
+614
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about just allowing unrecognized attributes to be ignored? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because then we could not later assign a meaning to them without potentially breaking user code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reserving a namespace is a separate thing from ignoring unrecognized values. These can work in tandem. An MF2.0 implementation would ignore the unrecognized value Alternatively (and as I suggested elsewhere), as long as the values are syntactically correct, the implementation can just parse the values without imputing meaning to them and pass them. It only has to apply validation rules to attributes it "knows" (and do we define an error for that???) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider the following hypothetical, in a world where we allow implementations to assign their own meaning to any attributes not explicitly defined in the spec like Let's say that an implementation defines Then let's say that in a 2.1 version of the MF spec we'd like to define But in this world we could not do that without potentially breaking userspace, because an implementation as defined above could exist, along with a pre-existing body of messages using |
||
|
||
Multiple _expression attributes_ are permitted in an _expression_. | ||
Each _expression attribute_ is separated by whitespace. | ||
If present, _expression attributes_ MUST be the last non-whitespace content in an _expression_. | ||
|
||
```abnf | ||
expression-attribute = "@" option | ||
``` | ||
|
||
> Examples of _expressions_ with _expression attributes_ | ||
> | ||
> A _message_ in English including a French _literal_ that should not be translated: | ||
> | ||
> ``` | ||
> {In French, "{|bonjour| @locale=fr @translate=no}" is a greeting} | ||
> ``` | ||
> | ||
> A _message_ with a `$date` _variable_ formatted using the `:datetime` _function_ | ||
> and overriding the locale to use French formatting: | ||
>``` | ||
>{The date would be displayed in French as {$date :datetime @locale=fr}.} | ||
> ``` | ||
> | ||
> A _message_ with a `$start` _variable_ that should be kept in translations | ||
> as the first element of the message. | ||
> | ||
> ``` | ||
> {{$start @can-reorder=no} is the beginning.} | ||
> ``` | ||
|
||
## Other Syntax Elements | ||
|
||
This section defines common elements used to construct _messages_. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remarked on this before: this is too opinionated. Just because you are thinking of translator hints at this moment does not make them them the sole or even primary reason for this feature.
I suspect we should take a moment to agree on requirements/design before adding a feature like this: we should work as efficiently as possible, but not headlong.