PPLR legend: its loading, empty and overflow lines speak the reader's language

PPLR's SemanticTreeLegend (a diverged copy of the library's; retiring it is card
RETIRE-PPLR-SEMANTICTREELEGEND) still typed in five strings: "Loading {label}…",
"Loading data…", "No data at this level", "Showing top {n} of {m}" and "use the
geocoder above to find the rest". The keys exist in all 11 locales since
d4359163 (legend.loadingRows / loadingData / noDataAtThisLevel / showingTop /
useGeocoderHint), which the library copy uses.

They now go through the component's existing guarded translator (ta), with the
English added to its fallback table, so a host without i18n still reads
English, never a key. Numbers keep their current toLocaleString (numerals held).

Headless: build OK, and check:no-free-identifiers, i18n-parity and
profiles-mount pass. (check:ui-strings-have-keys, which found this, is not on
main yet.)
This commit is contained in:
Doxa Maps 2026-09-26 13:24:07 +00:00
parent 85a4172644
commit 6bdfa59437

View file

@ -30,6 +30,10 @@ const A11Y_EN = {
'legend.a11y.expandRow': 'Expand {label}', 'legend.a11y.collapseRow': 'Collapse {label}',
'legend.a11y.clearSelection': 'Clear selection',
'aria.expandLegend': 'Expand legend', 'aria.collapseLegend': 'Collapse legend',
// The legend's own states and hints (keys shared with library/components/legends/SemanticTreeLegend.vue).
'legend.loadingRows': 'Loading {label}…', 'legend.loadingData': 'Loading data…',
'legend.noDataAtThisLevel': 'No data at this level', 'legend.showingTop': 'Showing top {n} of {m}',
'legend.useGeocoderHint': 'use the geocoder above to find the rest',
}
const fillA11y = (str, p) => String(str).replace(/\{(\w+)\}/g, (m, k) => (p && k in p ? p[k] : m))
let ta = (key, p) => fillA11y(A11Y_EN[key] ?? key, p)
@ -487,14 +491,13 @@ function rowClasses(row) {
<div v-if="tabLoading && !visibleRows.length" class="stl-empty stl-loading">
<span class="stl-spinner"></span>
<span>Loading {{ tabList[activeTab]?.label || 'rows' }}…</span>
<span>{{ ta('legend.loadingRows', { label: tabList[activeTab]?.label || 'rows' }) }}</span>
</div>
<div v-else-if="!visibleRows.length && nodes.length === 0" class="stl-empty">Loading data…</div>
<div v-else-if="!visibleRows.length" class="stl-empty">No data at this level</div>
<div v-else-if="!visibleRows.length && nodes.length === 0" class="stl-empty">{{ ta('legend.loadingData') }}</div>
<div v-else-if="!visibleRows.length" class="stl-empty">{{ ta('legend.noDataAtThisLevel') }}</div>
<div v-if="topNodesOverflow > 0" class="stl-overflow">
Showing top {{ tabList[activeTab].topLimit.toLocaleString() }} of
{{ topNodesAll.length.toLocaleString() }} —
<span class="stl-overflow-hint">use the geocoder above to find the rest</span>
{{ ta('legend.showingTop', { n: tabList[activeTab].topLimit.toLocaleString(), m: topNodesAll.length.toLocaleString() }) }} —
<span class="stl-overflow-hint">{{ ta('legend.useGeocoderHint') }}</span>
</div>
</div>
</div>