Commands

Overview

Commands are instructions you give the compiler to create templates and add custom logic to templates. Put commands within Closure Template tags, which are delimited by braces ({}). Specify the command name as the first token in the tag (except the print command, which is implied if no command is specified), and add additional tokens to form the command text. For example, to create a template, use the {template} tag. Within the template, you can write other commands to evaluate conditional expressions, iterate over data objects, or print messages.

A few tags below belong at the top of a Closure Template file, while most of them belong within a template. Within the body of a template, any text within Closure Template tags is parsed and understood by the compiler, while anything outside of Closure Template tags is raw text that is output as-is. The syntax for commands depends on the specific command. This chapter describes every command.

delpackage

Syntax:
{delpackage <delegate_package_name>}

This command belongs at the start of a template file, before the namespace tag. It must appear at the start of its own line. It is one of the two ways to use delegate templates. For details, see the section on using delegate templates with delpackage.

namespace

Syntax (basic form):
{namespace <namespace>}
With all optional attributes:
{namespace <namespace> autoescape="strict"}

This command is required at the start of every template file. It must appear at the start of its own line. It declares the namespace for the file, which serves as the common prefix for the full name of every template in the file. You can optionally declare strict autoescaping for every template in the file. You can override this default in the template tag.

Closure Templates allows multiple files to have the same namespace. However, Closure Library and Closure Compiler do not allow it, so if you're using Closure Templates in JavaScript together with other Closure technologies, avoid having the same namespace in multiple files.

alias

Syntax:
{alias <namespace>}
{alias <namespace> as <identifier>}

This command belongs at the start of the file, after the namespace tag. It must appear at the start of its own line. You can include any number of alias declarations. Each declaration aliases the given namespace to an identifier. For the first syntax form above, the alias is the last identifier in the namespace. For the second syntax form, the alias is the identifier you specify. When you call a template in an aliased namespace, you don't need to type the whole namespace, only the alias plus the template's partial name.

For example, if you declare
{alias long.namespace.root.projectx.mymodule.myfeature}
{alias long.namespace.root.projectx.foomodule.utils as fooUtils}
then you can replace the calls
{call long.namespace.root.projectx.mymodule.myfeature.myTemplate /}
{call long.namespace.root.projectx.foomodule.utils.someHelper /}
with
{call myfeature.myTemplate /}
{call fooUtils.someHelper /}

Delegate templates have their own full names (not a partial name prefixed by the namespace), so alias does not affect delegate calls (delcall).

template

Syntax (basic form):
{template <template_name>}
  ...
{/template}
With all optional attributes:
{template <template_name> private="<true/false>" autoescape="strict"}
  ...
{/template}

This command must appear at the start of its own line.

The template name must be a dot followed by an identifier because it is a partial name relative to the file's namespace. For example, if the file's namespace is ui.settings.login and the template's partial name is .newPassword, then the full template name is ui.settings.login.newPassword.

These are the template tag's attributes:

  • private: Optional. Default false. Set this to true if you want this to be a private template. A private template can be called by other templates, including templates in other files, as long as the callers are all within the bundle of files that is compiled together. When you set private to true, the compiler can optimize calls to that template in various ways, including inlining all calls of that template and removing that template altogether.

  • autoescape: Optional. Affects the encoding of print commands and is set according to these rules:
    • If there is an autoescape value specified in the template tag, use that value.
    • Else if there is an autoescape value specified in the file's namespace declaration, use that value.
    • Else default to strict autoescaping.

@param

Syntax:
{template <template_name>}
  {@param <param_name>: <param_type>}
  {@param? <param_name>: <param_type>}
  ...
{/template}

{@param} declares a template parameter. Parameter declarations must come first in the template, preceding all other template content.

The first syntax form above (@param) declares a required parameter that must be provided whenever you call the template. The second form (@param?) declares an optional parameter, which does not always have to be provided. Within a template, an optional parameter declared as {@param? <param_name>: <param_type>} has a type of <param_type>|null.

Doc comments for params

Doc comments for parameters may appear before or after the parameter declaration. If before, the comment must be on the preceding line; if after, the comment must start on the same line as the parameter declaration.

Example:

{template .example}
  /** A leading doc comment. */
  {@param name: string}
  {@param? height: int} /** A trailing doc comment. */
  ...
{/template}

Parameter type expressions

