Skip to content

[v2] Introduce textNode for all human-facing text #133

Description

@lorisleiva

Note

Status: gated. This item has an explicit go/no-go before the v2 candidate is declared; if the design has not converged by then, it slips to v3 without blocking the release.

Today in v1

Human-facing text — docs, display intent and interpolatedIntent, error messages, labels — is plain strings. There is no way to attach structured metadata to a piece of text (translations, formatting hints) without changing the shape of every attribute that carries one.

Proposal

A single node for all textual content:

{ "kind": "textNode", "content": "Transfers tokens between accounts." }

Because every node gets a plugins list in v2 (#124), text becomes extensible without further spec changes — for example a translation convention under an i18n namespace:

{
    "kind": "textNode",
    "content": "Transfers tokens between accounts.",
    "plugins": [{ "kind": "pluginNode", "name": "i18n.es", "payload": "Transfiere tokens entre cuentas." }]
}

String shorthand on the wire. A bare string is equivalent to a textNode with no plugins, and readers normalise to the node on parse — the same spirit as the existing empty-array convention. In-memory types are always textNode; an untranslated IDL looks exactly like today:

"docs": "Transfers tokens between accounts."

Decisions

  • Applies to docs, intent, interpolatedIntent, display labels and errorNode.message. Never to identifiers ([v2] Rename name to identifier and drop the casing mandate #129) — those are machine keys with their own charset and uniqueness rules.
  • docs becomes a single text value using \n, replacing the v1 array-of-lines encoding.
  • Multi-line is a per-attribute convention (docs may contain \n; intent should not), enforced as validator warnings rather than a node-level flag.

Trade-off, stated honestly

The shorthand keeps the wire compact, but moves complexity to readers: every textual position is string | textNode at parse time. The bet is that one normalisation rule per implementation is cheaper than a bespoke metadata mechanism per textual attribute, forever.

Migration

v1 strings pass through unchanged (they are valid shorthand); v1 docs arrays join with \n.


Part of #102 — Tier C (go/no-go).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions