mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
docs(i18n): translator's guide for the en-only foundation, current-state and changelog
docs/TRANSLATORS.md is rewritten for the foundation state: English shipped, and the locale-addition recipe front and center — the one-PR-per-locale procedure (catalogs, registration, CATALOG_LOCALES, pair behavior, parity gates). CURRENT-STATE.md documents the subsystem (file map, resolution order, selector, gates, deferrals) and the CHANGELOG records the foundation.
This commit is contained in:
1 parent
284c4d4601
commit
41378656c6
3 files changed
+340
-5
No files matched your search
@@ -2806,6 +2806,125 @@ test:track` 43 tracking invariants · headless QA harnesses under
|
||||
> attribution 18/18). New modules: `src/data/{motionModel,aircraftMeta,aircraftClass,aircraftIcons,issPass,routePlausible,dataCredits}.js`.
|
||||
> The live runtime now declares 29 voice tools; the 17→20 count above is retained only as milestone history.
|
||||
|
||||
### Internationalization / catalog locales (September 2026)
|
||||
|
||||
The application-owned UI is fully extracted into message catalogs; **en**
|
||||
is the only shipped locale in this foundation state — additional locales
|
||||
land as stacked follow-up PRs, one per locale (Spanish first), each
|
||||
following the locale-addition recipe in
|
||||
[`docs/TRANSLATORS.md`](./TRANSLATORS.md). English is the default, the
|
||||
source catalog, and the fallback. The subsystem lives in `src/i18n/`:
|
||||
|
||||
- **File map.** `src/i18n/locale.js` owns locale resolution, guarded storage
|
||||
(`gev:locale:v1`), the one-shot `?lang=` override, and `<html lang>`/`<html
|
||||
dir>` metadata. `src/i18n/index.js` owns the catalog registry, `t()`
|
||||
(interpolation + `Intl.PluralRules` plural selection), `formatNumber` /
|
||||
`formatDate`, `applyDocumentTranslations()`, and
|
||||
`persistLocaleAndReload()`. The shipped catalog is four flat message maps
|
||||
— `src/i18n/locales/en/{shell,cockpit,layers,setup}.js`, 912 keys (shell
|
||||
34, cockpit 369, layers 388, setup 121). Plural entries are the en
|
||||
`{ one, other }` shape; a future locale may add only cardinal categories
|
||||
`Intl.PluralRules` reports valid for it, and an entry lacking the selected
|
||||
category degrades to `other` at runtime. Locale-code normalization
|
||||
(`es-MX`/`es_419` → `es`, plus fr/ru/uk and variants) ships ahead of the
|
||||
locales on purpose: knowing a code is hygiene, shipping is catalog-driven
|
||||
through `CATALOG_LOCALES`.
|
||||
- **Selector.** The command dock carries a compact locale switch: a static
|
||||
`.dock-locale-switch` group container in `index.html` whose buttons
|
||||
(`.dock-locale-btn`) are rendered at runtime by `src/ui/applicationShell.js`
|
||||
`_initLocaleSelector()` — one per locale in the configured pair; while
|
||||
only English ships that is a single EN button. A click persists the
|
||||
choice and reloads the page with the hash preserved, so no live re-apply
|
||||
of already-rendered dynamic panels is needed.
|
||||
- **Locale pair config.** `GEV_DEFAULT_LOCALE` and `GEV_SECONDARY_LOCALE` in
|
||||
`.env`, injected as `import.meta.env` defines by `vite.config.js`; both
|
||||
values are validated against the shipped catalogs (`CATALOG_LOCALES`),
|
||||
and the offered set is `dedup([default, secondary, 'en'])`. While English
|
||||
is the only shipped catalog the built-in pair is en-only, so every
|
||||
configuration degenerates to a single offered locale; an invalid,
|
||||
unshipped, or degenerate configured pair falls back to that built-in
|
||||
en-only shape (dev-only warn). The first secondary-locale PR restores the
|
||||
built-in en+es pair.
|
||||
- **Resolution order.** `?lang=<locale>` (search string only; never
|
||||
persisted, never written into share links; stripped by
|
||||
`persistLocaleAndReload`; accepted only for offered locales) → stored
|
||||
`gev:locale:v1` (re-checked against the pair) →
|
||||
`navigator.languages` (regional variants normalize to the primary tag:
|
||||
`es-MX`/`es_419` → `es`) → the CONFIGURED default locale. Unsupported
|
||||
values defer to the next
|
||||
step rather than forcing English.
|
||||
- **Gates** (all under `node --test src/i18n/`, 40 tests):
|
||||
`catalog.test.mjs` enforces per-locale key, placeholder-name, and
|
||||
plural-shape parity with the strict exact-parity flip ON
|
||||
(`REQUIRE_FULL_PARITY`; `GEV_I18N_REQUIRE_FULL_LOCALE_PARITY=0` opts out
|
||||
for staged work; the loops are vacuous while only en ships — each locale
|
||||
PR meets them from day one);
|
||||
`markupCoverage.test.mjs` requires every `data-i18n*` attribute in
|
||||
`index.html` to resolve in every shipped catalog and rejects unknown attribute
|
||||
spellings; `i18n.test.mjs` pins precedence, guards, fallback,
|
||||
interpolation, the plural-selection contract (synthetic missing-category
|
||||
degradation; real-catalog plural pins arrive with each locale PR), and
|
||||
DOM application; `repairPass.test.mjs` anchors en byte-identity for
|
||||
extracted literals and rejects a locale-scoped CCTV wrap rule shipping
|
||||
ahead of its locale (per-locale value anchors arrive with each locale
|
||||
PR).
|
||||
- **Accepted deferrals (do not "fix" silently):**
|
||||
- The military-awareness subject header literal `FLIGHT / VESSEL WINDOW`
|
||||
(`src/data/militaryAwareness.js`) stays English; the literal is
|
||||
test-pinned in `src/data/militaryAwareness.test.mjs`.
|
||||
- The visible cockpit-brief tab tokens `SIG` / `NEWS` / `LOCAL`
|
||||
(`index.html`) stay untranslated to match the runtime keys; their
|
||||
`aria-label`s ARE localized (`cockpit.brief.tab*AriaLabel`).
|
||||
- `src/voice/gevActions.js` tool-result confirmation strings stay English
|
||||
by contract (voice tool schemas and spoken confirmations are
|
||||
keep-English; see the Keep-English boundary in `docs/TRANSLATORS.md`).
|
||||
- Number formatting is still the pre-i18n `toLocaleString` policy at:
|
||||
`src/ui.js:1442`, `src/data/satellites.js:829`,
|
||||
`src/data/flights.js:436` (`'en-US'` pinned), and
|
||||
`src/data/rocketLaunches.js:2281/2299/2364/2371/2374`
|
||||
(default-locale). A locale-aware number-format policy is deferred; the
|
||||
`formatNumber` helper exists in `src/i18n/index.js` when that lands.
|
||||
|
||||
### Overpass proxy mirror rotation (September 2026)
|
||||
|
||||
- `/api/overpass` fans out across four public mirrors. `overpassPayloadIsData()` governs cache reads, writes, and stale fallback: only a 2xx that is neither rate-limited nor a body-level runtime error qualifies. Previously stored refusals are ignored on both fresh and stale reads, so upgrading does not require manually clearing the disk cache.
|
||||
- HTTP refusals such as 406 now rotate alongside the existing network, rate-limit, and runtime-error cases. A refusal from one mirror no longer prevents reaching healthy alternatives or persists under the seven-day road/month-long boundary cache TTLs. Concurrent identical queries share one mirror sequence; if it fails, both the initiating and joined callers can use the same last-good data.
|
||||
- A refusal every mirror agrees on is still reported with the first mirror's status and body, so a genuinely malformed query says what upstream said — but only after every mirror has had the chance to answer it. `fetchOverpassPayload` takes injectable endpoints and fetch so the rotation is tested without a live mirror (`src/overpassProxy.test.mjs`).
|
||||
|
||||
### Share-link v2 layer state (August 2026)
|
||||
|
||||
- Generated share links use a deterministic v2 hash. Existing camera, visual,
|
||||
HUD, detection, post-processing, celestial, scope, and map-stack fields remain,
|
||||
with compact fields for enabled layers, allowlisted layer options, panel state,
|
||||
and the active preset's allowlisted shader controls. An absent layer field uses
|
||||
deterministic defaults; an explicit empty field means no enabled layers.
|
||||
- The registry seals only after all 16 production layers register, and every
|
||||
layer has an explicit serialization disposition. Unknown enabled-layer tokens
|
||||
reject the layer payload; unknown option tokens are ignored. Restoration
|
||||
settles independently per layer so one failed or unavailable source cannot
|
||||
block its siblings.
|
||||
- Stable visible options are limited to aircraft 3D mode, selected civilian and
|
||||
military flight IDs, Satellite catalog and selection, CCTV coverage/projection/
|
||||
auto-hop, and Radio filter/volume. Playback and tuning, live-data health,
|
||||
calibration, caches, lifecycle state, temporary Context ownership, and derived
|
||||
effects are deliberately excluded. Radio restore never selects or plays a
|
||||
station.
|
||||
- Normal loads restore the last successful explicit UI, voice, or tool choice
|
||||
from versioned local storage. Any valid camera share wins for the current load
|
||||
without overwriting recipient preferences. Restore ownership is split by
|
||||
visibility, option/selection, camera, visual, map, and individual panel lane:
|
||||
a newer explicit action supersedes only the field it owns. In particular,
|
||||
navigation cannot turn unrelated layers off, and an option change cannot
|
||||
|
||||
#### Keep-English adjudications (post-merge catch-ups)
|
||||
|
||||
- `src/ui/visualPresets.js` `'ELASTIC'` — detection-allocation STRATEGY IDENTIFIER (persisted
|
||||
under `gev:detection-allocation`, compared via `dataset.allocation ===`), not display copy.
|
||||
- `src/ui/layerPanel.js` guidance meta — the `{source} · {statusMessage}` composition uses a
|
||||
locale-neutral interpunct; the statusMessage itself IS localized via `installationFeedback`.
|
||||
- `src/ui/mapSourceControls.js` `'...'` switching label and the orbit `'↻'` glyph —
|
||||
punctuation/glyphs, identical across locales.
|
||||
|
||||
## Canonical Docs Order
|
||||
|
||||
Use docs in this order when details conflict:
|
||||
|
||||
Reference in new issue
Block a user