Promote develop → main (2026-05-21 17:10 UTC) #30
@@ -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",
|
"version": "2026-05-13T22:38Z",
|
||||||
"date": "2026-05-13",
|
"date": "2026-05-13",
|
||||||
|
|||||||
@@ -1174,18 +1174,28 @@ class AgentOrchestrator:
|
|||||||
new_count = 0
|
new_count = 0
|
||||||
new_articles_for_analysis = []
|
new_articles_for_analysis = []
|
||||||
for article in new_candidates:
|
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(
|
cursor = await db.execute(
|
||||||
"""INSERT INTO articles (incident_id, headline, headline_de, source,
|
"""INSERT INTO articles (incident_id, headline, headline_de, headline_en, source,
|
||||||
source_url, content_original, content_de, language, published_at, tenant_id)
|
source_url, content_original, content_de, content_en, language, published_at, tenant_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(
|
(
|
||||||
incident_id,
|
incident_id,
|
||||||
article.get("headline", ""),
|
article.get("headline", ""),
|
||||||
article.get("headline_de"),
|
article.get("headline_de"),
|
||||||
|
headline_en,
|
||||||
article.get("source", "Unbekannt"),
|
article.get("source", "Unbekannt"),
|
||||||
article.get("source_url"),
|
article.get("source_url"),
|
||||||
article.get("content_original"),
|
article.get("content_original"),
|
||||||
article.get("content_de"),
|
article.get("content_de"),
|
||||||
|
content_en,
|
||||||
article.get("language", "de"),
|
article.get("language", "de"),
|
||||||
article.get("published_at"),
|
article.get("published_at"),
|
||||||
tenant_id,
|
tenant_id,
|
||||||
|
|||||||
@@ -229,7 +229,13 @@ class RSSParser:
|
|||||||
"source_domain": feed_config.get("domain") or "",
|
"source_domain": feed_config.get("domain") or "",
|
||||||
"content_original": summary[:1000] if summary else None,
|
"content_original": summary[:1000] if summary else None,
|
||||||
"content_de": summary[:1000] if summary and self._is_german(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,
|
"published_at": published,
|
||||||
"relevance_score": relevance_score,
|
"relevance_score": relevance_score,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class TelegramParser:
|
|||||||
search_words = [w.lower() for w in search_words]
|
search_words = [w.lower() for w in search_words]
|
||||||
else:
|
else:
|
||||||
search_words = fallback_words or []
|
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)
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ class TelegramParser:
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
async def _fetch_channel(self, client, channel_id: str, search_words: list[str],
|
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."""
|
"""Letzte N Nachrichten eines Kanals abrufen und nach Keywords filtern."""
|
||||||
articles = []
|
articles = []
|
||||||
try:
|
try:
|
||||||
@@ -217,7 +217,10 @@ class TelegramParser:
|
|||||||
"source_url": source_url,
|
"source_url": source_url,
|
||||||
"content_original": content[:2000],
|
"content_original": content[:2000],
|
||||||
"content_de": content[:2000] if self._is_german(content) else None,
|
"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,
|
"published_at": published,
|
||||||
"relevance_score": relevance_score,
|
"relevance_score": relevance_score,
|
||||||
})
|
})
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren