"""Language registry + prompt helpers for localized AI output. Two surfaces consume this module: - Per-user LLM call sites (portfolio analysis only at this stage) call ``respond_in_clause(user.lang)`` and append the result to their system prompt. - The settings dropdown + its PATCH endpoint consult ``ACTIVE_LANGUAGES`` to decide which options are selectable. The strategic-log and digest translation fan-outs also consult it to decide which languages to spend tokens on. Adding Spanish/French/German support later is a one-line constant change: extend ``ACTIVE_LANGUAGES`` to include the new code. No other code change is required — the rest of the system already treats them as first-class via ``LANGUAGES``. """ from __future__ import annotations # Display labels for every language the system knows about. ES/FR/DE # are kept here so labels still render in the dropdown (as disabled # options) without requiring code changes to enable them later. LANGUAGES: dict[str, str] = { "en": "English", "it": "Italian", "es": "Spanish", "fr": "French", "de": "German", } # Languages users can actually select. Settings POST validates against # this; the strategic-log + digest translation fan-outs only consider # these. ACTIVE_LANGUAGES: set[str] = {"en", "it"} def respond_in_clause(lang: str | None) -> str: """Suffix appended to per-user LLM system prompts. Returns an empty string for ``en`` (no nudge needed), an unknown code, or ``None``/empty input — those callers want the default English path. Otherwise returns ``"\\n\\nRespond in ."`` keyed off ``LANGUAGES``. """ if not lang or lang == "en" or lang not in LANGUAGES: return "" return f"\n\nRespond in {LANGUAGES[lang]}."