feat(multitenancy): Sprach-Whitelist + Translator-Override + Forum-Quellenklasse

Vorbereitung fuer jp_demo-Organisation: drei separate Sprach-Settings statt
einer einzigen output_language.

org_settings.py:
- get_source_language_whitelist: Liste erlaubter Quellsprachen als JSON-Array
  (z.B. ["ja"] beschraenkt RSS/Telegram auf japanische Quellen).
- get_research_language: Sprache fuer WebSearch-Prompts (Default: output_language).
- get_translator_enabled: Pro-Org-Override des globalen TRANSLATOR_ENABLED-Flags.
- LANGUAGE_DISPLAY_NAMES um ja/zh/ko/ru/ar/fa/he/fr/es erweitert.

source_rules.py:
- get_feeds_with_metadata filtert nach source_language_whitelist, wenn gesetzt.
- Feeds ohne primary_language fallen bei aktiver Whitelist raus (gewollt).
- SELECT um media_type erweitert, damit es im Feed-Dict ankommt.

orchestrator.py:
- Laedt research_language, source_language_whitelist, translator_enabled aus
  den Org-Settings.
- Wenn Whitelist gesetzt: international_sources-Flag wird ignoriert.
- research_language_iso wird an researcher.search() weitergegeben.
- translate_articles bekommt enabled-Parameter aus Org-Setting.
- Geoparsing ueberspringt media_type='forum' Artikel.
- SELECT * FROM articles wird zu JOIN sources, damit media_type beim Reload
  am Article-Dict haengt.

researcher.py:
- search() akzeptiert research_language_iso. Asymmetrische Sprach-Auswahl
  (Recherche != Output) erzeugt eigene Prompt-Anweisung "primaer in Quell-
  sprache, englische Region-Outlets erlaubt".

translator.py:
- translate_articles akzeptiert enabled-Parameter. Ueberschreibt die globale
  TRANSLATOR_ENABLED-Konstante pro Aufruf.

factchecker.py:
- _format_articles_text filtert Artikel mit media_type='forum' aus. Anonyme
  Foren-Posts gelten nicht als Faktenbeleg.

rss_parser.py:
- _fetch_feed traegt media_type aus feed_config ins Article-Dict ein,
  damit downstream Pipeline-Schritte Foren-Quellen erkennen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
2026-05-22 00:12:56 +02:00
Ursprung 75038939b4
Commit 379d14518c
7 geänderte Dateien mit 226 neuen und 20 gelöschten Zeilen

Datei anzeigen

@@ -373,20 +373,27 @@ async def translate_articles(
output_lang: str = "de",
batch_size: int = DEFAULT_BATCH_SIZE,
usage_accumulator: UsageAccumulator | None = None,
enabled: bool | None = None,
) -> list[dict]:
"""Uebersetzt eine beliebige Anzahl Artikel in Batches.
Bringt die Batches durch Logik in `translate_articles_batch` und gibt
EINE flache Liste der Translations zurueck. Wenn ein Batch fehlschlaegt,
wird er uebersprungen (anderer Batches laufen weiter).
enabled: Pro-Aufruf-Override des globalen TRANSLATOR_ENABLED-Flags. Wenn None,
greift das Modul-Default (config.TRANSLATOR_ENABLED, abgeleitet aus .env).
Der Orchestrator setzt das aus dem Org-Setting 'translator_enabled', damit
jp_demo (Translator zwingend an) trotz global deaktiviertem Flag funktioniert.
"""
if not articles:
return []
if not TRANSLATOR_ENABLED:
is_enabled = TRANSLATOR_ENABLED if enabled is None else bool(enabled)
if not is_enabled:
logger.info(
"Translator deaktiviert (TRANSLATOR_ENABLED=false), %d Artikel uebersprungen",
len(articles),
"Translator deaktiviert (enabled=%s, global TRANSLATOR_ENABLED=%s), %d Artikel uebersprungen",
enabled, TRANSLATOR_ENABLED, len(articles),
)
return []