Variables

Variables are used to reference data that is not known at the time the message is authored, but is passed to the message at runtime (when it is displayed).

In a message, variables are always prefixed with a $ character. The variable name can contain almost all characters that are not spaces or punctuation. A variable name can't start with a number.

Usage Jump to heading

Variables can be interpolated into a message using a placeholder expression.

Your name is {$name}.
{ "name": "Alice" }

Variables can be used in function options and markup options.

You have {42 :number style=currency currency=$currency}.
{ "currency": "USD" }

Declarations Jump to heading

In addition to referring to external input values, variables can be declared within a message. A declaration binds a variable to a value within the scope of a message. This variable can then be used in other expressions within the same message. Declarations are useful for breaking down complex messages into smaller parts, or for reusing values multiple times.

Local declarations Jump to heading

Variables can be declared within a message using a .local statement. The declaration is followed by the variable name, an equals sign, and an expression that evaluates to the value of the variable.

.local $count = {42}
{{The count is: {$count}}}

Expressions inside of a .local statement can contain literals and functions. They can also reference other variables (local and external ones). When referencing a variable, they cannot reference themselves or variables that are declared syntactically after them — only variables that are declared before them.

.local $score = {0.42}
.local $score_percent = {$score :number style=percent}
{{Your score was {$score_percent}.}}

Input declarations Jump to heading

Input declarations are similar to local declarations, but they are used to explicitly name an external input value. This can be useful to annotate an input value with a specific type or format:

.input {$count :number}
{{The count is: {$count}}}
{ "count": 32 }

Because the :number annotation results in a formatting error if the value of $count is non-numeric, annotating $count explicitly makes it easier to detect if a non-numeric value is accidentally passed in:

.input {$count :number}
{{The count is: {$count}}}
{ "count": "not a number" }

Notice the error message "Input is not numeric".

Input declarations can also be useful to ensure that an input variable is always formatted in a specific way.

Input declarations are declared using a .input statement. The declaration is followed by an expression, specifically an expression whose operand is a variable. The variable in this expression is both the input variable being referenced, and the name of the local variable being declared.

.input {$count}
{{The count is: {$count}}}
{ "count": 32 }

In the above example, .input is just being used to ensure that the count is always passed. It acts as a form of documentation for both the developer and the translator: it tells the developer that the message expects a count variable, and it tells the translator that the message gets a count variable passed in.

Ideally expressions in .input should also specify a function. like :string, :number, or :datetime. These functions are not type assertions. They act as type coercions, returning a new value of the specified type based on the operand (or signaling an error if no coercion is possible). This also means that formatting options can be specified in the function.

.input {$amount :number style=currency currency=USD}
{{The price is: {$amount}.}}
{ "amount": 32 }

Selector options can also be specified in the function:

.input {$rank :number select=ordinal}
.match $rank
one {{This is the {$rank}st most expensive item}}
two {{This is the {$rank}nd most expensive item}}
few {{This is the {$rank}rd most expensive item}}
*   {{This is the {$rank}th most expensive item}}
{ "rank": 32 }

When the function in the .input declaration is later used as a selector, any options attached to it are carried to any .match statement that uses the declared variable.

Shadowing and redeclaration Jump to heading

If a local variable has the same name as an external input value, the local variable shadows the external one. That is, the meaning of any subsequent references to the variable name is the value bound to the local variable.

.local $count = {42}
{{The count is: {$count}}}
{ "count": 32 }

Variables can also only be declared once within a message. Redeclaring a variable will result in an error.

.local $count = {42}
.local $count = {32}
{{The count is: {$count}}}

The same rule applies to .input declarations:

.input {$count :number}
.local $count = {32}
{{The count is: {$count}}}
{ "count": 32 }

The .local declaration causes an error because there is already an .input declaration for $count. The same thing happens if the .local and .input declarations are swapped:

.local $count = {32}
.input {$count :number}
{{The count is: {$count}}}
{ "count": 32 }

Another rule is that referring to an external input variable creates an implicit declaration, and the "variables can only be declared once" rule applies to implicit declarations as well:

.local $count1 = {$count}
.local $count = {32}
{{The count is: {$count}}}

Notice that this also causes a "duplicate declaration" error, even though there was no .local declaration for $count before it was used in the declaration of $count1. Why? Because when $count is first used, that creates an implicit declaration of $count; so the subsequent .local $count declaration is considered a duplicate declaration.

On this page