The legend's region sections, its Deaf row and its one-country zones, the wall's card names, the print progress and error messages, the map's status badge and the Population column all rendered English in every locale. None of them was visible to check:hardcoded-english: they were single words, .js modules, Error() arguments, library components or number formatting. - Legend: region rows through one REGION_KEY table shared with the wall (poster.region_*, new region_deaf); zones through zoneTitle (tier A by country, the Deaf row by its bloc name); node ids stay English-derived. - Wall: card labels through zoneTitle, so the Show-on-map name, alt text, tooltip, HUD title and printed title agree with the legend and packet. - Errors a reader sees are keyedError(key, English, params); errorText(e, t) shows them translated, and an unkeyed error still shows its own message. Developer detail for a failed data load goes to the console; the badge says upgMap.mapDataFailed. - Population: Intl compact notation in the app's locale, same precision. - Country Posters: the unsupported card's reason is messages.countryPosterTooMany, not the data file's English note. - Strings only the UPG-100 map shows move to a new upgMap area, so other bundles do not carry them (country-posters 1,490,907 bytes). - check:hardcoded-english judges keyedError's English as a fallback (quiet when the key resolves everywhere, a finding when it does not); check:label-key-coverage follows REGION_KEY to legend-tree.js and covers the legend's table and its regionFor producer. Both self-tests two-sided. |
||
|---|---|---|
| .. | ||
| api | ||
| charts/whiteboard | ||
| colors | ||
| components | ||
| composables | ||
| constants | ||
| dashboards | ||
| data | ||
| elements | ||
| i18n | ||
| layouts | ||
| lists | ||
| maps | ||
| packet | ||
| packets | ||
| scripts | ||
| stores | ||
| styles | ||
| utils | ||
| vendor/cldr | ||
| index.js | ||
| ProfileLoader.vue | ||
| README.md | ||
library/ (@map) — the shared map template
The other half of the architecture (see ../plugin-designs/README.md):
every map in plugin-designs/<your-map>/ composes the reusable, parameterized pieces that live here.
Fix something here and every map benefits on the next build; break something here and every map
breaks — read components/WARNING.md before touching shared pieces.
| Folder | What lives there |
|---|---|
ProfileLoader.vue |
The root of every bundle: parses profile-config, loads the profile, provides the stores + config |
components/ |
Shared UI — map, legends, controls, popup (PeopleGroupDetail), tables, charts, hints (README) |
composables/ |
Shared logic — map engine (useMapInstance), provider switch, shadow-DOM styles, theming |
stores/ |
Per-instance Pinia stores (ui / map / data) — provided by ProfileLoader, injected by children |
api/ |
Data-source registry (sources.json) + fetch layer — the JAMstack runtime wiring |
colors/ |
Color sets maps opt into via profile-config.colorSet |
i18n/ |
The shared string catalogs (all maps speak the same languages) |
data/ |
Small shared datasets baked at build time (big served data lives in ../data/) |
constants/ |
Shared constants |
scripts/ |
Maintainer pipelines (posters, research) — not part of any bundle |
The rule of thumb (same as WARNING.md): custom code in your app-profile, reusable code here — and things only move from the first to the second once they've earned it.