Syntax Guide
MessageFormat
is a new functionality that can act as a Swiss Army knife for
many of your i18n needs, allowing you to localize interfaces with great ease.
MessageFormat
is currently in "tech preview" mode, with an alpha release.
What is a "Message"? Jump to heading
Messages are user-visible strings, often with variable elements like names, numbers and dates. Message strings are typically translated into the different languages of a UI, and translators rearrange the variable elements according to the grammar of the target language.
The simplest and most common use-case of such applications is to replace placeholders in applications with locale-specific messages.
Simple Messages Jump to heading
Simple (static) messages can be written without utilizing special syntax, since the default mode is "text mode".
EXAMPLE
This is a message.
Placeholders Jump to heading
A placeholder can either be an expression or a markup placeholder. We'll talk about expressions first.
Expressions Jump to heading
An expression represents a dynamic part of a message that will be determined
during the message's formatting at runtime. Expressions are enclosed within a
single set of braces ({...}
). The two kinds of expressions you could have in
your messages are:
Variable Replacement Jump to heading
The most common way to use MessageFormat
is for simple variable replacement
within messages.
EXAMPLE
Hello, {$userName}!
Annotations Jump to heading
Variables can also be decorated with annotations.
EXAMPLE
Today is {$date :datetime weekday=long}.
Because it begins with a :
, you can tell that :datetime
is the name of a
function. In MessageFormat, we say that $date
is annotated with the
annotation :datetime weekday=long
. This is analogous to a function call, with
:datetime
as the function and the runtime value of $date
as the argument. In
this annotation, we say that $date
is the operand of :datetime
. The
annotation can also have any number of named options. In this case, there is one
named option: the literal string long
, associated with the name weekday
.
In general, an annotation is a part of an expression containing either a function call together with its associated options, or a private-use or reserved sequence.
An annotation can appear in an expression by itself or following a single operand. If an operand is present, that operand serves as input to the annotation. (Currently, all the built-in functions in MessageFormat are required to have an operand.)
Literals Jump to heading
Markup Jump to heading
Complex Messages Jump to heading
More complex messages begin with a keyword. All keywords begin with a '.' character. Complex messages can include variants, declarations, or both.
Variants Jump to heading
Here is a message with variants:
EXAMPLE
.match {$userType :string}
guest {{Welcome Guest!}}
registered {{Welcome {$username}!}}
Because this message begins with the keyword .match
, you can tell that it's a
matcher
. We'll explain matchers in more details later. For now, notice that
there are two different patterns, {{Welcome Guest!}}
and
{{Welcome {$username}!}}
. These patterns are enclosed in double sets of curly
braces. This is syntax you might be familiar with from templating languages.
Declarations Jump to heading
Built-in Formatters Jump to heading
A number of commonly used formatters are built into all MessageFormat
implementations for easy access. Formatters are simple in that they format a
given locale-independent value (like a standardized date or a number) into a
localized string ready to be presented to the user.
Date and Time Formatting Jump to heading
A date and time formatter that closely mimics JavaScript Intl's
DateTimeFormat
is available as the :datetime
function in MessageFormat
. Two more functions,
:date
and :time
, are included. :date
only formats the date, while :time
formats the time.
EXAMPLE
The match on {$date :datetime dateStyle=long} is cancelled.
EXAMPLE
The match on {$date :date style=long} is cancelled.
EXAMPLE
The match at {$date :time style=medium} is cancelled.
OPTIONS
style
: The base display style to be used across the entire date time, possible values:full
,long
,medium
, andshort
.dateStyle
: The base display style to be used for the date component, possible values:full
,long
,medium
, andshort
.timeStyle
: The base display style to be used for the time component, possible values:full
,long
,medium
, andshort
.
:datetime
can also accept a number of field options. The entire list of
options is in
the specification.
Number Formatting Jump to heading
A number formatter that closely mimics JavaScript Intl's
NumberFormat
is available as the :number
function in MessageFormat
. A second function,
:integer
, is similar to :number
but always formats is input as an integer.
EXAMPLE
The average number of plants per household is {$amount :number minimumFractionDigits=2}.
EXAMPLE
The median number of plants per household is {$amount :integer}.
OPTIONS
The entire list of options is in the specification.
Selectors Jump to heading
The second class of functions, apart from formatters, are selectors. As opposed to formatters which format an input value inside a pattern, selectors allow you to "select" one of many patterns based on performing some kind of locale-sensitive operation on a value.
Selectors always have to be specified explicitly; you can't write
.match {$x} ...
, because $x
is not declared explicitly. You could fix this
message by writing either: .match {$x :number} ...
;
.input {$x :number} .match {$x} ...
; or
.local $x = {1: number} .match {$x} ...
.
Plural Selection Jump to heading
A plural selector that closely mimics JavaScript Intl's
PluralRules
is available as the :number
function in MessageFormat
. Notice that :number
has two meanings: as a formatting annotation, and as a selector annotation. The
meaning is disambiguated based on context.
EXAMPLE
.match {$count :number}
one {{One new message}}
* {{{$count :number} new messages}}
String Selection Jump to heading
A selector named :string
that just does literal string comparison is provided.
EXAMPLE
.match {$pronoun :string}
she {{{$user} added you to her friends list.}}
he {{{$user} added you to his friends list.}}
* {{{$user} added you to their friends list.}}
In this example, the runtime value of $pronoun
is treated as a string and
literally compared to the strings she
and he
. If it's not equal to any of
the other strings, then the *
variant is used.