i18n: localize indicator summaries (per-group + aggregate read)
This commit is contained in:
parent
7acd191051
commit
664757ea8a
4 changed files with 173 additions and 12 deletions
|
|
@ -36,6 +36,7 @@ from app.models import (
|
|||
AICall,
|
||||
Headline,
|
||||
IndicatorSummary,
|
||||
IndicatorSummaryTranslation,
|
||||
JobRun,
|
||||
Quote,
|
||||
StrategicLog,
|
||||
|
|
@ -138,6 +139,7 @@ async def indicators(
|
|||
as_: str | None = Query(default=None, alias="as"),
|
||||
tone: str | None = Query(default=None),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
principal: CurrentUser | None = Depends(maybe_current_user),
|
||||
):
|
||||
sub = (
|
||||
select(Quote.symbol, func.max(Quote.fetched_at).label("mx"))
|
||||
|
|
@ -205,6 +207,7 @@ async def indicators(
|
|||
if as_of_d and (today - as_of_d).days > threshold:
|
||||
stale_symbols.add(r.symbol)
|
||||
|
||||
await _apply_localized_summary(session, summary, principal)
|
||||
return templates.TemplateResponse(
|
||||
request, "partials/indicators.html",
|
||||
{"quotes": rows, "has_anchor": has_anchor,
|
||||
|
|
@ -340,6 +343,30 @@ async def _localized_content(
|
|||
return t.content_md if t is not None else None
|
||||
|
||||
|
||||
async def _apply_localized_summary(
|
||||
session: AsyncSession,
|
||||
row: IndicatorSummary | None,
|
||||
principal: CurrentUser | None,
|
||||
) -> None:
|
||||
"""If ``row`` has a matching translation for ``principal.user.lang``,
|
||||
overwrite the in-memory ``content`` attribute so the template renders
|
||||
the localized version. No DB write happens — the mutation lives only
|
||||
for the lifetime of this GET request.
|
||||
"""
|
||||
if row is None or principal is None or principal.user is None:
|
||||
return
|
||||
lang = (principal.user.lang or "en")
|
||||
if lang == "en":
|
||||
return
|
||||
t = (await session.execute(
|
||||
select(IndicatorSummaryTranslation)
|
||||
.where(IndicatorSummaryTranslation.summary_id == row.id)
|
||||
.where(IndicatorSummaryTranslation.lang == lang)
|
||||
)).scalar_one_or_none()
|
||||
if t is not None:
|
||||
row.content = t.content_md
|
||||
|
||||
|
||||
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)."""
|
||||
|
|
@ -552,6 +579,7 @@ async def aggregate_summary(
|
|||
session: AsyncSession = Depends(get_session),
|
||||
as_: str | None = Query(default=None, alias="as"),
|
||||
tone: str | None = Query(default=None),
|
||||
principal: CurrentUser | None = Depends(maybe_current_user),
|
||||
):
|
||||
wanted_tone = _resolve_tone_param(tone)
|
||||
row = (await session.execute(
|
||||
|
|
@ -573,6 +601,7 @@ async def aggregate_summary(
|
|||
statuses = all_statuses()
|
||||
|
||||
if as_ == "html":
|
||||
await _apply_localized_summary(session, row, principal)
|
||||
return templates.TemplateResponse(
|
||||
request, "partials/dashboard_header.html",
|
||||
{"summary": row, "markets": statuses, "tone": wanted_tone},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue