Skip to content

MessageFormat vs Fluent Syntax

Zibi Braniecki edited this page Mar 8, 2017 · 2 revisions

Below, we're going to analyze the syntactic shortcomings we identified in MessageFormat and how Fluent's Design Principles were applied in designing the alternative.

We'll use the following example:

// MessageFormat:
{unreadEmails, plural,
   one {You have one unread email from {date, datetime, short }.}
 other {You have {unreadEmails} unread emails.}
}

// Fluent:
emails = { $unreadEmails ->
    [one] You have one unread email from { DATETIME($date, style: "short") }.
   *[other] You have { $unreadEmails } unread emails.
}

Syntax readability

Our main problem with MessageFormat is that it's syntax mixes translatable and non-translatable pieces together.

In MessageFormat {You is to be translated, but {unreadEmails and {date are not to be translated. Also plural and one, despite looking like regular English words, are not to be translated.

In Fluent we focused on annotating non-translatable elements that may be taken for common words with sigils in order to maximize the chance that the reader will recognize them as special and not try to translate. In the example above, variables are annotated with $, variants with [], keyword has ':', keyword value is in ", and the function name is all-caps.

On top of that many pieces of the syntax are either intuitive (* for the default variant) or tap into potential prior-knowledge from the reader, like Microsoft Excel function calls and variables.

Function calls

MessageFormat function calls is very cryptic. {date, datetime, short } does not resemble any pattern that a localizer might have encounter before. It also does nothing to help user understand which part is which and in some cases may look weird, like if there was timeStyle and dateStyle, it would end up like this: {date, datetime, short, long }.

Fluent uses more syntax not only more familiar to the user based on Excel, but also annotates all potential words with sigils to help user understand that they're not to be translated. Keyword arguments are also annotated and named to help user understand their meaning: { DATETIME($date, timeStyle: "short", dateStyle: "long") }.

This may seem like a minor issue, but we actually believe that the cryptic syntax of functions severely limits the opportunity it has to make users create better messages. Lowering the barrier to write more sophisticated messages, enables more of the localizers to translate better. For example, take an example of a particularly complex message in Fluent:

liked-photo = { PLURAL($people) ->
    [1]     { $people } lubi
    [2]     { $people } lubią
    [3]     { TAKE(2, $people), "jedna inna osoba" } lubią

   *[other] { TAKE(2, $people),
              "{ PLURAL(DROP(2, $people)) ->
                  [1]    jedna inna osoba lubią
                  [few]  { LEN(DROP(2, $people)) } inne osoby lubią
                 *[many] { LEN(DROP(2, $people)) } innych osób lubi
               }"
            }
} Twoje zdjęcie.

We believe it would be very hard to write it in MessageFormat and the end result would be practically unreadable.

While we do not intend to remove the role of a good syntax highlighting and tooling, we believe that lowering the barrier to access and use the syntax is important for it's feasibility to be a Web Standard.