Commit Graph
26 Commits
Author SHA1 Message Date
Sameh Khamis 52507a0755 Draw no buoy for a virtual aid to navigation
A virtual aid (AIS message 21's VirtualAtoN flag) is a mark broadcast
where nothing physical stands, so drawing it as a buoy showed a mark
that is not there. The vessel source record now carries `virtual`
(false unless a source says true; any source may set it), AISStream
sets it from VirtualAtoN, and the vessel layer keeps such an aid's
disc: vesselModelSpec returns null for it and the layer gathers no
model item for it. Its card, selected card and readout add VIRTUAL
after its kind.
2026-11-14 11:07:13 -08:00
Sameh Khamis 6c7fe48f40 Show an aid to navigation's kind, not a speed or heading
A buoy's card, selected card and HUD readout showed "0.0KT · 135°" from
whatever its source reported. A fixed mark has neither, so they now show
its kind alone, whole ("CARDINAL MARK N", which the 14-character type cut
read as "CARDINAL MARK "), in the bone white of its disc.

isAidToNavigation now knows every kind an aid report names ("Light, with
sectors", "Fixed structure off shore" had no aid word), leaves out a
"Buoy Layer" as it does a tender, and matches each type text once: the
vessel layer asks per vessel on its rotation pass, which now skips the
aid discs it never turns.

Aid rows no longer cost ships their place: aisStreamRows lists every
vessel ahead of every aid, so the layer's 12,000-row request never drops
a ship for a buoy, and vessels_in_area (and the brief built on it)
counts ships only. An aid's name runs on into its NameExtension.
2026-11-14 10:02:59 -08:00
German Khokhlov d42b6fe764 Merge branch 'main' into german/map-render-error-state 2026-11-13 18:47:36 +04:00
German Khokhlov 7314dac1ce i18n: review and fix the strings added since the last translation review
Reviews the 474 strings that 27 pull requests added since the last
review, in all twelve catalogs, and fixes what the review confirmed:
wrong agreement when a placeholder takes a neutral value, plural-less
counts that read "1 sightings", terms that differ from the glossaries,
and typography the language guides set. Also applies most of the
findings earlier reviews left open.

zh-Hant is converted from zh-CN again. The new strings had been
translated separately with Taiwan vocabulary. The zh-Hant guide lists
two more characters OpenCC picks wrongly.

Three tests expected the old German and Spanish wording.
2026-11-13 17:49:54 +04:00
Sameh Khamis 347e77d1f6 feat(vessels): a selected vessel shows its Open Vessel Photos photo and MMSI
Selecting a vessel asks Open Vessel Photos (a free, keyless API) for its
photo by MMSI, once per MMSI. The CONTACTS view shows it under the vessel's
name and MMSI with the photographer, the photo's open licence and a link to
the vessel's page; only images on Open Vessel Photos' own host are shown, and
an answer about another MMSI is no photo. The vessel source exposes the lookup
as getEnrichment({kind: 'photo'}) and fetchOpenVesselPhoto for applications
with their own vessel source.
2026-11-12 20:10:30 -08:00
Said Turksever db80d82b8d Add the Data Library: live regional datasets, tiles and packs
DATA LAYERS keeps its curated core layers; regional and niche sources
live in the Data Library, opened from Browse data library at the foot
of the panel. Each entry is a JSON manifest in src/library/entries/
pointing at a live upstream (query API, provider-hosted file or tile
endpoint), so nothing is bundled and a self-hosted instance hosts no
data. Sources without CORS go through one allowlisted /api/library
route. Kinds: dataset (GeoJSON, CSV, JSON records, ArcGIS, partitioned
GeoParquet), tiles (XYZ, WMS/ArcGIS bbox export, terrarium relief) and
pack. Selections persist and travel in share links as lib=, separate
from the core layer tokens. Library rows get Zoom and Remove icon
chips that work while the layer is off, rendered through RailChips.
Strings are translated in every locale.
2026-11-12 12:26:45 +00:00
Denis Groshev 13818d0b9f Merge upstream main into denis/rail-layer 2026-11-11 18:02:52 +01:00
German Khokhlov 897a74ea27 Merge remote-tracking branch 'origin/main' into german/map-render-error-state
# Conflicts:
#	src/i18n/locales/ar.json
#	src/i18n/locales/de.json
#	src/i18n/locales/es.json
#	src/i18n/locales/fr.json
#	src/i18n/locales/he.json
#	src/i18n/locales/it.json
#	src/i18n/locales/ja.json
#	src/i18n/locales/pt.json
#	src/i18n/locales/ru.json
#	src/i18n/locales/uk.json
#	src/i18n/locales/zh-CN.json
#	src/i18n/locales/zh-Hant.json
2026-11-11 19:33:49 +04:00
Denis Groshev 830c080803 feat(rail): add a Rail layer with keyless live trains
Live trains from 30 keyless operator feeds: GPS positions from 29 and
Irish Rail's station reports, shown as the operators publish them. 28
work out of the box; Renfe long and medium distance and KTMB appear once
their pack is built, because their vehicles name no route.

Packs are opt-in (scripts/build-rail-paths.mjs): the operator's own
route lines, stop names, next stops and trip-update delays for live
trains. Nothing downloads when the app starts, no train is placed from a
timetable, and no request carries a deployer's key.
2026-11-11 16:06:22 +01:00
German Khokhlov 8334262109 Street Level: the action's failure cards in the interface language
The voice card showed English for show_street_level failures the catalog
did not know: a missing key, a map or source that could not be switched on,
the layer, invalid coordinates, an imagery fallback and the filter clause.
They now translate like the other action errors (exact messages and
patterns in speech.js), in all twelve languages; the spoken line stays
English, and the filter clause names the filters as their chips do.
2026-11-11 13:46:10 +04:00
Said Turksever e0fedc13dd Street Level: a link whose source has no working key says why 2026-11-11 09:21:06 +00:00
Said Turksever 5b7e917f94 Street Level: Hebrew strings for the show_street_level action 2026-11-11 08:55:55 +00:00
German Khokhlov 771ed98e3b Add the render failure notice in Hebrew 2026-11-11 12:48:44 +04:00
Sameh Khamis cbbf55cacd feat(vessels): key vessels by their source's stable id, and share a selected vessel
AIS Vessels are keyed by the id their live source gives, with the MMSI as an
attribute: an MMSI can be shared, spoofed or reused, so two vessels with one
MMSI are now two vessels. Looking a vessel up or selecting it by MMSI still
finds it.

A share link made while a vessel is selected opens that vessel. A UUID vessel
id travels as 16 bytes in a new thing field (13). A shared thing that is not
reporting now says so in a sentence per kind, with its id (ICAO, NORAD, MMSI
or vessel UUID) on a second line.
2026-11-10 18:12:53 -08:00
Sameh Khamis 2992232fcc fix(shipwrecks): tidy after merging main: the retired-token test reuses the retired token, natural Hebrew, voice comment beside its entry
- layerStateTokenLedger.test: the retired-token reuse case now offers the
  retired token (02) to the newcomer, not News's 00.
- he.json: the catalog's singular imperative, {count} first in the plural,
  Wikidata read as one source, and smoother legend and info text.
- layerManifest: News after Shipwrecks, so the prompt-budget comment stays
  next to the entries it explains.
- CURRENT-STATE: Prettier-formatted (table column, blank line before a heading).
2026-11-10 14:07:07 -08:00
Sameh Khamis 8ff22f1a12 Merge main into feat/shipwrecks
Main added the News layer at the same places: both layers are kept in the
layer names, panel order (News stays last of Events), standalone sources,
voice manifest, credits, DATA_SOURCES and the CURRENT-STATE table. News took
share-link token 00 first, so Shipwrecks moves to 01 (ledger, registry,
CURRENT-STATE and the token tests). The catalog now has 40 layers and the
share-link registry 38. Shipwreck strings are added to the new Hebrew
catalog; the other catalogs keep both sides' strings.
2026-11-10 14:03:39 -08:00
Mazeyar Moeini FeizabadiandClaude Fable 5.2 bb7e7ecad6 fix(news): Hebrew strings for the News layer and the gate modules in the news boundary
main added the he locale and the news provider now imports the same-site gate.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-10 21:33:01 +01:00
Sameh Khamis 8fec5a76bf feat(flights): a tracked flight's trail splits at gaps, follows the drawn aircraft, and a lost aircraft coasts then reads SIGNAL LOST
The trail no longer joins a day of history into one line. It lifts the pen
across a gap of more than 48 minutes, an implied speed over 1,500 kt, or a
report without altitude (a parked aircraft within 0.1 nm for under 3 h stays
joined), and every history point is kept as its own segment. History never
gets an invented altitude. The live end is the path the aircraft was drawn
along, thinned to its shape, so it no longer cuts corners through turns; a
late report trims what was drawn after it. Old segments are frozen in chunks,
so a 2,000-point trail costs about 0.1 ms a frame.

A tracked aircraft that misses an update shows STALE and is dimmed. It keeps
flying on its last speed and heading for five minutes (at most 1,500 kt),
then stops, dimmed, labelled SIGNAL LOST with the time since its last report,
and is kept for ten minutes after that report so the camera keeps its target.
Aircraft on or near known ground hold at their last report instead of
coasting. Military flights follow the same rules.
2026-11-10 11:30:59 -08:00
Sameh Khamis 6eb0729832 fix(firms): translate the snapshot-end label for Hebrew 2026-11-10 10:35:16 -08:00
German Khokhlov b6c2ba379b i18n(he): translate the photo credit added on main 2026-11-10 21:26:15 +04:00
German Khokhlov 7571e42556 i18n(he): apply the second translation review
- RECORD is «רשומה», a record rather than a recording.
- Time abbreviations end in the geresh again (דק׳, שנ׳, שע׳, ימ׳), and the
  counted forms agree with 1.
- Numbers after a Latin name, ordinals and units keep their order in RTL.
- Meaning, agreement and domain terms fixed across the catalog: cyclone
  advisories and storm centre, sensor swath, track-up, cinematic, tropical
  depression, pilot and sailing vessels, chips, metered billing, radio static,
  airspace, NOT AN ALL-CLEAR, and the remaining review items.
- LOOK and OFF-NADIR are translated; {value} KM stays Latin as an instrument
  readout, like KM/S.
- rtl.css shares the Arabic and Hebrew letter-spacing reset and drops the
  duplicated Arabic rules; he.md and its glossary follow the catalog.
2026-11-10 21:23:28 +04:00
Meir Michanie f79ceb690f i18n(he): apply review (#1594)
Before merging: singular 'one' forms from the review table (44 entries),
counters keep their order across the slash (מתוך, as Arabic المن), the
lightning layer says ברקים (the legend now counts ברק strikes, the help
text keeps 110°E Latin), configured-elsewhere keys are promised
untouched, Punk is פאנק רוק, dock/panel side labels follow the mirrored
layout, and the HUD-summary English guard covers he (NON_LATIN_LOCALES,
tested) — documented in Adding a language along with format-scope.

Suggestions and nits: restricted is מוגבל, stage recovery is החבה not
שחזור, voice-inactivity names the behavior, lane directions use
attributes (השמאלי) and around is לאחור, Ironbow and KM/S stay Latin in
same-as-english, {age} no longer doubles לפני, typos and garbled words
fixed (תנאים, ידנית, ודאות, מקלט, זמניים, ערוץ 14, מעונן חלקית, אין אות
קריאה, Tab לתצוגה מקדימה, השאר ריק, היוועץ), counted units shortened
(שנ' דק' שע' ימ'), terminology unified (briefing תדריך, forecast תחזית,
course מהלך, אונייה, שריפה), rtl.css shares the mono redirect under
:is(:lang(ar), :lang(he)) and its comments match the rules,
worldOverlayTokens adds Noto Sans Hebrew to the canvas card fonts, he.md
gets the fraction-aware plural table, iw/iw-IL map to he (tested).
2026-11-09 14:41:36 -06:00
Meir Michanie 23609b94b6 i18n(he): follow main's place names 2026-11-09 14:41:36 -06:00
Meir Michanie 3dd89af354 i18n(he): follow main's orbital site focus
- Translate the 12 new strings: site standby and Live-Signal pings,
  releasing and keeping the camera on a subject, riding a satellite,
  the focus and return chips, unnamed mapped sites.
- OFF-NADIR stays as printed via same-as-english.
2026-11-09 14:41:36 -06:00
Meir Michanie e35f38df8c i18n(he): follow main's satellite classes, orbital and bridge views
- Rebase on origin/main and translate the 130 new strings: event-age
  filter, satellite class groups (STATIONS/IMAGING/TELECOM/STARLINK/
  PROBES/DEBRIS) with CelesTrak SATCAT context, TomTom traffic limits,
  the ship bridge view (look/hold/radar/SOG/COG), the orbital view
  (swath, off-nadir, TLE, sub-satellite point, nadir/track-up) and the
  world-time play speeds.
- Instrument readouts keep the Latin codes (LOOK/STBD/PORT, NM, NORAD,
  EPOCH, TLE, OFF-NADIR, STARLINK, EYE, SWATH variants) via
  same-as-english.
- Prune 3 entries whose English main replaced.
2026-11-09 14:41:36 -06:00
Meir Michanie 584732c3ec 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 <html
  dir=rtl> 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.
2026-11-09 14:41:36 -06:00