analyze: send the live toggle lang from the frontend, log resolution
The /api/analyze flow previously read principal.user.lang from the DB on every request and ignored anything the client might send. That races the language toggle's PATCH: a user can flip the toggle and click Generate/Regenerate before the PATCH /api/settings/language hits the DB, so the analysis is sent with the OLD persisted lang while the toggle visually reads as the new one. From the user's POV the analysis comes back in the wrong language. Frontend portfolio.js now reads the live #lang-toggle data-lang attribute (the same source the UI itself uses) and includes it in the /api/analyze body. The dataset attribute is updated optimistically by cassandraSetLang() before the PATCH fires, so it always reflects what the user is looking at. Backend universe.py prefers payload["lang"] when present and falls back to user.lang otherwise — older clients (scripts, direct curl) that don't send anything still get the DB-stored preference. The resolution path is logged so we can confirm in prod which lang actually drove a given request. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
13dd3a8330
commit
21835afebe
2 changed files with 19 additions and 2 deletions
|
|
@ -362,10 +362,19 @@ async def analyze_portfolio(
|
|||
except Exception:
|
||||
raise HTTPException(status_code=400, detail="malformed JSON body")
|
||||
|
||||
user_lang = (
|
||||
# Resolve lang. The frontend sends the live toggle state in
|
||||
# payload["lang"]; that's what the user is *looking at* right now
|
||||
# and is the most up-to-date value. user.lang from the DB is the
|
||||
# persisted preference and is used as a fallback when the frontend
|
||||
# didn't send anything (older clients, scripts, direct curl).
|
||||
db_lang = (
|
||||
principal.user.lang if (principal.user and principal.user.lang) else "en"
|
||||
)
|
||||
payload["lang"] = user_lang
|
||||
incoming = (payload.get("lang") or "").strip().lower()
|
||||
payload["lang"] = incoming or db_lang
|
||||
log.info("analyze.lang_resolved",
|
||||
payload_lang=incoming or None, db_lang=db_lang,
|
||||
final=payload["lang"])
|
||||
|
||||
try:
|
||||
req = portfolio_analysis.parse_request(payload)
|
||||
|
|
|
|||
|
|
@ -469,6 +469,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
// The language toggle's data-lang attribute is the user's LIVE
|
||||
// pick — newer than user.lang in the DB if the user toggled and
|
||||
// hit Generate/Regenerate before the toggle-PATCH committed.
|
||||
// Backend prefers this value if provided (see universe.py).
|
||||
const langPill = document.getElementById('lang-toggle');
|
||||
const userLang = (langPill && langPill.dataset.lang) || 'en';
|
||||
|
||||
try {
|
||||
const r = await fetch('/api/analyze', {
|
||||
method: 'POST',
|
||||
|
|
@ -478,6 +485,7 @@
|
|||
positions: pie.positions,
|
||||
prices: prices,
|
||||
base_currency: pie.base_currency || 'GBP',
|
||||
lang: userLang,
|
||||
}),
|
||||
});
|
||||
const data = await r.json();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue