feat(i18n): Aktions-Buttons dynamisch + komplettes Neue-Lage/Bearbeiten-Modal

- _updateRefreshButton + _updateArchiveButton (app.js) nutzen T() statt
  Hardcode -- Aktualisieren/Laeuft/Wiederherstellen/Archivieren/Lesemodus.
- Modal-Title-Setter (Lage bearbeiten / Neue Lage anlegen) lokalisiert
  an drei Stellen (init / openEdit / closeModal).
- updateVisibilityHint und toggleTypeDefaults: dynamischer Text via T().
- HTML: ~31 data-i18n + data-i18n-attr im modal-new (Art der Lage,
  Optionen, Type-Hint, Quellen-Toggles, Sichtbarkeit, Aktualisierung,
  Intervall-Einheiten, Aufbewahrung, E-Mail-Toggles, Abbrechen).
- Cache-Buster app.js auf v=20260514a.
Dieser Commit ist enthalten in:
Claude Code
2026-05-13 22:05:31 +00:00
Ursprung 90f0731a86
Commit 3a68097b4f
4 geänderte Dateien mit 924 neuen und 840 gelöschten Zeilen

Datei-Diff unterdrückt, da er zu groß ist Diff laden

Datei anzeigen

@@ -17,6 +17,12 @@
"action.export": "Bericht exportieren", "action.export": "Bericht exportieren",
"action.archive": "Archivieren", "action.archive": "Archivieren",
"action.delete": "Löschen", "action.delete": "Löschen",
"action.refreshing": "Läuft...",
"action.restore": "Wiederherstellen",
"action.budget_exceeded": "Budget aufgebraucht",
"action.read_only": "Nur Lesezugriff",
"action.budget_exceeded_title": "Token-Budget aufgebraucht. Bitte Verwaltung kontaktieren.",
"action.read_only_title": "Lizenz erlaubt keinen Schreibzugriff",
"sidebar.empty": "Keine Lagen vorhanden", "sidebar.empty": "Keine Lagen vorhanden",
"header.logout": "Abmelden", "header.logout": "Abmelden",
"header.new_incident": "+ Neuer Fall", "header.new_incident": "+ Neuer Fall",
@@ -46,6 +52,37 @@
"modal.new_incident.visibility_public": "Öffentlich", "modal.new_incident.visibility_public": "Öffentlich",
"modal.new_incident.visibility_private": "Privat", "modal.new_incident.visibility_private": "Privat",
"modal.new_incident.submit": "Lage anlegen", "modal.new_incident.submit": "Lage anlegen",
"modal.new_incident.title2": "Neuen Fall anlegen",
"modal.new_incident.edit_title": "Lage bearbeiten",
"modal.placeholder.title": "z.B. Explosion in Madrid",
"modal.placeholder.description": "Weitere Details zum Vorfall (optional)",
"modal.field.type": "Art der Lage",
"modal.option.type_adhoc": "Live-Monitoring : Ereignis beobachten",
"modal.option.type_research": "Recherche : Thema analysieren",
"modal.hint.type_adhoc": "Durchsucht laufend hunderte Nachrichtenquellen nach neuen Meldungen. Empfohlen: Automatische Aktualisierung.",
"modal.hint.type_research": "Strukturierte Tiefenrecherche mit mehreren Durchläufen. Empfohlen: Manuell starten und bei Bedarf vertiefen.",
"modal.field.sources": "Quellen",
"modal.toggle.international": "Internationale Quellen einbeziehen",
"modal.toggle.telegram": "Telegram-Kanäle einbeziehen",
"modal.toggle.visibility_public_text": "Öffentlich : für alle Nutzer sichtbar",
"modal.toggle.visibility_private_text": "Privat : nur für dich sichtbar",
"modal.field.refresh": "Aktualisierung",
"modal.option.manual": "Manuell",
"modal.option.auto": "Automatisch",
"modal.field.interval": "Intervall",
"modal.unit.minutes": "Minuten",
"modal.unit.hours": "Stunden",
"modal.unit.days": "Tage",
"modal.unit.weeks": "Wochen",
"modal.field.start_time": "Erste Aktualisierung um",
"modal.field.retention": "Aufbewahrung (Tage)",
"modal.placeholder.retention": "0 = Unbegrenzt",
"modal.field.notifications": "E-Mail-Benachrichtigungen",
"modal.hint.notifications": "Per E-Mail benachrichtigen bei:",
"modal.notify.summary": "Neues Lagebild",
"modal.notify.new_articles": "Neue Artikel",
"modal.notify.status_change": "Statusänderung Faktencheck",
"aria.close": "Schließen",
"modal.sources.title": "Quellenverwaltung", "modal.sources.title": "Quellenverwaltung",
"modal.sources.approve_all_high": "Alle ≥ 0.85 genehmigen", "modal.sources.approve_all_high": "Alle ≥ 0.85 genehmigen",
"modal.export.title": "Bericht exportieren", "modal.export.title": "Bericht exportieren",

Datei anzeigen

@@ -17,6 +17,12 @@
"action.export": "Export report", "action.export": "Export report",
"action.archive": "Archive", "action.archive": "Archive",
"action.delete": "Delete", "action.delete": "Delete",
"action.refreshing": "Running...",
"action.restore": "Restore",
"action.budget_exceeded": "Budget exhausted",
"action.read_only": "Read-only",
"action.budget_exceeded_title": "Token budget exhausted. Please contact administration.",
"action.read_only_title": "License does not permit write access",
"sidebar.empty": "No situations yet", "sidebar.empty": "No situations yet",
"header.logout": "Sign out", "header.logout": "Sign out",
"header.new_incident": "+ New situation", "header.new_incident": "+ New situation",
@@ -46,6 +52,37 @@
"modal.new_incident.visibility_public": "Public", "modal.new_incident.visibility_public": "Public",
"modal.new_incident.visibility_private": "Private", "modal.new_incident.visibility_private": "Private",
"modal.new_incident.submit": "Create situation", "modal.new_incident.submit": "Create situation",
"modal.new_incident.title2": "Create new case",
"modal.new_incident.edit_title": "Edit situation",
"modal.placeholder.title": "e.g. Explosion in Madrid",
"modal.placeholder.description": "More details about the incident (optional)",
"modal.field.type": "Type of situation",
"modal.option.type_adhoc": "Live monitoring : track an event",
"modal.option.type_research": "Research : analyse a topic",
"modal.hint.type_adhoc": "Continuously searches hundreds of news sources for new articles. Recommended: automatic refresh.",
"modal.hint.type_research": "Structured deep research with multiple passes. Recommended: start manually and deepen when needed.",
"modal.field.sources": "Sources",
"modal.toggle.international": "Include international sources",
"modal.toggle.telegram": "Include Telegram channels",
"modal.toggle.visibility_public_text": "Public : visible to all users",
"modal.toggle.visibility_private_text": "Private : only visible to you",
"modal.field.refresh": "Refresh",
"modal.option.manual": "Manual",
"modal.option.auto": "Automatic",
"modal.field.interval": "Interval",
"modal.unit.minutes": "Minutes",
"modal.unit.hours": "Hours",
"modal.unit.days": "Days",
"modal.unit.weeks": "Weeks",
"modal.field.start_time": "First refresh at",
"modal.field.retention": "Retention (days)",
"modal.placeholder.retention": "0 = unlimited",
"modal.field.notifications": "Email notifications",
"modal.hint.notifications": "Notify me by email about:",
"modal.notify.summary": "New briefing",
"modal.notify.new_articles": "New articles",
"modal.notify.status_change": "Fact-check status change",
"aria.close": "Close",
"modal.sources.title": "Source management", "modal.sources.title": "Source management",
"modal.sources.approve_all_high": "Approve all ≥ 0.85", "modal.sources.approve_all_high": "Approve all ≥ 0.85",
"modal.export.title": "Export report", "modal.export.title": "Export report",

Datei anzeigen

