Diffing the Arabic region page against live turned up three table headers rendering differently from ours. Tracing them proved we had copied FAITHFULLY: our values are verbatim in root-dx-life's i18n/locales/ar/common.json under exactly those keys. The live site renders different strings, and none of the new ones appears anywhere in that file. The read-only clone we are told to copy from has fallen behind the site we are told to match. So the two standing instructions disagreed, and the scope ruling settles it: a change must MATCH what is on dx-life's /regions pages, and those pages are live. Copying a string out of the live DOM still translates nothing, so the live wording wins. dx-life has revised its Arabic terminology -- people groups from بشرية to شعبية, engaged from منخرط to مخدومة, adopted from تم انتماؤه to متبنّاة. Every value was mapped BY MEASUREMENT, never by reading Arabic, which I cannot check: the table by its logical column order (Country, People Groups, 1+ People Praying, Adopted, Engaged) against their /ar table; the three cards heading-for-heading and line-for-line; and the two remaining labels by their own class names, region-stat__label inside "region-stat | card" and .color-brand-lighter, both present on their EN and their AR page. Result: 60 of the 61 Arabic strings our page renders are now identical to live, up from 51. The table headers match byte for byte. The one remainder is their own map-note template, ours byte-identical to their file, which their page does not display -- so there is no live evidence it changed and it is left alone. Four other keys also contain مجموعة بشرية and are deliberately NOT touched: the revision live may well be partial, and without a rendered string to measure against there is nothing to copy. Two of my own oracles were corrected on the way. The page-text diff filtered to strings under 60 characters, which silently excluded every long goal sentence -- raised to 220, which is how the interpolated summary line surfaced at all. And that diff marks a rendered string "clone lacks it" whenever the clone holds a TEMPLATE with placeholders, so interpolated text can never match a raw value set; that is a property of the oracle, not evidence of invention. check:i18n-provenance now records these nine as taken from live, each beside the value the clone still carries, so the decision stays auditable and a future clone refresh can be checked against it. Any other locale and any other key still fails, so a hand-translated string remains exactly as catchable as before. Parity PASS, SRI PASS, and the RTL region-page diff still reports 0 differences. |
||
|---|---|---|
| .. | ||
| api | ||
| colors | ||
| components | ||
| composables | ||
| constants | ||
| data | ||
| i18n | ||
| layouts | ||
| maps | ||
| packet | ||
| scripts | ||
| stores | ||
| styles | ||
| utils | ||
| 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.