Bilingual UI - msupino/NavigationApp GitHub Wiki
๐ฎ๐ฑ ืขืืจืืช
NavAid ships a fully translated Hebrew (RTL) and English UI. Switch via the language picker in the toolbar (๐).

The same app in Hebrew (RTL):

The choice (on every page load) is short:
-
?lang=heor?lang=enin the address, else - Hebrew โ NavAid is flown in Israeli airspace and read in Hebrew by most of the people who open it.
That is the whole rule. A language is not remembered. A plain navaid.supino.org is
Hebrew every time, not only the first, and English is a choice the address carries โ which the
toolbar picker, the safety notice's selector and every link shared from inside the app all set.
What this replaced was a stored navaid.lang: it made a plain address mean different things on
different devices, so "open navaid.supino.org" became an unanswerable question about what a
pilot would actually see โ including for whoever was talking them through it over the radio. A
key left behind by an older version is ignored, not honoured.
The bootstrap sets <html lang> and <html dir> before the stylesheet, and writes ?lang=โฆ
into the address so the language on screen is the language in the link you copy.
Two other places carry the same decision:
- The safety notice has its own language control, because it is the first thing on screen and the toolbar's picker is behind it. What it picks is the app's language, not the notice's. See Safety notice.
-
About, Privacy and Terms resolve language exactly the same way โ
?lang, else Hebrew โ and store nothing either. They used to default to English and write that fallback, so opening Terms before the planner flipped the whole app to English.
-
docs/i18n/he/strings.jsโ Hebrew overrides. -
docs/i18n/en/strings.jsโ empty (window.S = {}); English is the default locale defined inline indocs/app/core.js.
The locale file loads first; core.js then merges the English defaults beneath it (window.S = Object.assign({ โฆdefaultsโฆ }, window.S || {})), so a key like tbAddWp resolves to the locale value when present, else English. The HTML uses data-i18n="key" / data-i18n-title="key" / data-i18n-placeholder="key" attributes. A small init pass walks the DOM and fills text / title / placeholder from S.
Adding a new translated string requires:
- A new entry in
docs/app/core.js(the English default) and, if translated, an override indocs/i18n/he/strings.js. - A
data-i18n="newKey"on the element. - Do not bump cache values merely for deployment invalidation.
docs/index.htmlkeeps literal?v=src; app/i18n data URLs retain their existing source values. Deploy rewrites both forms to the branch short SHA.
-
<html dir="rtl">is set when Hebrew is active. - The toolbar swaps its handle / collapse icons via CSS logical properties (
inline-start/inline-end). - The Hebrew page uses an entry-point HTML at
docs/he/index.htmlthat redirects to/?lang=heto preserve a stable, indexable Hebrew URL.
The CVFR graph has 172 layer members; the 170 active reporting points carry
name, English en, and Hebrew he fields and appear in the overlay. The map
label uses the locale's language; search matches both languages and renders
primary / alt.
Airfields carry ICAO name, Hebrew he, and English en fields. Search matches all three, and the marker label shows ICAO plus the localized name.
The charts viewer adds the following i18n keys (English defaults in docs/app/core.js, Hebrew overrides in docs/i18n/he/strings.js):
| Key | EN | HE |
|---|---|---|
plates |
Charts | ืืคืืืช |
plateCategoryApproach |
Approach | ืืืฉื |
plateCategorySid |
SID | SID |
plateCategoryStar |
STAR | STAR |
plateCategoryGround |
Ground | ืงืจืงืข |
plateCategoryVfr |
VFR / Airport | VFR / ืฉืื ืชืขืืคื |
plateCategoryOther |
Other | ืืืจ |
plateOpen |
Open | ืคืชื |
plateDownload |
Download | ืืืจื |
plateOpenTab |
Open in new tab | ืคืชื ืืืฉืื ืืช ืืืฉื |
plateClose |
Close | ืกืืืจ |
platesNone |
No charts available โ see official AIP | ืืื ืืคืืืช โ ืจืื AIP ืืจืฉืื |
plateLoadError |
Failed to load chart. | ืืขืื ืช ืืืคืืช ื ืืฉืื. |
plateAttribution |
Charts ยฉ Israel CAAI / Ministry of Transport โ published in the AIP. | ืืคืืช ยฉ ืจืฉืืช ืืชืขืืคื ืืืืจืืืช / ืืฉืจื ืืชืืืืจื โ ืืคืืจืกื ื-AIP. |
- The toolbar buttons and titles are user-visible and reviewed; pick the shortest natural phrasing โ the toolbar is narrow.
- The inspector strings are also visible and frequently used.
- "Mag var" is a pilot term โ in Hebrew use "ื ืืืื ืืื ืืืช"; do not invent.
- "CVFR" stays as is in both languages (it's an internationally-recognised acronym).
- Brand labels
GitHubandWikistay in English in the Hebrew UI.
- The page exposes
hreflanghe,en, andx-defaultalternates so search engines route users to the right language. - The page title is rewritten to a localized version on language switch; meta description / OG tags follow shortly (see SEO roadmap).