These are the type expressions that can appear in a parameter declaration.

Type Expression Meaning
any The supertype of all types. Any value may be assigned to the any type, but the only operations that are allowed on the any type are printing and (implicit) casting to boolean.
null The null type. Often used as a member of a union type to indicate the value might null or optional.
? The unknown type. This type disables all type checking in expressions where it appears. All operations are allowed on values of the unknown type.
string
bool
int
float
number
Primitive types.

number = (int|float).
html
uri
js
css
attributes
Sanitized content types (produced by templates using strict autoescaping). These represent pre-escaped strings for various contexts.
a.b.c
proto.foo.bar
Object of specific named type. These types are not defined by Closure Templates. They must be defined externally and imported into the compiler's type registry via a Java plugin (not covered in this document). Using a type name that is not registered is an error.
list<ElementType> List containing elements of type ElementType.
map<KeyType, ValueType> Map containing keys of type KeyType and values of type ValueType. Allows item access, for example {$a[b]}.
[a:int, b:float] Record type. Allows field access, for example {$a.b}.
type1|type2 Union type. A union a|b may contain either a value of type a or a value of type b.

Special Characters

Use the following special character commands to add raw text characters:

Special Character Equivalent Raw Text
{sp} space
{nil} empty string
{\r} carriage return
{\n} new line (line feed)
{\t} tab
{lb} left brace
{rb} right brace

Follow these heuristics when deciding when to use {sp} and {nil}:

  • {sp}: Use {sp} to insert a space character at the beginning or end of a line, in situations where the line-joining algorithm would not normally insert a space (specifically, at line-joining locations bordered by an HTML or template tag on either side).

  • {nil}: If a line joining location normally adds a space, but you want to make the lines join without a space, then add {nil} at the end of the first line (most common) or the beginning of the second line. While the {nil} itself turns into an empty string, it adds a template tag at the line-joining location, which eliminates the default single space.

literal

Syntax:
{literal} ... {/literal}

This command allows you to include a literal block of raw text, possibly including special characters like braces. The rendered output is exactly what appears in the literal block. Note that this means that absolutely no processing happens within a literal block: no HTML escaping, no line joining, no removal of indentation, no parsing for template commands, and no parsing for comments.

print

Syntax (without directives):
{<expression>}
{print <expression>}
With directives:
{<expression> |<directive1> |<directive2> |...}
{print <expression> |<directive1> |<directive2> |...}

The print command is the most common command in Closure Templates, so it merits a short syntax in which you can omit the command name print. When Closure Templates encounters a print tag, it simply inserts the result of the expression, coerced to a string if necessary, into the rendered output.

Note: The command name print is optional.

Print directives

Print directives are post-processing on the output of a print command. For a list of print directives, see the Print Directives chapter.

msg

Syntax (basic form):
{msg desc="<help_text_for_translators>"}
  ...
{/msg}
With all optional attributes:
{msg meaning="<differentiator>" desc="<help_text_for_translators>"}
  ...
{/msg}

Use the msg tag to mark a section of the template as a message that needs to be translated. The required desc attribute provides explanation text to the (human) translators.

Note: Do not break up a sentence or phrase into multiple messages. Translation is most effective with the context of the entire sentence or phrase.

Within a msg block, the compiler turns HTML tags and Closure Template tags into placeholders, with the exception of template tags that generate raw text (e.g. special character commands and literal blocks), which are simply substituted. Messages that contain placeholders might be confusing to translators, so you should consider providing (in the desc attribute) an example of how the message looks to the user.

Here are details on how Closure Templates generate placeholders in messages:

  • The compiler uses fixed names for common HTML tags, e.g. <a ...> becomes {START_LINK} and <br /> becomes {BREAK}.

  • A simple print tag that prints a data reference turns into a placeholder that's named according to the last key name, by default. For example, {$user.emailAddress} turns into the placeholder {EMAIL_ADDRESS}.

  • A complete call block (up to the closing /call) turns into a single placeholder. The placeholder is named {XXX} by default, so if you put a call inside a msg, be sure to provide a clear example of what the message might look like in the desc attribute.

  • If you find a need to specify a placeholder name for a print or call instead of allowing the compiler generate the default name, you can add the phname attribute. The value can either be camel case or upper underscore. For example, {call .emailAddr phname="emailAddress" /} causes the placeholder name to be EMAIL_ADDRESS instead of XXX. Note that changing a placeholder name changes the message id, causing retranslation.

  • If a message contains multiple placeholders that would result in the same placeholder name, then the compiler appends number suffixes to distinguish them, e.g. START_LINK_1, START_LINK_2.

  • Template commands for control flow (if, switch, foreach, for) are not allowed in msg blocks. However, you can put them in a let block and then print the resulting reference from a within a msg block. If you do this, make sure the let block has absolutely no translatable content.

Example message:
{msg desc="Says hello and tells user to click a link."}
  Hello {$userName}! Please click <a href="{$url}">here</a>.
{/msg}
Example of what the translators see:
Hello {USER_NAME}! Please click {START_LINK}here{END_LINK}.
Example translation that one translator might give us:
{START_LINK}Zhere{END_LINK} zclick zplease. {USER_NAME} zhello!
Example output (for userName = 'Jess' and url = 'http://www.google.com/'):
<a href="http://www.google.com/">Zhere</a> zclick zplease. Jess zhello!

Use the meaning attribute when you have two messages that are exactly the same string in English, but might be translated to different strings in other languages. The meaning should then be a short string that distinguishes the two messages, and is used for generating different message ids. Translators do not see the meaning attribute, so you must still communicate all the details in the desc. For example:
{msg meaning="noun" desc="The word 'Archive' used as a noun, i.e. an information store."}
  Archive
{/msg}
{msg meaning="verb" desc="The word 'Archive' used as a verb, i.e. to store information."}
  Archive
{/msg}

See more information about translating messages in the Translation chapter.

fallbackmsg

Syntax:
{msg <new_attributes>}
  <new_message>
{fallbackmsg <old_attributes>}
  <old_message>
{/msg}

If you want to change a message in-place, without worrying about accidentally displaying the untranslated new source message to foreign-language users while the new message is getting translated, use the fallbackmsg feature. The compiler automatically chooses the appropriate version of the message to use. If the new message's translation is in the message bundle, then it is used, else the compiler falls back to using the old message's translation. (This decision happens at message insertion time or render time in JavaScript or Java usage, respectively.)

When changing a message, move the old message attributes and content to the fallbackmsg portion. Then, write the new message attributes and content in the msg portion.

For example, to fix a typo in this message:
{msg meaning="verb" desc="button label"}
  Arcive
{/msg}
replace it with the new message:
{msg meaning="verb" desc="button label"}
  Archive
{fallbackmsg meaning="verb" desc="button label"}
  Arcive
{/msg}

When replacing an existing message, you can change the message structure, meaning, placeholders, etc. There are no technical limitations on the relationship between the old and new messages.

Periodically, you might want to clean up your code by grepping for old fallbackmsgs and removing them. Although, it's not particularly harmful to leave fallbackmsgs in the code longer than necessary.

let

Syntax for arbitrary values:
{let $<identifier>: <expression> /}

Syntax for rendering to string ("block form"):

{let $<identifier>}...{/let}

let defines a name for an intermediate value. The name is defined only within the immediate code block containing the let command, and the value of the name is not modifiable. You might use let because you need to reuse the intermediate value multiple times, or you need to print a rendered value using a directive, or you feel it improves the readability of your code.

Example:
{let $isEnabled: $isAaa and not $isBbb and $ccc == $ddd + $eee /}
{if $isEnabled and $isXxx}
  ...
{elseif not $isEnabled and $isYyy}
  ...
{/if}

The second syntax form listed above renders the contents of the let block to a string, including applying autoescaping. It is sometimes needed, but should be used sparingly.

if, elseif, else

Syntax:
{if <expression>}
  ...
{elseif <expression>}
  ...
{else}
  ...
{/if}

Use the if command for conditional output. The compiler evaluates the expressions for if and optional elseif clauses in a boolean context. As soon one expression evaluates to true, the compiler processes that sub-block and skips the rest of the if statement. Any elseif clauses that appear after the one that evaluates to true are never evaluated. The compiler only processes the optional else command when none of the if and elseif conditions are true.

For example:

{if round($pi, 2) == 3.14}
  {$pi} is a good approximation of pi.
{elseif round($pi) == 3}
  {$pi} is a bad approximation of pi.
{else}
  {$pi} is nowhere near the value of pi.
{/if}

Example output (for pi = 2.71828):

2.71828 is a bad approximation of pi.

