unicode-org / message-format-wg

Developing a standard for localizable message strings

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Reserve locally declared patterns

stasm opened this issue · comments

Similar to #592, I'd like us to consider whether we want to also reserve locally declared patterns. I'm starting with an issue to see if there's any appetite for such sub-patterns, before implementing them as reserved in the ABNF.

The current syntax lends itself to the following possible extension, assuming some extra look-ahead:

.local $sub_simple = {{A simple subpattern.}}
.local $sub_select = {
    // Only the .match keyword would be allowed here.
    .match {$count} one {{One}} other {{Many}}
}
.match {$which :string}
simple {{Use it as {$sub_simple}.}}
select {{Use it as {$sub_select}.}}

The main benefit of such extension is to:

  • Allow non-literals as option values, e.g. to markup.
  • Combat the exploding complexity in cases of multiple selectors.

However, when we previously discussed this idea, we also noted its drawbacks:

  • It's effectively string concatenation: spotting errors at the subpattern boundary is hard, and making sure the subpatterns fit well into their surrounding context is hard too.
  • It increases the complexity of the data model by nesting potentially complex patterns as local variables, which can make migrations more difficult, and tooling and UIs harder to build.

Without the extension, custom-implemented message references could be used as a work-around.

(as individual contributor)

This specifically breaks a long time design tenet. We try to avoid features that are "string concatenation in disguise". I am strongly opposed to this.

Brainstorming a bit, the string concatenation angle of this could be averted by defining a new local variable type that takes pattern values and can only be used in option values. Something like:

.local &title = {{The title of the button}}
{{Click the {#button title=&title /} to continue}}

(chair hat on)

We need to determine if this is in or out for LDML45.

(as contributor)

To bring it in, we would need to add quoted-pattern to local-declaration. The resulting assignment would have to be evaluated separately from the main pattern (the one actually used by the message).

There would be a significant limitation on these patterns as well. They could only be straight patterns, without a matcher. Consider:

.local $title = {{Click here for {$chances :integer} more chances}} <-- wants a plural
{{Click the {#button title=$title /} to continue}}

@eemeli's brainstorm is interested, except that the result is no different that a plain literal (the example is probably unfair, since you would just use a literal there vs. a pattern)

To summarize, I think this represents a "compound message" and we don't support these currently. I think a resource format could do useful things here that MF2 can't really do. I think it would be better to work on it as something in the resource format space, in which the parts of a compound message are evaluated separately to form the whole.

If we do want to delegate the consideration of this to the resource space, then it would be very helpful if eemeli/message-resource-wg could be transferred under unicode-org.

From a language design perspective, allowing something like:

.local $sub_select = {
    .match {$count} one {{One}} * {{}}
}
.match {$which :string}
select {{{$sub_select}}}
* {{}}

(minimized version of Stas's initial example)

is weird, because if we don't allow:

.match {$which :string}
select {{{.match {$count} one {{One}} * {{}}}}}
* {{}}

then that violates the intuition that variable names can always be substituted with their values to get an equivalent program. To be fair, that intuition already isn't true -- see #589 -- but the change suggested here would apply to all implementations.

@stasm will document why we will not do this. (from 2024-02-12 call)