3.3 KiB
Language support
LearnHarness supports English and Russian. Settings → General contains independent interface and speech recognition language selectors. The microphone also has a speech language selector. Each offers System default, English, and Русский.
System default uses the preferred browser language (the operating system's
preferred language in the desktop app); Russian locales select Russian and other
locales select English. Explicit choices persist in settings.json as
general.language and general.sttLanguage. Removing a field restores automatic
selection. Changing one preference preserves the other general settings.
The interface changes immediately, including accessibility labels and the desktop menu. New AI teaching, questions, plans, practice, graph descriptions, research, figures, and demos use the interface language. Existing conversations and imported source material retain their authored text. A session retains the language of its latest foreground turn so automatic follow-ups can use the same language after a restart; an explicit app language preference takes precedence.
Speech recognition uses Deepgram Nova-3 with an explicit language=en or
language=ru. A recording captures the selected language when it starts and keeps
that language through reconnections. The selector is disabled while recording;
changes elsewhere take effect on the next recording. Audio capture, deferred
transcript insertion, stopping, and cancellation retain their existing behavior.
Maintaining translations
The pure localization functions live in src/core/i18n.ts and are exported through
the core barrel. English and Russian catalogs are in src/core/locales/en.json and
ru.json. English source phrases are message keys. Add every new app-owned message
to both catalogs, use named interpolation parameters, and use plural entries with
Intl.PluralRules for counts. Russian entries may use one, few, many, and
other forms. Keep code, provider/model names, identifiers, and user-authored text
out of translation lookups.
React components use useI18n() from components/i18n.tsx. The root provider gets
server-resolved initial settings and locale to preserve hydration. General-setting
writes share a serialized read-modify-write path; other surfaces use the existing
settings-saved signal. Server and agent code receive an explicit language rather
than depending on a mutable global translation state.
Some existing protocol errors arrive preformatted in English. Localization can recognize cataloged application templates at the display boundary, preserving the canonical error values used for classification and any third-party diagnostics. Raw technical instructions, code, and user overrides remain editable source data.
The desktop shell has its own small catalog in electron/language.cjs, packaged
with the shell. Its narrow lh:language channel accepts only en and ru from a
trusted application window. Russian prose uses Noto Sans because Source Sans 3
has no Cyrillic subset. Explicit font choices continue to take precedence.
tests/i18n.test.tsx covers preference validation, automatic selection, independent
STT requests, catalog parity and interpolation, Russian plural forms, SSR locale
isolation, translated dialogs and exports, agent instructions, and native labels.