diff --git a/src/agents/orchestrator.py b/src/agents/orchestrator.py index e1191af..d251211 100644 --- a/src/agents/orchestrator.py +++ b/src/agents/orchestrator.py @@ -1174,18 +1174,28 @@ class AgentOrchestrator: new_count = 0 new_articles_for_analysis = [] for article in new_candidates: + # headline_en / content_en: zuerst die vollwertige Übersetzung + # vom Translator (wenn TRANSLATOR_ENABLED), sonst die für den + # Topic-Filter angefertigte Mini-Übersetzung wiederverwenden. + # Ohne diesen Fallback würden fremdsprachige Artikel zwar + # gefiltert, aber ohne englische Headline in der DB landen und + # später im Frontend bzw. im Summary-LLM unlesbar bleiben. + headline_en = article.get("headline_en") or article.get("headline_en_for_topic") + content_en = article.get("content_en") or article.get("content_en_for_topic") cursor = await db.execute( - """INSERT INTO articles (incident_id, headline, headline_de, source, - source_url, content_original, content_de, language, published_at, tenant_id) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", + """INSERT INTO articles (incident_id, headline, headline_de, headline_en, source, + source_url, content_original, content_de, content_en, language, published_at, tenant_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", ( incident_id, article.get("headline", ""), article.get("headline_de"), + headline_en, article.get("source", "Unbekannt"), article.get("source_url"), article.get("content_original"), article.get("content_de"), + content_en, article.get("language", "de"), article.get("published_at"), tenant_id, diff --git a/src/feeds/rss_parser.py b/src/feeds/rss_parser.py index 1e0f234..7e3d1d6 100644 --- a/src/feeds/rss_parser.py +++ b/src/feeds/rss_parser.py @@ -229,7 +229,13 @@ class RSSParser: "source_domain": feed_config.get("domain") or "", "content_original": summary[:1000] if summary else None, "content_de": summary[:1000] if summary and self._is_german(summary) else None, - "language": "de" if self._is_german(title) else "en", + # Sprache primär aus der Quell-Konfiguration übernehmen + # (z.B. "ja" für Asahi Shimbun, "ru" für TASS). Nur wenn + # die Quelle kein primary_language gesetzt hat, auf die + # alte de/en-Heuristik zurückfallen. Sonst landen + # CJK/kyrillische Headlines fälschlich als language="en" + # und verlieren Pre-Topic-Übersetzung + Translator-Pfad. + "language": feed_config.get("primary_language") or ("de" if self._is_german(title) else "en"), "published_at": published, "relevance_score": relevance_score, }) diff --git a/src/feeds/telegram_parser.py b/src/feeds/telegram_parser.py index e657766..377aa99 100644 --- a/src/feeds/telegram_parser.py +++ b/src/feeds/telegram_parser.py @@ -104,7 +104,7 @@ class TelegramParser: search_words = [w.lower() for w in search_words] else: search_words = fallback_words or [] - tasks.append(self._fetch_channel(client, channel_id, search_words)) + tasks.append(self._fetch_channel(client, channel_id, search_words, channel_lang=channel_lang)) results = await asyncio.gather(*tasks, return_exceptions=True) @@ -150,7 +150,7 @@ class TelegramParser: return [] async def _fetch_channel(self, client, channel_id: str, search_words: list[str], - limit: int = 50) -> list[dict]: + limit: int = 50, channel_lang: str | None = None) -> list[dict]: """Letzte N Nachrichten eines Kanals abrufen und nach Keywords filtern.""" articles = [] try: @@ -217,7 +217,10 @@ class TelegramParser: "source_url": source_url, "content_original": content[:2000], "content_de": content[:2000] if self._is_german(content) else None, - "language": "de" if self._is_german(content) else "en", + # Sprache primär aus der Kanal-Konfiguration übernehmen + # (z.B. "ru" für russische Kanäle). Sonst Fallback auf die + # de/en-Heuristik. Symmetrisch zur RSS-Pfad-Logik. + "language": channel_lang or ("de" if self._is_german(content) else "en"), "published_at": published, "relevance_score": relevance_score, })