@@ -2178,18 +2178,23 @@ async handleRefresh() {
_updateRefreshButton(disabled) { _updateRefreshButton(disabled) {
const btn = document.getElementById('refresh-btn'); const btn = document.getElementById('refresh-btn');
if (!btn) return; if (!btn) return;
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
// Hard-Stop: Lese-Modus (Budget aufgebraucht / Lizenz abgelaufen) -> immer disabled // Hard-Stop: Lese-Modus (Budget aufgebraucht / Lizenz abgelaufen) -> immer disabled
if (this.user && this.user.read_only) { if (this.user && this.user.read_only) {
btn.disabled = true; btn.disabled = true;
const reason = this.user.read_only_reason; const reason = this.user.read_only_reason;
btn.textContent = reason === 'budget_exceeded' ? 'Budget aufgebraucht' : 'Nur Lesezugriff'; btn.textContent = reason === 'budget_exceeded'
? _t('action.budget_exceeded', 'Budget aufgebraucht')
: _t('action.read_only', 'Nur Lesezugriff');
btn.title = reason === 'budget_exceeded' btn.title = reason === 'budget_exceeded'
? 'Token-Budget aufgebraucht. Bitte Verwaltung kontaktieren.' ? _t('action.budget_exceeded_title', 'Token-Budget aufgebraucht. Bitte Verwaltung kontaktieren.')
: 'Lizenz erlaubt keinen Schreibzugriff'; : _t('action.read_only_title', 'Lizenz erlaubt keinen Schreibzugriff');
return; return;
} }
btn.disabled = disabled; btn.disabled = disabled;
btn.textContent = disabled ? 'Läuft...' : 'Aktualisieren'; btn.textContent = disabled
? _t('action.refreshing', 'Läuft...')
: _t('action.refresh', 'Aktualisieren');
btn.title = ''; btn.title = '';
}, },
@@ -2236,8 +2241,8 @@ async handleRefresh() {
toggleRefreshInterval(); toggleRefreshInterval();
// Modal-Titel und Submit ändern // Modal-Titel und Submit ändern
{ const _e = document.getElementById('modal-new-title'); if (_e) _e.textContent = 'Lage bearbeiten'; } { const _e = document.getElementById('modal-new-title'); if (_e) _e.textContent = (typeof T === 'function') ? T('modal.new_incident.edit_title', 'Lage bearbeiten') : 'Lage bearbeiten'; }
{ const _e = document.getElementById('modal-new-submit'); if (_e) _e.textContent = 'Speichern'; } { const _e = document.getElementById('modal-new-submit'); if (_e) _e.textContent = (typeof T === 'function') ? T('common.save', 'Speichern') : 'Speichern'; }
// E-Mail-Subscription laden // E-Mail-Subscription laden
try { try {
@@ -2297,7 +2302,10 @@ async handleRefresh() {
_updateArchiveButton(status) { _updateArchiveButton(status) {
const btn = document.getElementById('archive-incident-btn'); const btn = document.getElementById('archive-incident-btn');
if (!btn) return; if (!btn) return;
btn.textContent = status === 'archived' ? 'Wiederherstellen' : 'Archivieren'; const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
btn.textContent = status === 'archived'
? _t('action.restore', 'Wiederherstellen')
: _t('action.archive', 'Archivieren');
}, },
// === WebSocket Handlers === // === WebSocket Handlers ===
@@ -3466,8 +3474,8 @@ function openModal(id) {
if (id === 'modal-new' && !App._editingIncidentId) { if (id === 'modal-new' && !App._editingIncidentId) {
// Create-Modus: Formular zurücksetzen // Create-Modus: Formular zurücksetzen
document.getElementById('new-incident-form').reset(); document.getElementById('new-incident-form').reset();
document.getElementById('modal-new-title').textContent = 'Neue Lage anlegen'; document.getElementById('modal-new-title').textContent = (typeof T === 'function') ? T('modal.new_incident.title2', 'Neue Lage anlegen') : 'Neue Lage anlegen';
document.getElementById('modal-new-submit').textContent = 'Lage anlegen'; document.getElementById('modal-new-submit').textContent = (typeof T === 'function') ? T('modal.new_incident.submit', 'Lage anlegen') : 'Lage anlegen';
{ const _b = document.getElementById('btn-enhance-description'); if (_b) _b.disabled = true; } { const _b = document.getElementById('btn-enhance-description'); if (_b) _b.disabled = true; }
{ const _t = document.getElementById("inc-description"); if (_t) { _t.style.height = ""; _autoResizeTextarea(_t); } } { const _t = document.getElementById("inc-description"); if (_t) { _t.style.height = ""; _autoResizeTextarea(_t); } }
// E-Mail-Checkboxen zuruecksetzen // E-Mail-Checkboxen zuruecksetzen
@@ -3500,8 +3508,8 @@ function closeModal(id) {
} }
if (id === 'modal-new') { if (id === 'modal-new') {
App._editingIncidentId = null; App._editingIncidentId = null;
document.getElementById('modal-new-title').textContent = 'Neue Lage anlegen'; document.getElementById('modal-new-title').textContent = (typeof T === 'function') ? T('modal.new_incident.title2', 'Neue Lage anlegen') : 'Neue Lage anlegen';
document.getElementById('modal-new-submit').textContent = 'Lage anlegen'; document.getElementById('modal-new-submit').textContent = (typeof T === 'function') ? T('modal.new_incident.submit', 'Lage anlegen') : 'Lage anlegen';
} }
} }
@@ -3675,9 +3683,10 @@ function updateVisibilityHint() {
const isPublic = document.getElementById('inc-visibility').checked; const isPublic = document.getElementById('inc-visibility').checked;
const text = document.getElementById('visibility-text'); const text = document.getElementById('visibility-text');
if (text) { if (text) {
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
text.textContent = isPublic text.textContent = isPublic
? 'Öffentlich — für alle Nutzer sichtbar' ? _t('modal.toggle.visibility_public_text', 'Öffentlich — für alle Nutzer sichtbar')
: 'Privat — nur für dich sichtbar'; : _t('modal.toggle.visibility_private_text', 'Privat — nur für dich sichtbar');
} }
} }
@@ -3696,15 +3705,16 @@ function toggleTypeDefaults(preserveMode = false) {
const hint = document.getElementById('type-hint'); const hint = document.getElementById('type-hint');
const refreshMode = document.getElementById('inc-refresh-mode'); const refreshMode = document.getElementById('inc-refresh-mode');
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
if (type === 'research') { if (type === 'research') {
hint.textContent = 'Recherchiert in Tiefe: Nachrichtenarchive, Parlamentsdokumente, Fachmedien, Expertenquellen. Empfohlen: Manuell starten und bei Bedarf vertiefen.'; hint.textContent = _t('modal.hint.type_research', 'Recherchiert in Tiefe: Nachrichtenarchive, Parlamentsdokumente, Fachmedien, Expertenquellen. Empfohlen: Manuell starten und bei Bedarf vertiefen.');
// Nur bei Typ-Wechsel/Neuanlage Modus zurückziehen, beim Edit bestehender Lagen DB-Wert respektieren // Nur bei Typ-Wechsel/Neuanlage Modus zurückziehen, beim Edit bestehender Lagen DB-Wert respektieren
if (!preserveMode) { if (!preserveMode) {
refreshMode.value = 'manual'; refreshMode.value = 'manual';
toggleRefreshInterval(); toggleRefreshInterval();
} }
} else { } else {
hint.textContent = 'Durchsucht laufend hunderte Nachrichtenquellen nach neuen Meldungen. Empfohlen: Automatische Aktualisierung.'; hint.textContent = _t('modal.hint.type_adhoc', 'Durchsucht laufend hunderte Nachrichtenquellen nach neuen Meldungen. Empfohlen: Automatische Aktualisierung.');
} }
// Beschreibungs-Tooltip je nach Typ wechseln // Beschreibungs-Tooltip je nach Typ wechseln