Persist Flat, Render as Tree
Persist Flat, Render as Tree
Store hierarchical data flat and reconstruct the hierarchy at render time, rather than persisting a nested structure. The localization-helper keeps keys as flat, dot-namespaced strings in JSON and only builds a tree when drawing the UI:
{ "en-US": { "general.action.delete": "Delete" } } // persisted: flatgeneral → action → delete // rendered: tree, built lazily
(treeBuilder.ts:18-66 — split on ., group, sort each level; stateless and deterministic)
Why decouple the format from the shape:
- The persistent file stays diff-friendly, greppable, and order-independent —
"general.action.delete"is one searchable line, not a path through nested braces. - The UI hierarchy can be reorganized (regroup, collapse, re-sort) without ever migrating the stored data, because the tree is derived, not stored.
- Reconstruction is a pure function of the flat keys, so two different views (tree, table, locale-columns) can project the same data differently — exactly the row-shape projection in Grid Columns Are Row-Object Keys Projected into Augmentable Descriptors, and the pure-projection principle of Stateless Editor Panel as Pure Projection.
The general rule: the storage format should optimize for durability and tooling (flat, flat-diffable, stable); the in-memory shape should optimize for the view. When the hierarchy is implicit in a delimiter, you get both for free.