fix(i18n): preserve explicit saved English on first-visit bootstrap
Closes #7622. Round-3 follow-up to the maintainer review at https://github.com/nesquena/hermes-webui/pull/7730#issuecomment-5786493511. The round-2 'primary === "en"' heuristic overrode users who had genuinely picked English: when the server-stored 'language' was 'en' the resolver treated it as the schema default and skipped it, falling through to localStorage / the browser hint. This round addresses all three maintainer findings: 1. BRICK — server stops injecting the schema default. Drop '"language": "en"' from api/config.py:_SETTINGS_DEFAULTS so a fresh install returns settings['language'] == None. Existing settings.json files that already carry 'language: "en"' still report 'en' (the field is just absent from the defaults dict; the per-file load path is unchanged). 'language' is added back to _SETTINGS_ALLOWED_KEYS so the Settings modal save path still validates and persists explicit user picks (the BCP-47 regex is unchanged). 2. CORE — browser-language detection is now in one guarded helper. static/i18n.js exposes _detectBrowserLanguageHint(), used by loadLocale(), boot.js, and panels.js. A throwing navigator accessor in some embedded webviews can no longer abort boot or settings hydration before the model/provider/plugin/extension sections are populated. 3. CI RED — restore the test shape. boot.js and panels.js call resolvePreferredLocale(s.language, localStorage.getItem('hermes-lang'), _detectBrowserLanguageHint()) inline so tests/test_language_precedence.py::test_boot_and_settings_panel_use_shared_locale_precedence matches the expected argument list. The TestComposedResolverPrecedence tests in tests/test_issue7622_initial_locale_from_browser.py are re-pinned to the round-3 contract (server primary is None for a fresh install; an explicit 'en' primary from a user-saved file beats a non-English browser hint). Tests (22/22 i18n-related pass; 833/833 settings+i18n+locale pass; ruff forward-gate --diff origin/master is clean): - test_language_precedence.py: 8/8 (added guarded-helper, server-default, composed-resolver, and cross-file first-visit tests) - test_issue7622_initial_locale_from_browser.py: 14/14 (re-pinned to round-3 contract; added explicit-saved-English regression test) - test_login_locale.py and friends: unchanged behaviour for the save/load round trip
This commit is contained in:
1 parent
b471e7d1b8
commit
8d0cdaefbe
6 files changed
+343
-139
No files matched your search
+11
-17
@@ -3431,24 +3431,18 @@ window._mirrorSpeechSettingsFromServer=_mirrorSpeechSettingsFromServer;
|
||||
localStorage.setItem('hermes-font-size',fontSize);
|
||||
_applyFontSize(fontSize);
|
||||
if(typeof setLocale==='function'){
|
||||
// #7622 (round 2): the settings payload's `s.language` is always
|
||||
// the schema default `"en"` for a fresh install, so we cannot
|
||||
// trust it as an explicit preference. Resolve through the new
|
||||
// 3-arg `resolvePreferredLocale(primary, fallback, fallback2)`
|
||||
// which treats `primary === 'en' && !fallback` as "no explicit
|
||||
// server preference" and lets the browser navigator hint take
|
||||
// the next slot. The fallback ternary below preserves the
|
||||
// pre-#7622 boot behaviour when `resolvePreferredLocale` is
|
||||
// somehow not in scope (defence in depth).
|
||||
const _stored=localStorage.getItem('hermes-lang');
|
||||
const _browserHint=(typeof navigator!=='undefined')
|
||||
? (Array.isArray(navigator.languages)&&navigator.languages.length
|
||||
? navigator.languages[0]
|
||||
: (typeof navigator.language==='string'?navigator.language:null))
|
||||
: null;
|
||||
// #7622 (round 3): the settings payload's `s.language` is
|
||||
// absent (None) for a fresh install, so an explicit non-empty
|
||||
// value is the user's genuine saved choice. The browser
|
||||
// navigator hint is now read via the guarded
|
||||
// `_detectBrowserLanguageHint()` helper (round-3 finding 2) so
|
||||
// a throwing `navigator` accessor in some embedded webviews
|
||||
// can no longer abort this branch and reset loaded preferences.
|
||||
// The fallback ternary preserves the pre-#7622 boot behaviour
|
||||
// when neither helper is in scope (defence in depth).
|
||||
const _lang=typeof resolvePreferredLocale==='function'
|
||||
? resolvePreferredLocale(s.language, _stored, _browserHint)
|
||||
: (s.language || _stored || _browserHint || 'en');
|
||||
? resolvePreferredLocale(s.language, localStorage.getItem('hermes-lang'), _detectBrowserLanguageHint())
|
||||
: (s.language || localStorage.getItem('hermes-lang') || 'en');
|
||||
setLocale(_lang);
|
||||
if(typeof applyLocaleToDOM==='function')applyLocaleToDOM();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user