log: serve localized content from the HTMX endpoints
The /log page renders its content asynchronously by hitting
/api/log/latest?as=html and /api/log/by-date/{day}?as=html via HTMX.
Both endpoints returned StrategicLog.content (English) verbatim,
ignoring the new StrategicLogTranslation table entirely. The
_resolve_log_content helper I added to pages.py earlier was wired
into the page handlers themselves but never reached for HTMX swaps,
so Italian users only ever saw English content despite their
lang='it' preference being persisted and translations being
generated correctly.
Fix: add a _localized_content helper in api.py that looks up the
matching translation row for the requesting principal's lang.
_log_partial_payload gains a content_override arg; both HTMX
endpoints (log_latest, log_by_date) compute the override and pass
it through. JSON paths (?as= other than html) remain English to
avoid changing the public API contract.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
eb31d09782
commit
7acd191051
1 changed files with 35 additions and 6 deletions
|
|
@ -39,6 +39,7 @@ from app.models import (
|
|||
JobRun,
|
||||
Quote,
|
||||
StrategicLog,
|
||||
StrategicLogTranslation,
|
||||
User,
|
||||
)
|
||||
from app.schemas import (
|
||||
|
|
@ -297,11 +298,15 @@ async def news_list(
|
|||
# --- Strategic log -----------------------------------------------------------
|
||||
|
||||
|
||||
def _log_partial_payload(row: StrategicLog | None) -> dict | None:
|
||||
def _log_partial_payload(
|
||||
row: StrategicLog | None,
|
||||
content_override: str | None = None,
|
||||
) -> dict | None:
|
||||
if row is None:
|
||||
return None
|
||||
content = content_override if content_override is not None else row.content
|
||||
return {
|
||||
"content_html": _md_to_html(row.content),
|
||||
"content_html": _md_to_html(content),
|
||||
"generated_at": row.generated_at,
|
||||
"model": row.model,
|
||||
"tone": row.tone,
|
||||
|
|
@ -313,6 +318,28 @@ def _log_partial_payload(row: StrategicLog | None) -> dict | None:
|
|||
}
|
||||
|
||||
|
||||
async def _localized_content(
|
||||
session: AsyncSession,
|
||||
row: StrategicLog | None,
|
||||
principal: CurrentUser | None,
|
||||
) -> str | None:
|
||||
"""Return the translated content_md for ``row`` when the principal has
|
||||
a non-English lang preference and a matching translation row exists.
|
||||
Returns None to signal 'use row.content as-is' (the default English
|
||||
path)."""
|
||||
if row is None or principal is None or principal.user is None:
|
||||
return None
|
||||
lang = (principal.user.lang or "en")
|
||||
if lang == "en":
|
||||
return None
|
||||
t = (await session.execute(
|
||||
select(StrategicLogTranslation)
|
||||
.where(StrategicLogTranslation.log_id == row.id)
|
||||
.where(StrategicLogTranslation.lang == lang)
|
||||
)).scalar_one_or_none()
|
||||
return t.content_md if t is not None else None
|
||||
|
||||
|
||||
def _resolve_tone_param(tone: str | None) -> str:
|
||||
"""Normalise a query-param tone to one of the two valid values.
|
||||
PRO is silently mapped to INTERMEDIATE (see openrouter.PROMPT_VERSION 6)."""
|
||||
|
|
@ -368,10 +395,11 @@ async def log_latest(
|
|||
row = (await session.execute(fallback)).scalar_one_or_none()
|
||||
|
||||
if as_ == "html":
|
||||
content_override = await _localized_content(session, row, principal)
|
||||
return templates.TemplateResponse(
|
||||
request, "partials/log.html",
|
||||
{"log": _log_partial_payload(row), "tone": wanted_tone,
|
||||
"paid": not free_only},
|
||||
{"log": _log_partial_payload(row, content_override=content_override),
|
||||
"tone": wanted_tone, "paid": not free_only},
|
||||
)
|
||||
|
||||
if row is None:
|
||||
|
|
@ -422,10 +450,11 @@ async def log_by_date(
|
|||
row = (await session.execute(fallback)).scalar_one_or_none()
|
||||
|
||||
if as_ == "html":
|
||||
content_override = await _localized_content(session, row, principal)
|
||||
return templates.TemplateResponse(
|
||||
request, "partials/log.html",
|
||||
{"log": _log_partial_payload(row), "tone": wanted_tone,
|
||||
"paid": not free_only},
|
||||
{"log": _log_partial_payload(row, content_override=content_override),
|
||||
"tone": wanted_tone, "paid": not free_only},
|
||||
)
|
||||
if row is None:
|
||||
raise HTTPException(status_code=404, detail="No log on this date")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue