diff --git a/app.py b/app.py index 159274c..5eaf683 100644 --- a/app.py +++ b/app.py @@ -4169,10 +4169,77 @@ def _lang_dropdown_html(lang: str) -> str: }); }); } +})(); + // UI text translation + var lang = localStorage.getItem("bsn-lang") || "de"; + if (lang !== "de") { + var uiText = + '_ui_text_json(lang)' + ; + function translateUI() { + // Translate text content of elements with specific text + var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); + var node; + while (node = walker.nextNode()) { + var txt = node.textContent.trim(); + if (uiText[txt]) { + node.textContent = node.textContent.replace(txt, uiText[txt]); + } + } + // Translate input placeholders + document.querySelectorAll("[placeholder]").forEach(function(el) { + var ph = el.getAttribute("placeholder"); + if (uiText[ph]) el.setAttribute("placeholder", uiText[ph]); + }); + // Translate button text + document.querySelectorAll("button").forEach(function(el) { + if (el.textContent.trim() && uiText[el.textContent.trim()]) { + el.textContent = uiText[el.textContent.trim()]; + } + }); + } + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", translateUI); + } else { + translateUI(); + } + } })(); """ +# ═══════════════════════════════════════════ +# UI-Text-Übersetzungen (via JS + Fallback) +# ═══════════════════════════════════════════ +UI_TEXT = { + "Willkommen in der BSN Community!": {"en": "Welcome to the BSN Community!", "fr": "Bienvenue dans la communauté BSN !", "es": "¡Bienvenido a la comunidad BSN!"}, + "Nicht mehr anzeigen": {"en": "Don't show again", "fr": "Ne plus afficher", "es": "No mostrar más"}, + "Alles klar!": {"en": "Got it!", "fr": "Compris !", "es": "¡Entendido!"}, + "Powered by": {"en": "Powered by", "fr": "Propulsé par", "es": "Desarrollado por"}, + "Zurück zur Übersicht": {"en": "Back to overview", "fr": "Retour à l'aperçu", "es": "Volver a la vista general"}, + "Aufrufe": {"en": "views", "fr": "vues", "es": "vistas"}, + "Kommentare": {"en": "Comments", "fr": "Commentaires", "es": "Comentarios"}, + "Dein Name (optional)": {"en": "Your name (optional)", "fr": "Votre nom (facultatif)", "es": "Tu nombre (opcional)"}, + "Schreib einen Kommentar...": {"en": "Write a comment...", "fr": "Écrire un commentaire...", "es": "Escribe un comentario..."}, + "Damit wir dich bei Antworten benachrichtigen können (E-Mail oder Nummer erforderlich):": {"en": "So we can notify you of replies (email or phone required):", "fr": "Pour vous notifier des réponses (email ou numéro requis) :", "es": "Para notificarte de las respuestas (correo o número requerido):"}, + "E-Mail-Adresse": {"en": "Email address", "fr": "Adresse e-mail", "es": "Dirección de correo"}, + "Handynummer (für WhatsApp-Benachrichtigung)": {"en": "Phone number (for WhatsApp notification)", "fr": "Numéro (notification WhatsApp)", "es": "Número (notificación WhatsApp)"}, + "Kommentar senden": {"en": "Send comment", "fr": "Envoyer", "es": "Enviar comentario"}, + "Beitrags-ID:": {"en": "Post ID:", "fr": "ID publication :", "es": "ID publicación:"}, +} + +def __(text: str, lang: str) -> str: + """UI-String übersetzen. Fallback: Originaltext.""" + if lang == "de" or not text: + return text + entry = UI_TEXT.get(text) + return entry.get(lang, text) if entry else text + +def _ui_text_json(lang: str) -> str: + """Erzeugt JSON-Objekt mit allen Übersetzungen für target_lang.""" + result = {} + for de_text, trans in UI_TEXT.items(): + result[de_text] = trans.get(lang, de_text) + return json.dumps(result, ensure_ascii=False) + @app.route('/api/chat', methods=['POST']) def api_chat(): """Chat agent with read-only access to published submissions.""" @@ -4849,7 +4916,7 @@ def public_detail(sub_id: int):
- ← Zurück zur Übersicht + ← {__("Zurück zur Übersicht", lang)}
{"".join([f'
{row["halle"]}
' if row["halle"] else '', f'
🚫 AUSVERKAUFT{(" · " + row["spiel_titel"] + "") if row["spiel_titel"] else ""}
' if row["category"] == "ausverkauft" else ''])}
@@ -4860,31 +4927,31 @@ def public_detail(sub_id: int):
{media_html}
{"".join([f'
{content}
' if content else ''])}
- {row['views'] or 0} Aufrufe + {row['views'] or 0} {__("Aufrufe", lang)}
-

💬 Kommentare ({len(comment_rows)})

+

💬 {__("Kommentare", lang)} ({len(comment_rows)})

{comments_html}
↩ Antwort an × abbrechen
- - -
Damit wir dich bei Antworten benachrichtigen können (E-Mail oder Nummer erforderlich):
- - - + + +
{__("Damit wir dich bei Antworten benachrichtigen können (E-Mail oder Nummer erforderlich):", lang)}
+ + +
- Beitrags-ID: #{sub_id} \u2014 Bei Fragen oder Löschwunsch bitte diese ID angeben. + {__("Beitrags-ID:", lang)} #{sub_id} \u2014 Bei Fragen oder Löschwunsch bitte diese ID angeben.
""" +# ═══════════════════════════════════════════ +# UI-Text-Übersetzungen (via JS + Fallback) +# ═══════════════════════════════════════════ +UI_TEXT = { + "Willkommen in der BSN Community!": {"en": "Welcome to the BSN Community!", "fr": "Bienvenue dans la communauté BSN !", "es": "¡Bienvenido a la comunidad BSN!"}, + "Nicht mehr anzeigen": {"en": "Don't show again", "fr": "Ne plus afficher", "es": "No mostrar más"}, + "Alles klar!": {"en": "Got it!", "fr": "Compris !", "es": "¡Entendido!"}, + "Powered by": {"en": "Powered by", "fr": "Propulsé par", "es": "Desarrollado por"}, + "Zurück zur Übersicht": {"en": "Back to overview", "fr": "Retour à l'aperçu", "es": "Volver a la vista general"}, + "Aufrufe": {"en": "views", "fr": "vues", "es": "vistas"}, + "Kommentare": {"en": "Comments", "fr": "Commentaires", "es": "Comentarios"}, + "Dein Name (optional)": {"en": "Your name (optional)", "fr": "Votre nom (facultatif)", "es": "Tu nombre (opcional)"}, + "Schreib einen Kommentar...": {"en": "Write a comment...", "fr": "Écrire un commentaire...", "es": "Escribe un comentario..."}, + "Damit wir dich bei Antworten benachrichtigen können (E-Mail oder Nummer erforderlich):": {"en": "So we can notify you of replies (email or phone required):", "fr": "Pour vous notifier des réponses (email ou numéro requis) :", "es": "Para notificarte de las respuestas (correo o número requerido):"}, + "E-Mail-Adresse": {"en": "Email address", "fr": "Adresse e-mail", "es": "Dirección de correo"}, + "Handynummer (für WhatsApp-Benachrichtigung)": {"en": "Phone number (for WhatsApp notification)", "fr": "Numéro (notification WhatsApp)", "es": "Número (notificación WhatsApp)"}, + "Kommentar senden": {"en": "Send comment", "fr": "Envoyer", "es": "Enviar comentario"}, + "Beitrags-ID:": {"en": "Post ID:", "fr": "ID publication :", "es": "ID publicación:"}, +} + +def __(text: str, lang: str) -> str: + """UI-String übersetzen. Fallback: Originaltext.""" + if lang == "de" or not text: + return text + entry = UI_TEXT.get(text) + return entry.get(lang, text) if entry else text + +def _ui_text_json(lang: str) -> str: + """Erzeugt JSON-Objekt mit allen Übersetzungen für target_lang.""" + result = {} + for de_text, trans in UI_TEXT.items(): + result[de_text] = trans.get(lang, de_text) + return json.dumps(result, ensure_ascii=False) + @app.route('/api/chat', methods=['POST']) def api_chat(): """Chat agent with read-only access to published submissions.""" @@ -4849,7 +4916,7 @@ def public_detail(sub_id: int):
- ← Zurück zur Übersicht + ← {__("Zurück zur Übersicht", lang)}
{"".join([f'
{row["halle"]}
' if row["halle"] else '', f'
🚫 AUSVERKAUFT{(" · " + row["spiel_titel"] + "") if row["spiel_titel"] else ""}
' if row["category"] == "ausverkauft" else ''])}
@@ -4860,31 +4927,31 @@ def public_detail(sub_id: int):
{media_html}
{"".join([f'
{content}
' if content else ''])}
- {row['views'] or 0} Aufrufe + {row['views'] or 0} {__("Aufrufe", lang)}
-

💬 Kommentare ({len(comment_rows)})

+

💬 {__("Kommentare", lang)} ({len(comment_rows)})

{comments_html}
↩ Antwort an × abbrechen
- - -
Damit wir dich bei Antworten benachrichtigen können (E-Mail oder Nummer erforderlich):
- - - + + +
{__("Damit wir dich bei Antworten benachrichtigen können (E-Mail oder Nummer erforderlich):", lang)}
+ + +
- Beitrags-ID: #{sub_id} \u2014 Bei Fragen oder Löschwunsch bitte diese ID angeben. + {__("Beitrags-ID:", lang)} #{sub_id} \u2014 Bei Fragen oder Löschwunsch bitte diese ID angeben.