Labels
Labels are data. Every user-facing string azdocs prints, draws or exports —
report chapter titles, table headers, empty-state sentences, diagram legends,
CLI progress lines, TUI pane titles and the desktop app’s copy — lives in
data/labels/en.toml, embedded in the binary. Report and interface code names keys instead of embedding English copy.
Clap help, typed error messages and configurable report titles/footers are
explicit exceptions.
# azdocs.toml
[branding]
labels = "en"
en is the default and the only set shipped. Drop files into
<config dir>/azdocs/labels/ to change wording — the same drop-in pattern as
themes and queries.d/.
Overriding wording
A user file is partial: it is deep-merged over the built-in set it names, so it states only the keys it changes. Unknown keys are an error, so a typo fails loudly rather than being ignored.
mkdir -p ~/.config/azdocs/labels
cat > ~/.config/azdocs/labels/en.toml <<'EOF'
[report.summary]
chapter = "Management summary"
[common.plurals.resource]
one = "asset"
other = "assets"
EOF
On macOS the config directory is ~/Library/Application Support/azdocs/; on
Windows %APPDATA%\azdocs\.
A file named after a set that is not built in (say fr.toml) is merged over
en and selected with labels = "fr", so a full alternative can start as a
handful of keys and grow. [branding] labels naming a set that exists nowhere
is an error that lists the names that do.
The CLI treats a broken override as an error. The desktop logs the failure and
falls back to built-in wording so the application remains usable.
azdocs check reports a broken selected label pack before authenticating. The desktop resolves labels for the active tenant and reloads them when its
configuration is refreshed. After editing an override, reload the configuration
in Settings or restart the app.
Placeholders and plurals
Two conventions, the same in Rust and TypeScript:
| Form | Example | Filled by |
|---|---|---|
{name} | "Collected {rows} rows into a {status} snapshot" | the code that owns the string; an unfilled placeholder is left visible, never silently dropped |
{ one = "…", other = "…" } | resource = { one = "resource", other = "resources" } | a count: one for exactly one, other otherwise |
Placeholders are {snake_case}; braces that do not form one ({}, {Big})
are ordinary text, so an ARM id or JSON value inside a label is safe. A user
file may drop a placeholder it does not want; it cannot add one the code does
not fill.
Some strings begin or end with a space — " · {count} nested",
" matching “{search}”". They are fragments joined around a value; keep the
space.
Sections
| Section | Read by |
|---|---|
[common] | Every surface: severities, cover words, table column headers, governance headings, plural nouns, the Subscription scope stand-in group name |
[report.*] | The PDF/DOCX composer (summary, findings, governance, overview, type_index, estate, evidence), the Typst page counter, and the markdown, html, xlsx and csv emitters |
[diagram] | Graph titles, ×N tiles, container captions, the SVG legend and watermark, draw.io workbook sheet names |
[cli.*] | Progress lines and table headers of each command |
[tui.*] | Pane titles, keybars and field labels of azdocs browse |
[desktop.*] | The Tauri app: one table per view, plus topology.nodes and backend which the Rust side reads |
Two maps are keyed by values Rust serialises and are checked against it:
desktop.topology.edge_kinds must name every EdgeKind, and
desktop.topology.kind_classes every relationship family. Adding an edge kind
without a label fails topology-fallback.test.ts.
Not labels
Some text stays in code on purpose:
--helpoutput: clap derives it from doc comments at compile time.- Error messages (
thiserror), which are diagnostics rather than wording. - The report
titleandfooter, which[branding]already configures. - The
—shown for an absent value and the(none)location key inside the report data itself. - Typographic separators such as
·. - Machine values: severity keys, edge kind keys, view ids, CSS tokens.
Changing the built-in wording
Edit data/labels/en.toml. The report goldens and the print tests pin the
shipped wording, so a change there is reviewed through the snapshot diff — the
same way a diagram change is. Adding a string means adding a key to the file
and a field to the matching struct in src/labels/schema.rs; the desktop’s
generated-labels.json is regenerated by cargo test -p azdocs-desktop.
Excel sheet names come from [report.xlsx]; they are case-insensitive and
capped at 31 characters, and the category sheets keep their " queries"
suffix so a category named inventory cannot collide with the fixed sheet.
Next: Queries