Specify error fallbacking
Fluent is designed around the concept of strong error fallbacking. The core idea behind it is that we can't assume everything will always go smooth and if errors happen, we want to be as resilient as possible. Much more like HTML and CSS than XML or JS.
The error recovery is a strong part of the resource format in Fluent, allowing us to recover from an error in any message with the next message. This may be important when we decide on whether we want to specify resource format or just pattern format because some design decisions around syntax were driven in Fluent by the desire to strengthen the recovery algorithm (which sigils to use where may matter if you want to be able to recover).
But even within a single pattern, there are multiple error scenarios that I'd like us to consider specifying:
- Formatter error
key = You have { NUMBER($emails) } unread emails
If NUMBER fails for some reason, we should be able to display something meaningful to the user. I suggest we ensure that each variable can be displayed without a formatter, even in a dummy way. So the result here could be You have 5 unread emails where 5 would be western arabic numerals 5 irrelevant of the locale.
Similarly date could be formatted as ISO date.
- Missing/broken variable
If a localizer attempts to use a variable and its missing, we could still format the message: You have $emailCount unread emails is more meaningful than fully missing message
- Unresolved selector
If the selector fails to resolve, we should have a way to select a "default" variant. In Fluent we denote it with *, but it could be "the first", "the last" or one named "other" which could be mandatory.
In all of those scenarios (and probably several others I failed to list), I'd like us to report the partially formatted message and errors so that higher level API can decide whether to display this partially formatted message or fallback on the next locale in the hopes that it'll format properly.
In Fluent our plan (not yet implemented) was to design the behavior of fallbacking depending on severity of errors and if all locales in the chain fail, then display the partially formatted message from the first locale.
+100
Considering the general case of error fallbacking in the context of the data model, should a message be able to define its own fallback value, to use in case any part of its formatting fails?
For instance, could a greeting Hello {$user}! include a fallback form Hello! to use if $user is not defined? I know that this is achievable e.g. with a custom selector:
greeting = { defined($user) ->
[true] Hello {$user}!
[false] Hello!
}
However, if the failing formattable is something more complicated than just $user, an approach like this can get really unwieldy. In that case, an approach that'd be equivalent to a try { ... } catch { ... } might be simpler to use and translate. This would, however, need to be accounted for in the data model.
Another alternative is to consider this a problem of the runtime, in which case the formatting needs a way of communicating that some part of its output is using a sub-par message, and then the runtime can opt to use a completely different message instead.
Do we have data on preferred fallback mechanism? For react-intl we've been doing
- try to render the message in specified locale
- try to render the default message in default locale
- display the default message as is
- display the message ID
We don't do any per-variable fallback like ICU does and so far we haven't got any issues on our fallback mechanism for the lifetime of react-intl