Skip to main content

Nested Tag Substitution

Finding a template is only half of resolution. The template body is then expanded: anything between { and } is itself a localization tag, resolved against the same localizer, and its result is spliced in. This is what makes a handful of templates cover thousands of tags.

Numeric Terms Are Indices into the Tag Being Resolved​

Inside {}, a term that is a whole number is replaced by the term at that zero-based index of the tag currently being resolved. Everything else is taken literally.

Plural={1}s

Resolving Plural'Story:

  1. Terms are ["Plural", "Story"].
  2. {1} → term 1 → Story.
  3. The nested tag Story is resolved. With no template for Story, it resolves to itself.
  4. Result: Storys.

{0} is the whole first term; an index past the end of the tag expands to the empty string, which is the mechanism behind optional trailing terms described in Tag resolution.

The Substituted Value Is Resolved, Not Re-Resolved​

The value spliced in is the resolution of the nested tag. It is not fed back through the resolver a second time. This matters when a translated value happens to collide with another tag:

Add=Add {1}
Story=Backlog Item
Backlog Item=bogus

Add'Story yields Add Backlog Item, not Add bogus.

Literal Tags Nest Too​

A nested tag does not have to reference an index. It can name another tag outright, and that tag's template is expanded in turn — recursively, until no braces remain.

Add'Story=Add {Story}
Story=Backlog Item

Add'Story → Add Backlog Item.

Indices and literals combine freely:

Plural={1}s
Report2=Report {Plural'1}/{Plural'2}
Plural'Story=Stories
Scope=Project

Report2'Scope'Story → Report Projects/Stories.

Braces Nest, Innermost First​

Expansion runs repeatedly until no {…} pairs remain, and the innermost pair is always matched first. That lets you build a tag out of another tag's result:

Plural={1}s
Plural'AssetType={Plural'{1'2}'x}
AssetType'Story=Backlog Item

Resolving Plural'AssetType'Story, whose terms are ["Plural", "AssetType", "Story"]:

  1. Innermost {1'2} → AssetType'Story → resolves to Backlog Item.
  2. The body is now {Plural'Backlog Item'x}.
  3. That tag's stack walk finds Plural, whose {1} picks term 1 of Plural'Backlog Item'x — Backlog Item.
  4. Result: Backlog Items.

The literal 'x term is padding: it keeps Backlog Item at index 1 so the generic Plural template still sees it in the right slot.

Literal Braces Are Doubled​

To emit a { or } in the output, double it. Doubled braces are pulled out before expansion starts and restored afterwards, so they never participate in tag matching.

open=open {{ brace
close=close }} brace
match=open {{and}} close
nest=open {{{and}}} close
and=xyz
TagResultWhy
openopen { brace{{ is a literal {
closeclose } brace}} is a literal }
matchopen {and} closeBoth braces are literal, so and is plain text
nestopen {xyz} closeThe outer braces are literal; the inner pair is a real tag

{} — an empty pair — resolves the empty tag, which is pre-seeded to the empty string, so it emits nothing.

Recursion Is Guarded, Not Forbidden​

The localizer keeps a stack of the tags it is currently resolving. If expansion reaches a tag already on that stack, the tag is emitted literally instead of being resolved again. There is no exception and no stack overflow.

bogus=recursive {0} recursive

bogus → recursive bogus recursive. {0} is bogus, which is already being resolved, so it is written out as text.

Cycles fail silently

A cycle between two templates does not raise an error — it produces output containing a raw tag. If a loc-2.v1 response contains an unexpected internal name embedded mid-sentence, suspect a cycle in the templates rather than a transport problem.

Reading a Real Response​

Putting it together, this is why the following is a perfectly ordinary result on an instance where the Story asset type has been renamed:

curl "https://www.example.com/VersionOne/loc-2.v1?[Plural'Story,Command'Delete'Story]"
{
"Plural'Story": "Backlog Items",
"Command'Delete'Story": "Remove Backlog Items"
}

Command'Delete is defined as Remove {Plural'2}. Term 2 of Command'Delete'Story is Story, so the nested tag is Plural'Story, which resolves through its own stack walk. One request, three template lookups, and none of the strings involved is stored anywhere in that final form.