translationKeys method

List<TranslationOccurrence> translationKeys()

Every distinct text style on screen, most-used first.

An aggregate, because "what is the type ramp" is a table and not a list of nodes. Asking it as a search returned 63 hits, cost 2451 tokens and was still truncated; this is the whole answer in about 185 — which makes it the cheapest question in the drill-down and the one that settles most design arguments (two greys that should be one, a ramp with 11.5 and 12.5 in it).

Buckets on InspectNode.textStyle, and that is a correction. It used to read InspectNode.properties, which for a Text is the style its author wrote — so every text that took its size and colour from the theme had neither key and fell out of the ramp entirely. In a themed app that is most of the screen, and the answer was a table of the exceptions presented as a table of the whole. A ramp that cannot see the body text cannot settle "are these two greys the same grey", which is the question it exists for.

The fallback to properties is for stored readings, not for live ones: scenario artifacts and comparison caches written before the resolved Every translation key on this screen, with where it is.

Flattened out of the tree so a reader — the export, the panel — does not have to walk 120KB of nodes to answer "which keys are here". The node id and box ride along, because the next question is always where to crop.

A key appearing twice on a screen appears twice here: two occurrences are two places to photograph, and collapsing them would throw away the choice between them.

Implementation

List<TranslationOccurrence> translationKeys() {
  var found = <TranslationOccurrence>[];
  void visit(InspectNode node) {
    for (var key in node.keys) {
      found.add(
        TranslationOccurrence(
          key: key,
          node: node.id,
          layout: node.layout,
          offstage: node.offstage,
          overflowed: node.textOverflowed,
        ),
      );
    }
    for (var child in node.children) {
      visit(child);
    }
  }

  if (root case var root?) visit(root);
  return found;
}