ICU format

ICU is the placeholder syntax StoryBonsai uses inside text fields that need to vary at runtime. When a writer types Hello {name}, the runtime swaps {name} for the current value of the name variable before the line is shown. ICU also handles plurals (one item vs five items), branching on a string value (he vs she vs they), and ordinal forms (1st, 2nd, 3rd).

You will type ICU in three places: the text of a Dialogue event, the template of a Set Variable (Text) event, and the source text of a custom locale string (the text_* entries resolved by Localize). The Online ICU Sandbox listed under See also lets you try a template in a browser editor without opening StoryBonsai.

Placeholders

A bare placeholder is a name in curly braces. The runtime substitutes the value of the matching variable or event-resolution argument at fire time.

Hello {name}. becomes Hello Kim. when name is the string Kim.

What populates a placeholder depends on the host field. Variables are the usual source on dialogue and set-variable-text events; localization argument bindings cover custom locale strings. The placeholder name itself has no type or formatting modifier; pick the variable or argument with the value you want to print, and the runtime prints it verbatim.

Plural

A plural picks one branch from a list of numeric forms based on the value of a number argument. The forms are zero, one, two, few, many, other, plus exact matches written as =0, =1, and so on. StoryBonsai requires every plural to include an other branch as the catch-all. Without it the editor will not export the project.

You have {n, plural, one {# arrow} other {# arrows}} left. becomes You have 5 arrows left. when n is 5, and You have 1 arrow left. when n is 1.

The # inside a branch substitutes the number that was matched. The same shortcut works inside selectordinal branches.

Offset

offset:N subtracts N from the number before it picks a branch. The # inside the branch then prints the reduced number, which is useful when the speaker shouldn’t be included in the count.

{n, plural, offset:1 =0 {nobody} one {you and # other} other {you and # others}} resolves to you and 2 others when n is 3.

Select

A select picks a branch by matching its string argument against named keys. Keys match exactly; male and Male are different keys. Every select needs an other branch, which is the fallback StoryBonsai uses when no key matches.

{pronoun, select, he {He nods.} she {She nods.} they {They nod.} other {They nod.}} resolves to She nods. when pronoun is she.

Use it for any small fixed set of cases that change a sentence’s wording: character pronouns, faction membership, weapon types.

Select ordinal

A select ordinal picks one branch based on the ordinal form of a number. English uses one for 1st, two for 2nd, few for 3rd, and other for the rest; other languages use a different mix. Selectordinal works the same way as plural here: the other branch is mandatory in StoryBonsai, and a template missing one fails the export gate.

{place, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} resolves to 3rd when place is 3. The # inside the branch substitutes the original number, exactly as it does inside a plural branch.

Nesting

Constructs nest inside each other’s branches. The inner construct is its own argument with its own rules; the outer construct picks a branch first, then the inner runs against the chosen branch’s text.

{count, plural, one {{tone, select, warm {an old friend} other {an acquaintance}}} other {a crowd}} resolves to an old friend when count is 1 and tone is warm, and a crowd when count is 5.

You can nest as deeply as you need, but every layer still has to be a valid construct on its own.

Literal braces

Wrap a literal { or } in apostrophes to print it as a character instead of opening a placeholder. The apostrophes are quote marks for the braces; they do not appear in the output.

Press '{'ESC'}' for {action}. resolves to Press {ESC} for menu. when action is menu.

What’s not here

  • Date, time, and number type-format placeholders. Constructs like {n, number, percent} or {when, date, short} are not supported. Pre-format the value into a string variable before the line runs, then reference that variable from the template. Studio code can take a parseable value, like an ISO date, and write back the locale-appropriate display form.
  • Custom format types. A writer cannot register a new type name ({thing, mytype, …}) for the runtime to call. The set of supported constructs is the one listed above.

See also

Docs last synced: 2026-07-08
Screenshot viewer