i18n: localize indicator summaries (per-group + aggregate read)

This commit is contained in:
Giorgio Gilestro 2026-05-27 20:19:47 +02:00
parent 7acd191051
commit 664757ea8a
4 changed files with 173 additions and 12 deletions

View file

@ -172,6 +172,37 @@ class IndicatorSummary(Base):
__table_args__ = (Index("ix_indsumm_group_generated", "group_name", "generated_at"),)
class IndicatorSummaryTranslation(Base):
"""Cached translation of a single IndicatorSummary row.
Same pattern as StrategicLogTranslation: one row per
(summary_id, lang). Populated by indicator_summary_job after the
English row is committed. The dashboard / indicators endpoints
swap in the matching translation when a user with a non-en
lang preference loads them, falling back silently to the English
source when no row exists yet.
"""
__tablename__ = "indicator_summary_translations"
id: Mapped[int] = mapped_column(_PK, primary_key=True, autoincrement=True)
summary_id: Mapped[int] = mapped_column(
BigInteger().with_variant(Integer(), "sqlite"),
ForeignKey("indicator_summaries.id", ondelete="CASCADE"),
nullable=False,
)
lang: Mapped[str] = mapped_column(String(8), nullable=False)
content_md: Mapped[str] = mapped_column(Text, nullable=False)
generated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, default=utcnow,
)
llm_model: Mapped[str | None] = mapped_column(String(64))
llm_cost_usd: Mapped[float | None] = mapped_column(Float)
__table_args__ = (
UniqueConstraint("summary_id", "lang", name="uq_ist_summary_lang"),
)
class AICall(Base):
"""Cost ledger for OpenRouter calls. Feeds the monthly cap check."""
__tablename__ = "ai_calls"