switch, case, default

Syntax:
{switch <expression>}
  {case <expression_list>}
    ...
  {case <expression_list>}
    ...
  {default}
    ...
{/switch}

Use the switch command for conditional output based on the value of an expression. Each case can have one or more expressions (use a comma-separated list if you have more than one), and the case matches when any one of its expressions matches the value of the switch expression. When a case matches, the compiler process that sub-block and the skips the remainder of the switch statement. The compiler processes the optional {default} command if none of the expressions from the case statements match the switch expression.

For example:

{switch $numMarbles}
  {case 0}
    You have no marbles.
  {case 1, 2, 3}
    You have a normal number of marbles.
  {default}  // 4 or more
    You have more marbles than you know what to do with.
{/switch}

Example output (for numMarbles = 2):

You have a normal number of marbles.

foreach, ifempty

Syntax:
{foreach <local_var> in <data_ref>}
  ...
{ifempty}
  ...
{/foreach}

The foreach command iterates over a list. The iterator local_var is a local variable that is defined only in the block. Within the block, you can use three special functions that only take the iterator as their argument:

  • isFirst($var) returns true only on the first iteration.
  • isLast($var) returns true only on the last iteration.
  • index($var) returns the current index in the list. List indices are 0-based.

The optional ifempty command is for a fallback section that is executed when the list is empty.

For example:

{foreach $operand in $operands}
  {if not isFirst($operand)} + {/if}
  {$operand}
{ifempty}
  0
{/foreach}

Example output (for operands = ['alpha', 'beta', 'gamma']):

alpha + beta + gamma

for

Syntax:
{for <local_var> in range(<expression1>, <expression2>, <expression3>)}
  ...
{/for}

The for command generates a simple numerical loop. The iterator local_var is a local variable that is defined only in the block. The range() function can take one, two, or three arguments. With 3 arguments, the first is the initial value, the second is the limit (note that the loop only continues if the loop variable's value is strictly less than the limit), and the third is the increment. With two arguments, the increment is assumed to be 1. With only one argument, the initial value is assumed to be 0. For example:

range(10)        →  0 1 2 3 4 5 6 7 8 9
range(4, 10)     →          4 5 6 7 8 9
range(4, 10, 2)  →          4   6   8

For example:

{for $i in range($numLines)}
  Line {$i + 1} of {$numLines}.<br>
{/for}

Example output (for numLines = 3):

Line 1 of 3.<br>Line 2 of 3.<br>Line 3 of 3.<br>

call, param

Syntax (basic form):
{call <template_name> data="<data_to_pass>" /}
With enclosed parameters:
{call <template_name> data="<data_to_pass>"}
  {param <key1>: <expression> /}
  {param <key2>}
    ...
  {/param}
{/call}

The call command calls another template and inserts its output into the current template. To provide the parameters of the callee template, you can pass all or part of the caller template's data, construct values to pass using param commands, or use a combination of the two. The following sections discuss these three options in turn, using this example callee template:

{template .exampleCallee}
  {@param largerNum: int} /** An integer larger than 'smallerNum'. */
  {@param smallerNum: int} /** An integer smaller than 'largerNum'. */
  {$largerNum} is greater than {$smallerNum}.
{/template}

Pass all or part of the caller's data

To pass all or part of the caller's data to the callee, the keys of the caller's data must match the names of the callee's parameters. For example, if the caller's data includes a list pairs where each element is a map containing keys largerNum, and smallerNum, then you can use the following:

{foreach $pair in $pairs}
  {call .exampleCallee data="$pair" /}
{/foreach}

Alternatively, you can use the special attribute data="all" to pass all of the caller's data. This means that the callee's parameters must be a subset of the caller's data, and have the same names. In such cases, it's good practice to use data="all" instead of re-listing the parameters. For example, if the caller's data contains two parameters aaa and bbb, and you want to pass both to the callee (with the same parameter names), it would be extra work and unnecessary to re-list each parameter:

// Unnecessary.
{call .mySubtemplate}
  {param aaa: $aaa /}
  {param bbb: $bbb /}
{/call}

Instead, simply set data="all":

// Recommended.
{call .mySubtemplate data="all" /}

Finally, you can omit the data attribute if there are no parameters to be passed in this manner.

Construct values to pass

The param command constructs values to pass to the callee.

Syntax for arbitrary values:
{param <key>: <expression> /}

Syntax for rendering to string ("block form"):

{param <key>}...{/param}

The first form is for arbitrary values and should be used in most cases.

The second form renders the contents of the param block to a string, including applying autoescaping. It is needed in some situations, but it's usually an error to use it when the first form would suffice. A common heuristic is that if you're using the second form with a param block that contains a single print tag:

{param aaa}{$bbb}{/param}
then it's usually an error, and should be replaced with:
{param aaa: $bbb /}
Back to our example, assume that the caller's data includes a list pairs where each element is a map containing key largerInt (note the name change) and only sometimes contains the key smallerInt (otherwise undefined). Use this to make the call:
{foreach $pair in $pairs}
  {call .exampleCallee}
    {param largerNum: $pair.largerInt /}
    {param smallerNum}
      {if $pair.smallerInt}
        {$pair.smallerInt}  // if defined, pass it
      {else}
        {$pair.largerInt - 100}
      {/if}
    {/param}
  {/call}
{/foreach}

The above example demonstrates the two forms of the param command. The first form evaluates an expression and passes the result as the parameter. The second form renders an arbitrary section of Soy code and passes the result as the parameter.

If you're observant, you've probably noticed two issues. The first issue is the value passed for smallerNum is now a string, not an integer (fortunately in this case the callee only uses the parameter in a string context). If you noticed this issue, then perhaps you also noticed that the computation for smallerNum can be put into an expression so that it can be passed as an integer:
{param smallerNum: $pair.smallerInt ? $pair.smallerInt : $pair.largerInt - 100 /}
The second issue is if $pair.smallerInt == 0, then it would be falsy and so $largerInt - 100 would be passed even though $pair.smallerInt is defined and should be passed. This is why you should generally avoid using sometimes-defined map keys. If you do use them, consider the possibility of falsy values. In this example, if there's a possibility that $pair.smallerInt == 0, you could correct the bug by rewriting the expression using the function isNonnull:
{param smallerNum: isNonnull($pair.smallerInt) ? $pair.smallerInt : $pair.largerInt - 100 /}
or better yet, use the null-coalescing operator:
{param smallerNum: $pair.smallerInt ?: $pair.largerInt - 100 /}

Use a combination of the two

Finally, you can mix the two options above: you can pass some of the callee's parameters directly from the caller's data, and pass the rest of the parameters using param commands. For example, if the caller's data includes an integer largerNum and a list of integers smallerNums that are all smaller than largerNum, you could use the following template:

{foreach $smallerNum in $smallerNums}
  {call .exampleCallee data="all"}
    {param smallerNum: $smallerNum /}
  {/call}
{/foreach}

Here, data="all" passes in the callee's original template data largerNum and the list smallerNums. However, because data="all" does not pass in the variable smallerNum, you must pass it explicitly using the param command.

Note: The data attribute of a call tag can only be used to pass all or part of the callee's original template data.

Calling a template in a different namespace

All of the above examples demonstrate calling a template in the same namespace, hence the partial template name (beginning with a dot) used in the call command text. To call a template from a different namespace, use the full template name including namespace. For example:
{call myproject.mymodule.myfeature.exampleCallee data="$pair" /}
Or, if you've aliased the namespace of the template you're calling to its last identifier, then
{call myfeature.exampleCallee data="$pair" /}

Delegate templates (with delpackage)

Delegate templates allow you to write multiple implementations of a template and choose one of them at render time. Delegate templates are defined and called using deltemplate and delcall, which have syntax similar to template and call.

There are two independent ways to use delegates, differing in how you control which delegate implementation is called. This section explains how to use delegates with delegate packages (delpackage), which is appropriate for cases where you don't intend to send code for unused delegate implementations to the client, (for example, an experiment whose code is only sent to a small subset of users.) The next section explains how to use delegates with the variant attribute, which is appropriate for finer control of delegate selection at the call site.

Syntax:
main.soy
{namespace ...}

/** Caller (basic template, not delegate template). */
{template ...}
  {delcall aaa.bbb.myButton allowemptydefault="false" data="..." /}
{/template}

/** Default implementation. */
{deltemplate aaa.bbb.myButton}
  ...
{/deltemplate}
experiment.soy
{delpackage MyExperiment}
{namespace ...}

/** My experiment's implementation. */
{deltemplate aaa.bbb.myButton}
  ...
{/deltemplate}

The implementations must appear in different files, and each file other than the default implementation must declare a delegate package name (delpackage). This is the identifier used to select the implementation at usage time.

The delegate template names are not within the file's namespace; namespaces only apply to basic templates. Instead, delegate template names are just strings that are always written in full. They can be any identifier or multiple identifiers connected with dots.

Template files can have an optional delpackage declaration at the top, just above the namespace declaration. And multiple files can have the same delpackage name, putting them all within the same delegate package. If a delegate template is defined in a file without delpackage, then it is a default implementation. If a delegate template is defined in a file with delpackage, then it is a non-default implementation.

At render time, when a delegate call needs to be resolved, Closure Templates looks at all the "active" implementations of the delegate template and uses the implementation with the highest priority. Basically, this means:

  1. Use a non-default implementation, if there is one.
  2. Otherwise, use the default implementation, if there is one.
  3. Otherwise, if the decall has the attribute allowemptydefault="true", then the call renders to the empty string.
  4. Otherwise, an error occurs.

Due to the third case, it is legal to render a delegate template that has no default implementation, as long as the delcall has allowemptydefault="true".

What counts as an "active" implementation depends on the backend in use. In JavaScript, an active implementation is simply an implementation that is defined in the JavaScript files that are loaded. Ship only the generated JavaScript files for the active delpackages.

In Java, use SoyTofu.Renderer#setActiveDelegatePackageNames to set the active implementations. For example, with the example template code above, call

myTofu.newRenderer(...)
    .setActiveDelegatePackageNames(ImmutableSet.of("MyExperiment"))
    .setData(...)
    .render()

This will use the non-default implementation of aaa.bbb.myButton from the MyExperiment delegate package. On the other hand, if you omit the call to setActiveDelegatePackageNames(), or if you pass a set not including MyExperiment, it will use the default implementation of aaa.bbb.myButton.

In either backend, it is an error to have more than one active implementation at the same priority (for example, multiple active non-default implementations).

Delegate Templates (with variant)

Delegate templates allow you to write multiple implementations of a template and choose one of them at render time. Delegate templates are defined and called using deltemplate and delcall, which have syntax similar to template and call.

There are two independent ways to use delegates, differing in how you control which delegate implementation is called. The previous section explains how to use delegates with delegate packages (delpackage), which is appropriate for cases where you don't intend to send code for unused delegate implementations to the client, (for example, an experiment whose code is only sent to a small subset of users). This section explains how to use delegates with the variant attribute, which is appropriate for finer control of delegate selection at the call site.

Syntax:
/** Caller (basic template, not delegate template). */
{template ...}
  {delcall aaa.bbb.myButton variant="$variantToUse" /}
{/template}

/** Implementation 'alpha'. */
{deltemplate aaa.bbb.myButton variant="'alpha'"}
  ...
{/deltemplate}

/** Implementation 'beta'. */
{deltemplate aaa.bbb.myButton variant="'beta'"}
  ...
{/deltemplate}

The delegate template names are not within the file's namespace; namespaces only apply to basic templates. Instead, delegate template names are just strings that are always written in full. They can be any identifier or multiple identifiers connected with dots.

The variant in a deltemplate command must be a string literal containing an identifier. If no variant is specified, then it defaults to the empty string. The variant in a delcall command can be an arbitrary expression, as long as it evaluates to a string at render time.

At render time, when a delegate call needs to be resolved,

  1. Use the delegate implementation with matching variant, if there is one.
  2. Otherwise, use the delegate implementation with no variant, if there is one.
  3. Otherwise, an error occurs.

css

Syntax:

{css <command_text>}

The css command is a layer of indirection that frees you from having to hard-code CSS class names in your template files. The behavior depends on the backend in use. In JavaScript, {css 'foo'} becomes a call to the Closure Library function goog.getCssName('foo').. In Java, {css 'foo'} becomes a lookup into a SoyCssRenamingMap, which can be set with Renderer#setCssRenamingMap().

xid

Syntax:

{xid <command_text>}

The xid command is useful for minification and obfuscation of strings. In JavaScript, it is replaced by a call of xid function. This function is not defined by Soy; users need to define it themselves. In Java, users can specify a renaming map using SoyTofu#setIdRenamingMap. If this map is not specified then the default implementation just appends _ to the passed string.