From 584732c3ecea2e1b4e472e5dbcdae58c229650fe Mon Sep 17 00:00:00 2001 From: Meir Michanie Date: Thu, 5 Nov 2026 22:09:09 -0600 Subject: [PATCH 1/8] i18n(he): complete and ship Hebrew - Add the full catalog (2940 entries keyed by the English text; 75 plural entries carry one/two/other per Intl.PluralRules('he')), reviewed for meaning, terms, separators and label length. - Register he: he-IL and he map to it; it joins RTL_LOCALES so mirrors the chrome through logical properties and rtl.css. - rtl.css: Noto Sans Hebrew (loaded with the other Google fonts) leads the mono and sans stacks, tracking released like Arabic, HUDs keep JetBrains Mono for Latin telemetry. - same-as-english: instrument codes and HUD readouts stay as printed (HDG/BRG/CRS/FOV/CRT/NVG/FLIR/CAL/SRC, MW units, Sentinel-2, km/h...). - docs/translations/he.md: style, plurals and glossary. - docs: TRANSLATORS.md and CURRENT-STATE.md updated; normalizeLocale test covers he-IL. --- docs/CURRENT-STATE.md | 24 +- docs/TRANSLATORS.md | 4 +- docs/translations/he.md | 65 + index.html | 2 +- scripts/package-boundaries.json | 46 + src/i18n/i18n.test.mjs | 3 + src/i18n/index.js | 2 + src/i18n/locale.js | 6 +- src/i18n/locales/he.json | 3242 +++++++++++++++++++++++++++++++ src/i18n/same-as-english.json | 89 + src/ui/localePicker.test.mjs | 4 + src/ui/styles/rtl.css | 37 + 12 files changed, 3509 insertions(+), 15 deletions(-) create mode 100644 docs/translations/he.md create mode 100644 src/i18n/locales/he.json diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index 05240d922..8ebabaf61 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -4589,7 +4589,9 @@ test:track` 43 tracking invariants · headless QA harnesses under ### Interface localization (October 2026) -Shipped locales: **en** (source and fallback), **ar**, **de**, **es**, **fr**, **it**, **ja**, **pt** (Brazilian Portuguese), **ru**, **uk**, **zh-CN** and **zh-Hant**. The code lives in +Shipped locales: **en** (source and fallback), **ar**, **de**, **es**, **fr**, **he**, +**it**, **ja**, **pt** (Brazilian Portuguese), **ru**, **uk**, **zh-CN** and +**zh-Hant**. The code lives in `src/i18n/`. How to mark UI text: [`docs/I18N.md`](./I18N.md); translator workflow: [`docs/TRANSLATORS.md`](./TRANSLATORS.md). @@ -4603,19 +4605,21 @@ Shipped locales: **en** (source and fallback), **ar**, **de**, **es**, **fr**, * `navigator.languages` → English. Any `pt` tag (`pt-BR`, `pt-PT`) selects `pt`. Chinese tags default to `zh-CN`; Traditional Chinese tags select `zh-Hant`. Explicit `Hans` selects `zh-CN` regardless of region. `?lang=` is not stored, and share links drop it, so a recipient keeps their own language. The globe picker in the - bottom-right corner (bottom-left in Arabic) (`src/ui/localePicker.js`) stores the choice, drops + bottom-right corner (bottom-left in Arabic and Hebrew) +(`src/ui/localePicker.js`) stores the choice, drops `?lang=` (keeps it only when storage is blocked) and switches in place: views re-render, code that published translated text words it again through `onLocaleChange`, and ``/`dir` and the page's `data-i18n` markup follow. Nothing is lost; a toast already on screen keeps its words. -- **Right to left.** Arabic (`ar`) is in `RTL_LOCALES`, so ``: - the title, style indicator, both panel stacks and their icon rails swap - sides through logical properties (`inset-inline-*`, `margin-inline-*`), the - dock and corner row reverse their order, and `src/ui/styles/rtl.css` holds - the rest: no letter-spacing on Arabic text, Noto Sans Arabic in the font - stacks, the intel HUD kept as a left-to-right instrument overlay, FM seek - and the radio dial kept left to right. Intl formatters get `ar-u-nu-latn`, - so numbers and dates keep Western digits. +- **Right to left.** Arabic (`ar`) and Hebrew (`he`) are in `RTL_LOCALES`, so + ``: the title, style indicator, both panel stacks and their + icon rails swap sides through logical properties (`inset-inline-*`, + `margin-inline-*`), the dock and corner row reverse their order, and + `src/ui/styles/rtl.css` holds the rest: no letter-spacing on Arabic and + Hebrew text, Noto Sans Arabic and Noto Sans Hebrew in the font stacks, the + intel HUD kept as a left-to-right instrument overlay, FM seek and the radio + dial kept left to right. Intl formatters get `ar-u-nu-latn`, so numbers and + dates keep Western digits. - **Gate.** `npm run i18n` (and `src/i18n/catalog.test.mjs` under `npm test`) extracts every message and fails on missing, empty, unused, placeholder-mismatched, still-English (plural forms included) or diff --git a/docs/TRANSLATORS.md b/docs/TRANSLATORS.md index f83316c7a..d08711193 100644 --- a/docs/TRANSLATORS.md +++ b/docs/TRANSLATORS.md @@ -1,6 +1,6 @@ # Translating God's Eye View -Shipped languages: **English** (source and fallback), **Arabic** (`ar`), **German** (`de`), **Spanish** (`es`), **French** (`fr`), **Italian** (`it`), **Japanese** (`ja`), **Brazilian Portuguese** (`pt`), **Russian** (`ru`), **Ukrainian** (`uk`), **Simplified Chinese** (`zh-CN`) and **Traditional Chinese** (`zh-Hant`). +Shipped languages: **English** (source and fallback), **Arabic** (`ar`), **German** (`de`), **Spanish** (`es`), **French** (`fr`), **Hebrew** (`he`), **Italian** (`it`), **Japanese** (`ja`), **Brazilian Portuguese** (`pt`), **Russian** (`ru`), **Ukrainian** (`uk`), **Simplified Chinese** (`zh-CN`) and **Traditional Chinese** (`zh-Hant`). ## How it works @@ -63,4 +63,4 @@ These are contracts, not copy: layer ids and registry keys, status enums and oth ## Language notes -Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/.md`: [Arabic](./translations/ar.md), [German](./translations/de.md), [Spanish](./translations/es.md), [French](./translations/fr.md), [Italian](./translations/it.md), [Japanese](./translations/ja.md), [Brazilian Portuguese](./translations/pt.md), [Russian](./translations/ru.md), [Ukrainian](./translations/uk.md), [Simplified Chinese](./translations/zh-CN.md), [Traditional Chinese](./translations/zh-Hant.md). Read it before translating, and add a term there when you settle on one. +Each language keeps its glossary, plural forms, units and style in its own file, `docs/translations/.md`: [Arabic](./translations/ar.md), [German](./translations/de.md), [Spanish](./translations/es.md), [French](./translations/fr.md), [Hebrew](./translations/he.md), [Italian](./translations/it.md), [Japanese](./translations/ja.md), [Brazilian Portuguese](./translations/pt.md), [Russian](./translations/ru.md), [Ukrainian](./translations/uk.md), [Simplified Chinese](./translations/zh-CN.md), [Traditional Chinese](./translations/zh-Hant.md). Read it before translating, and add a term there when you settle on one. diff --git a/docs/translations/he.md b/docs/translations/he.md new file mode 100644 index 000000000..6d531cab5 --- /dev/null +++ b/docs/translations/he.md @@ -0,0 +1,65 @@ +# Hebrew (`he`) + +Catalog: `src/i18n/locales/he.json`. General rules: [TRANSLATORS.md](../TRANSLATORS.md). + +## Style + +- Address the user with a masculine imperative, Google style: הסתר, הצג, נסה שוב, התקרב. Menu items and tooltips take the noun form: הסרת {name}, הרחבת {name}, שינוי הצבע של {name}. +- Sentence case: Hebrew has no case forms, so UPPERCASE English is normal sentence style here; short HUD labels stay short, favor an abbreviation over a wrapped line. +- Keep the `·`, `—`, `→`, `↗`, `…` separators. Latin codes read inside RTL text because the app isolates interpolated values; leave them alone. +- Units follow the catalog: ק"מ, מ׳, קמ"ש, שנ', דק', שע'; instrument chips keep the Latin unit (MW, KM, FT, KTS, kn) and codes (HDG, FOV, CAL, SRC, REC) exactly as in English — see `same-as-english.json`. + +## Digits and direction + +- Western digits 0–9 only, like every catalog: "5 מטוסים", "26.08.2026". Dates in scene labels use dd.mm.yyyy. +- `{direction}` values are adverbs (שמאלה, ימינה, ישר); maneuver templates are written to place them after the verb: פנה {direction} אל {road}. +- Values inserted by t() are isolated (U+2068…U+2069); do not add manual RTL marks — write the sentence as natural Hebrew and let isolation do the rest. + +## Plurals + +A `tn()` entry needs three forms under `Intl.PluralRules('he')`: + +| Form | Counts | Example | +| ------- | ------------------------- | -------------- | +| `one` | 1 | 1 מצלמה | +| `two` | 2 | 2 מצלמות | +| `other` | 0, 3, 10, 100, fractions… | 5 מצלמות | + +With {count} shown as a digit, `two` and `other` share the plural noun (2 מצלמות, 5 מצלמות); `one` takes the singular (1 מצלמה). For constructs that resist agreement with a noun (אין, הכול, זמין), phrase around the number: "{count} תחנות מדווחות" is fine, but prefer "ממתין: {count}" over a mismatched genitive chain. + +## Glossary + +| English | עברית | +| ---------------------------------------------- | ----------------------------------------------------- | +| layer / data layer | שכבה / שכבת נתונים | +| feed | פיד | +| source / data source / Provider Settings | מקור / מקור נתונים / הגדרות הספקים | +| LIVE / live data / LIVE TRACK | חי / נתונים חיים / מעקב חי | +| SIMULATED | מדומה | +| stale / degraded / unavailable | מיושן / מופחת / לא זמין | +| key (API key) / POWER UP | מפתח / אתחול | +| globe / map / map source / basemap | גלובוס / מפה / מקור מפה / מפת בסיס | +| aircraft / flight / military flight | מטוס (כלי טיס in class lists) / טיסה / טיסה צבאית | +| vessel / ship / ships | אונייה / אוניות | +| satellite | לוויין | +| launch (rocket) / space mission | שיגור / משימת חלל | +| contact / tracking | מגע / עקיבה | +| installation / site | מתקן / אתר | +| camera / CCTV camera / ALPR camera | מצלמה / מצלמת CCTV / מצלמת ALPR | +| earthquake / active fire / cyclone | רעידת אדמה / שרפה פעילה / ציקלון | +| scene / shot | סצנה / שוט | +| briefing / panel / dock | דיווח / פאנל / עגינה | +| visual preset / style | ערכת ראייה / סגנון | +| Scope (circular viewport mask) / keyhole | סקופ / חור המנעול | +| heading (compass °) / course | כיוון / מסלול | +| HDG / BRG / CRS / FOV / DEST / SPD / RANGE | בלי שינוי — קודי מכשיר | +| advisory (NHC/CPHC cyclone) | ייעוץ; Advisory center — מרכז הייעוץ | +| Street View (Google) | Street View, בלי תרגום | +| Street Level / Street Level layer | Street Level, בלי תרגום (שם שכבה) | +| WHOT/BHOT, Ironbow, CRT, NVG, FLIR | בלי שינוי — קודים ושמות מצבים | +| PREV / NEXT | הקודם / הבא | +| anchor / data pack / asset bundle (scene) | עוגן / חבילת נתונים / חבילת נכסים | +| witness / geolocated source | עד ראייה / מקור נתון גיאוגרפית | +| contained (wildland fire) / FRP | הכלה / FRP, בלי שינוי | + +Latin product, provider and dataset names stay as printed: Google Maps, Cesium ion, OpenSky, ADS-B, AIS, KartaView, Mapillary, Panoramax, Overpass, InciWeb, iNaturalist, Acartia, NASA FIRMS, NOAA, USGS, CelesTrak, TomTom, Sentinel-2, Landsat, VIIRS, HLS, S2 GhostMaps, TeleGeography. diff --git a/index.html b/index.html index 291b99708..5cfee67ea 100644 --- a/index.html +++ b/index.html @@ -21,7 +21,7 @@ - +