i18n: Aufraeumen und Doku-Update (Phase 5)

- lagebild.js: tote initLangToggle() und switchContent() entfernt;
  initTranslations()-Aufruf aus init() raus (translations.js gibt es
  nicht mehr). Kein neues Verhalten, nur Aufraeumen.
- CLAUDE.md aktualisiert: en/situations/-Struktur, Slug-Mapping,
  Daten-Freigabe-Konzept, Kontaktformular i18n-Hinweis,
  CHANGE_LOG erweitert.

Backend (contact-form.py) wurde live ausgerollt und ist nicht im
Repo (liegt unter /opt/v2-Docker/aegis-website/), Backup unter
contact-form.py.bak.<timestamp>.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
2026-05-06 23:30:24 +02:00
Ursprung 645fb33898
Commit f874d1dee0
2 geänderte Dateien mit 30 neuen und 71 gelöschten Zeilen

Datei anzeigen

@@ -50,6 +50,10 @@ STRUCTURE:
- index.html: Hauptseite (EN) - index.html: Hauptseite (EN)
- legal-notice.html: Impressum (EN, Hinweis "German version prevails") - legal-notice.html: Impressum (EN, Hinweis "German version prevails")
- privacy.html: Datenschutz (EN, Hinweis "German version prevails") - privacy.html: Datenschutz (EN, Hinweis "German version prevails")
situations:
- iran-conflict/index.html: Lagebild Iran (EN-Mirror, teilt /lagen/iran-konflikt/data)
- cyber-attacks/index.html: Lagebild Cyberangriffe (EN-Mirror, teilt /lagen/cyberangriffe/data)
- deepfakes/index.html: Recherche Deepfakes (EN-Mirror, teilt /lagen/deepfakes/data)
assets: assets:
fonts: [Inter, Bebas Neue] fonts: [Inter, Bebas Neue]
@@ -98,12 +102,23 @@ PAGES:
product: product:
- AccountForger Video-Demo - AccountForger Video-Demo
lagen: lagen:
url_struktur: /lagen/{thema}/ url_struktur:
de: /lagen/{thema}/
en: /en/situations/{slug}/ (slug ist die englische URL-Variante)
slug_mapping:
iran-konflikt: iran-conflict
cyberangriffe: cyber-attacks
deepfakes: deepfakes
daten_freigabe: |
EN-Mirror-Seiten setzen window.LAGEBILD_DATA_BASE auf den DE-Pfad,
damit beide Sprachvarianten die gleichen JSON-Daten laden. Das
lagebild.js liest curLang() aus <html lang> und schaltet UI-Strings
automatisch um (lang.de / lang.en Dictionary).
redirect: /lagebild/ -> 301 -> /lagen/iran-konflikt/ redirect: /lagebild/ -> 301 -> /lagen/iran-konflikt/
aktiv: aktiv:
- iran-konflikt: Live-Lagebild Irankonflikt (ehemals /lagebild/) - iran-konflikt / iran-conflict: Live-Lagebild Irankonflikt
geplant: - cyberangriffe / cyber-attacks: Live-Lagebild Cyberangriffe
- (2 weitere Lagen in Vorbereitung) - deepfakes / deepfakes: Recherche-Briefing Deepfakes
vorschau: vorschau:
url: /vorschau/ url: /vorschau/
zweck: Produktseite AegisSight Monitor (ersetzt spaeter die Hauptseite) zweck: Produktseite AegisSight Monitor (ersetzt spaeter die Hauptseite)
@@ -122,7 +137,14 @@ DEVELOPMENT:
sprachumschalter: css/lang-switcher.css sprachumschalter: css/lang-switcher.css
pendant_urls: in jeder Seite hardcoded (funktioniert ohne JS) pendant_urls: in jeder Seite hardcoded (funktioniert ohne JS)
cookie_banner: cookie-consent.js liest <html lang> selbststaendig cookie_banner: cookie-consent.js liest <html lang> selbststaendig
open: contact-form.py ist noch DE-only (Validierungs- und Mailtexte) lagen: lagebild.js liest <html lang> via curLang(); Daten-Pfad ueber
window.LAGEBILD_DATA_BASE pro EN-Mirror-Seite
kontaktformular: |
Frontend (js/app.js) sendet lang im POST-Body, zeigt Sende- und
Fehler-Texte in der jeweiligen Sprache. Backend
(/opt/v2-Docker/aegis-website/contact-form.py, NICHT im Repo)
liest lang und antwortet entsprechend; E-Mail an info@aegis-sight.de
bleibt deutsch, mit Hinweis "[EN]" im Betreff bei EN-Anfragen.
large_files: "assets/videos/ (~300MB)" large_files: "assets/videos/ (~300MB)"
design: mobile-first responsive design: mobile-first responsive
@@ -152,6 +174,9 @@ CHANGE_LOG:
- "i18n: Sprachumschalter DE/EN, neue Seiten unter /en/" - "i18n: Sprachumschalter DE/EN, neue Seiten unter /en/"
- "Aufraeumen: js/translations.js, impressum-en.html, datenschutz-en.html entfernt" - "Aufraeumen: js/translations.js, impressum-en.html, datenschutz-en.html entfernt"
- "data-translate Attribute aus Lagen-Seiten entfernt" - "data-translate Attribute aus Lagen-Seiten entfernt"
- "EN-Lagen-Seiten unter /en/situations/{slug}/, teilen DE-Datenfiles"
- "lagebild.js: curLang() liest <html lang>, dataBase()-Helper neu, tote initLangToggle/switchContent entfernt"
- "Kontaktformular zweisprachig (Frontend + Backend)"
Last-Updated: 2026-05-06 Last-Updated: 2026-05-06

