Skip to content

Latest commit

 

History

History
47 lines (42 loc) · 3.06 KB

File metadata and controls

47 lines (42 loc) · 3.06 KB

Internationalization (i18n)

Reference detail moved out of CLAUDE.md to keep that file a terse map. This is the full text for this subsystem.

Internationalization (i18n)

English / French, no build step; js/i18n.js (classic script, loaded early) is the whole mechanism.

  • Two string sources. UI strings live in the message catalogue inside js/i18n.js (one object per language). Data strings (region/pathway/circuit names, descriptions, neurotransmitters, the group/kind/sign/receptor labels) are authored as {en,fr} objects in generate_data.py, but the emitted data is English-only: at serialization time every {en,fr} dict is collapsed to its English string and the English -> French pairs are deduplicated into a single side table, public/data/translations.fr.json. js/data.js fetches that table (only in French) and pick(field) looks each English string up in it.
  • Generator side. Anatomy is authored in English; a single FR table (English -> French) is the French source, and _t("English") wraps any display string into {en, fr}. A string with no FR entry makes build_records raise listing every missing one, so it can't ship half-translated. Per-hemisphere names are composed by _side_name (Right/Left, and gender/number-agreed French tuned by an optional fr_gender of m/f/mp/fp), not stored; each record also carries a hemisphere-stripped base_name. The externalize pass (externalize() + TRANSLATIONS in data_generators/i18n.py, driven by write_artifacts) does the collapse: it walks each record + meta, replaces every {en,fr} dict with its English string, and accumulates TRANSLATIONS[en] = fr. Identical en == fr pairs are skipped (the viewer falls back to English), and one English string mapping to two different French values is a hard error (the FR model assumes en -> fr is a function). This is a pure serialization step: records are still built bilingual.
  • Language pick. detectLang(): ?lang=en|fr (persisted to localStorage) > saved choice > browser locale fr* > English. window.__I18N__ exposes lang, t(key, vars) (UI, {token} interpolation, falls back to English then the key), pick(field) (in French, translate a plain English data string via the side table, falling back to English; a legacy {en,fr} object still collapses defensively), setDataTranslations(obj) (install the side table, called by js/data.js before any localize runs), setLang.
  • Static markup in index.html carries data-i18n (textContent), data-i18n-html (innerHTML), data-i18n-attr="attr:key,...", filled at DOMContentLoaded; dynamic UI calls t() directly. setLang saves the choice and reloads (data is resolved at load), and writes <html lang>. The #lang-switch (EN/FR) is pinned at the top of the panel body.

Important

Any new user-visible string goes in both language tables in js/i18n.js (UI) or as an {en, fr} object in generate_data.py (data). Source citations + URLs are intentionally not translated.