From a41c8ae529de8eeb08316e9949af71e82e24d557 Mon Sep 17 00:00:00 2001 From: claude-dev Date: Thu, 21 May 2026 17:05:47 +0000 Subject: [PATCH 1/2] =?UTF-8?q?feat(articles):=20headline=5Fen=20persistie?= =?UTF-8?q?ren=20+=20Sprache=20aus=20Quell-Konfig=20=C3=BCbernehmen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zwei Lücken beim Befund Lage 96 (Verfassungsänderung Japan): die japanische Asahi-Shimbun-Quelle wurde durch das Sprach-aware Keyword-Matching (#27) und Pre-Topic-Translate (#28) erstmals durchgereicht, landete aber mit language='en' und ohne englische Headline in der DB. Damit ist sie im Frontend nur als Kanji-Headline zu lesen und das Summary-LLM kann den Treffer nicht aussagekräftig referenzieren. 1. INSERT INTO articles erweitert um headline_en und content_en. Werte stammen primär vom Translator (headline_en, falls TRANSLATOR_ENABLED den Pfad einmal in Englisch befüllt), Fallback auf die für den Topic-Filter angefertigte Mini-Übersetzung (headline_en_for_topic / content_en_for_topic). So liegt die englische Variante dauerhaft in der DB statt nur während des Refresh-Laufs im Speicher. 2. RSS- und Telegram-Parser setzen 'language' nun primär aus der Quell-/ Kanal-Konfiguration (primary_language). Vorher war es hart 'de' wenn die Headline deutsch wirkte, sonst 'en' - mit dem Resultat, dass ein Kanji-Titel als language='en' landete. Mit dem Fix bekommen Asahi & Co. korrekt language='ja', russische Telegram-Kanäle 'ru' etc. - src/agents/orchestrator.py: INSERT erweitert, Kommentar zur Fallback-Logik - src/feeds/rss_parser.py: language aus feed_config.primary_language - src/feeds/telegram_parser.py: channel_lang durch _fetch_channel reichen Co-Authored-By: Claude Opus 4.7 (1M context) --- src/agents/orchestrator.py | 16 +++++++++++++--- src/feeds/rss_parser.py | 8 +++++++- src/feeds/telegram_parser.py | 9 ++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) 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, }) -- 2.49.1 From 3196424ec9ac31871f228645e39fbbd2f1359509 Mon Sep 17 00:00:00 2001 From: IntelSight_Admin Date: Thu, 21 May 2026 19:10:01 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Release-Notes:=20Sprachunterst=C3=BCtzung?= =?UTF-8?q?=20f=C3=BCr=20Artikel-=C3=9Cberschriften=20verbessert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RELEASES.json | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASES.json b/RELEASES.json index d723dc8..cbe2df9 100644 --- a/RELEASES.json +++ b/RELEASES.json @@ -1,4 +1,13 @@ [ + { + "version": "2026-05-21T17:10Z", + "date": "2026-05-21", + "title": "Sprachunterstützung für Artikel-Überschriften verbessert", + "items": [ + "Englische Überschriften werden jetzt korrekt gespeichert und angezeigt.", + "Die Sprache eines Artikels wird automatisch aus der jeweiligen Quelle übernommen." + ] + }, { "version": "2026-05-13T22:38Z", "date": "2026-05-13", -- 2.49.1