Datei anzeigen

@@ -110,9 +110,6 @@ var Lagebild = {
}, },
async init() { async init() {
if (typeof initTranslations === 'function') {
try { initTranslations(); } catch(e) {}
}
this.initScrollProgress(); this.initScrollProgress();
this.initParticles(); this.initParticles();
try { try {
@@ -134,7 +131,6 @@ var Lagebild = {
}; };
this.render(); this.render();
this.initTabs(); this.initTabs();
this.initLangToggle();
this.initScrollReveal(); this.initScrollReveal();
this.initFloatingCta(); this.initFloatingCta();
this.initLiveFeed(); this.initLiveFeed();
@@ -1214,68 +1210,6 @@ var Lagebild = {
} }
}, },
initLangToggle: function() {
var btn = document.querySelector('.lang-toggle');
if (!btn) return;
var self = this;
btn.addEventListener('click', function(e) {
e.preventDefault();
var cur = (typeof getCurrentLanguage === 'function') ? getCurrentLanguage() : 'de';
var newLang = cur === 'de' ? 'en' : 'de';
if (typeof switchLanguage === 'function') switchLanguage(newLang);
self.switchContent(newLang);
});
},
switchContent: async function(lang) {
var base = this.dataBase();
var jsonFile = base + (lang === 'en' ? 'data/current_en.json' : 'data/current.json');
try {
var resp = await fetch(jsonFile + '?t=' + Date.now());
if (!resp.ok && lang === 'en') {
resp = await fetch(base + 'data/current.json?t=' + Date.now());
}
if (!resp.ok) throw new Error('HTTP ' + resp.status);
this.data = await resp.json();
this.allSnapshots = {};
this.currentView = {
summary: this.data.current_lagebild.summary_markdown,
sources_json: this.data.current_lagebild.sources_json,
updated_at: this.data.current_lagebild.updated_at || this.data.generated_at,
articles: this.data.articles,
fact_checks: this.data.fact_checks,
article_count: this.data.incident.article_count,
fact_check_count: this.data.incident.factcheck_count
};
this.render();
// Update hero title for language
var heroH1 = document.getElementById('hero-title');
if (heroH1) {
var isResearch = this.data.incident && this.data.incident.type === 'research';
heroH1.textContent = isResearch ? this.t('heroResearch') : this.t('hero');
}
// Update tab labels
var tabBtns = document.querySelectorAll('.tab-btn');
var isResearch = this.data.incident && this.data.incident.type === 'research';
for (var i = 0; i < tabBtns.length; i++) {
var tab = tabBtns[i].getAttribute('data-tab');
if (tab === 'lagebild') tabBtns[i].childNodes[0].textContent = isResearch ? this.t('tabBriefingResearch') : this.t('tabBriefing');
else if (tab === 'ueberblick') tabBtns[i].childNodes[0].textContent = isResearch ? this.t('tabUeberblickResearch') : this.t('tabUeberblick');
else if (tab === 'karte') tabBtns[i].childNodes[0].textContent = this.t('tabMap');
else if (tab === 'faktenchecks') tabBtns[i].childNodes[0].textContent = this.t('tabFactchecks') + ' ';
else if (tab === 'quellen') tabBtns[i].childNodes[0].textContent = this.t('tabSources') + ' ';
}
// Update Ueberblick H2 title
var ueberblickH2 = document.getElementById('ueberblick-title');
if (ueberblickH2) ueberblickH2.textContent = isResearch ? this.t('tabUeberblickResearch') : this.t('tabUeberblick');
// Update data source note
var dsNote = document.querySelector('.data-source-note');
if (dsNote) dsNote.textContent = this.t('dataSource');
} catch(e) {
console.error('Language switch failed:', e);
}
},
/* ===== FLOATING CTA ===== */ /* ===== FLOATING CTA ===== */
initFloatingCta: function() { initFloatingCta: function() {
var cta = document.createElement('div'); var cta = document.createElement('div');