From 7d0692150ca957042392ae89e44464fd9b7e33ab Mon Sep 17 00:00:00 2001 From: JUSN Date: Fri, 18 Sep 2026 15:56:49 +0200 Subject: [PATCH] =?UTF-8?q?Website:=2028=20Sprachen=20statt=207=20?= =?UTF-8?q?=E2=80=94=20per=20Generator=20statt=20Handarbeit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tools/sprachseiten/ enthaelt jetzt vorlage.html + texte.js + build.js. 'node tools/sprachseiten/build.js' erzeugt alle 27 Sprachseiten und pflegt hreflang + Sprachwaehler auch in der handgemachten index.html nach. Warum ein Generator: 28 Seiten von Hand zu pflegen heisst, jede kuenftige Aenderung 28-mal zu machen. So ist es eine Aenderung an einer Stelle. Neue Sprachen u. a. Rumaenisch, Kurdisch (Kurmanci), Bulgarisch, Kroatisch, Serbisch, Bosnisch, Albanisch, Italienisch, Griechisch, Vietnamesisch, Hindi, Urdu, Paschtu, Tigrinya, Somali, Chinesisch. Sprachleiste ist jetzt ein Aufklappmenue — 28 Links nebeneinander waeren unbenutzbar, besonders auf dem Handy. Google findet die Seiten weiter ueber hreflang (28 + x-default, auf jeder Seite identisch) und die Sitemap (38 URLs). Ausserdem: Hinweis in beiden Kauf-Boxen, warum sich die E-Mail-Angabe lohnt (Zugangs-Link -> Guthaben auf jedem Geraet nutzbar). Co-Authored-By: Claude Opus 5 --- tools/sprachseiten/build.js | 129 ++++++ tools/sprachseiten/texte.js | 720 ++++++++++++++++++++++++++++++++ tools/sprachseiten/vorlage.html | 193 +++++++++ webseite/ar.html | 276 +++++------- webseite/bg.html | 258 ++++++++++++ webseite/bs.html | 258 ++++++++++++ webseite/demo.html | 7 + webseite/el.html | 258 ++++++++++++ webseite/en.html | 268 +++++------- webseite/es.html | 258 ++++++++++++ webseite/fa.html | 258 ++++++++++++ webseite/fr.html | 258 ++++++++++++ webseite/hi.html | 258 ++++++++++++ webseite/hr.html | 258 ++++++++++++ webseite/hu.html | 258 ++++++++++++ webseite/index.html | 75 +++- webseite/it.html | 258 ++++++++++++ webseite/ku.html | 258 ++++++++++++ webseite/pl.html | 274 +++++------- webseite/ps.html | 258 ++++++++++++ webseite/pt.html | 258 ++++++++++++ webseite/ro.html | 258 ++++++++++++ webseite/ru.html | 285 +++++-------- webseite/sitemap.xml | 35 +- webseite/so.html | 258 ++++++++++++ webseite/sq.html | 258 ++++++++++++ webseite/sr.html | 258 ++++++++++++ webseite/ti.html | 258 ++++++++++++ webseite/tr.html | 253 +++++------ webseite/uk.html | 284 +++++-------- webseite/ur.html | 258 ++++++++++++ webseite/vi.html | 258 ++++++++++++ webseite/zh.html | 258 ++++++++++++ 33 files changed, 7216 insertions(+), 1001 deletions(-) create mode 100644 tools/sprachseiten/build.js create mode 100644 tools/sprachseiten/texte.js create mode 100644 tools/sprachseiten/vorlage.html create mode 100644 webseite/bg.html create mode 100644 webseite/bs.html create mode 100644 webseite/el.html create mode 100644 webseite/es.html create mode 100644 webseite/fa.html create mode 100644 webseite/fr.html create mode 100644 webseite/hi.html create mode 100644 webseite/hr.html create mode 100644 webseite/hu.html create mode 100644 webseite/it.html create mode 100644 webseite/ku.html create mode 100644 webseite/ps.html create mode 100644 webseite/pt.html create mode 100644 webseite/ro.html create mode 100644 webseite/so.html create mode 100644 webseite/sq.html create mode 100644 webseite/sr.html create mode 100644 webseite/ti.html create mode 100644 webseite/ur.html create mode 100644 webseite/vi.html create mode 100644 webseite/zh.html diff --git a/tools/sprachseiten/build.js b/tools/sprachseiten/build.js new file mode 100644 index 0000000..39b93be --- /dev/null +++ b/tools/sprachseiten/build.js @@ -0,0 +1,129 @@ +/** + * Erzeugt alle Sprach-Landingpages aus EINER Vorlage + texte.js. + * + * node tools/sprachseiten/build.js + * + * Warum ein Generator: Bei 28 Sprachen müsste sonst jede Änderung (neuer + * Abschnitt, neuer Link, neues Brevo-Formular) 28-mal von Hand gemacht werden. + * So ist es eine Änderung an einer Stelle. + * + * Deutsch (index.html) wird NICHT erzeugt — die Startseite ist handgemacht + * und deutlich umfangreicher. Sie bekommt nur hreflang + Sprachwähler gepflegt + * (siehe hreflangBlock() / waehlerBlock(), die auch index.html aktualisieren). + */ +const fs = require('fs'); +const path = require('path'); + +const { SPRACHEN, TEXTE } = require('./texte.js'); +const AUS = path.join(__dirname, '..', '..', 'webseite'); +const BASIS = 'https://behoerdenklar.de'; +const BREVO = 'https://86550585.sibforms.com/serve/MUIFAAvOQCpFg148k-xD2Ze2PDVKKaFEIaLECCCMe9fGKd_uIurPljyn_IhTrkR0EkM_pQp_8VBzcHZ6N9sKDX5GBZi9elYKN6isXGPUUxcAgO37OKhTFZyMlJiC9ikRmPI8Q2tU2GvqP6esJ5ReGfv1htZV_OfXRIgW59P6pkeUsYKxqdXA7nWOaWxNTYz4MzzoGg7czJMJ2fxuEg=='; + +/** Alle Sprachen inkl. Deutsch, in der Reihenfolge aus texte.js. */ +const ALLE = [{ code: 'de', eigenname: 'Deutsch', datei: 'index.html', pfad: '/' }].concat( + SPRACHEN.map((s) => ({ ...s, datei: `${s.code}.html`, pfad: `/${s.code}` })) +); + +/** hreflang-Satz — identisch auf JEDER Seite, sonst wertet Google ihn ab. */ +function hreflangBlock() { + return ( + ALLE.map((s) => ` `).join('\n') + + `\n ` + ); +} + +/** + * Sprachwähler als Auswahlliste. Bei 28 Sprachen wäre eine Linkleiste + * unbenutzbar — ein Aufklappmenü bleibt auch auf dem Handy bedienbar. + * Google findet die Seiten trotzdem: über hreflang und die Sitemap. + */ +function waehlerBlock(aktiv, label) { + const optionen = ALLE.map( + (s) => + ` ` + ).join('\n'); + return ` `; +} + +const WAEHLER_CSS = ` + .sprachwahl { + font-family: inherit; font-size: 15px; color: var(--tinte); + background: #fff; border: 1.5px solid var(--tinte); padding: 6px 10px; + max-width: 220px; cursor: pointer; + }`; + +function seite(s) { + const t = TEXTE[s.code]; + if (!t) throw new Error('Keine Texte für ' + s.code); + const rtl = s.rtl ? ' dir="rtl"' : ''; + const vorlage = fs.readFileSync(path.join(__dirname, 'vorlage.html'), 'utf8'); + + return vorlage + .replace(/\{\{LANG\}\}/g, s.code) + .replace(/\{\{DIR\}\}/g, rtl) + .replace(/\{\{LOCALE\}\}/g, t.locale || s.code) + .replace(/\{\{TITEL\}\}/g, t.titel) + .replace(/\{\{BESCHREIBUNG\}\}/g, t.beschreibung) + .replace(/\{\{OG_TITEL\}\}/g, t.ogTitel) + .replace(/\{\{OG_BESCHREIBUNG\}\}/g, t.ogBeschreibung) + .replace(/\{\{URL\}\}/g, `${BASIS}/${s.code}`) + .replace(/\{\{HREFLANG\}\}/g, hreflangBlock()) + .replace(/\{\{WAEHLER_CSS\}\}/g, WAEHLER_CSS) + .replace(/\{\{WAEHLER\}\}/g, waehlerBlock(s.code, t.navLabel)) + .replace(/\{\{H1_A\}\}/g, t.h1a) + .replace(/\{\{H1_B\}\}/g, t.h1b) + .replace(/\{\{INTRO\}\}/g, t.intro) + .replace(/\{\{CTA_HERO\}\}/g, t.ctaHero) + .replace(/\{\{STEMPEL\}\}/g, t.stempel) + .replace(/\{\{S1_TITEL\}\}/g, t.s1Titel) + .replace(/\{\{VORHER_LABEL\}\}/g, t.vorherLabel) + .replace(/\{\{PFEIL\}\}/g, t.pfeil) + .replace(/\{\{NACHHER_LABEL\}\}/g, t.nachherLabel) + .replace(/\{\{NACHHER_TEXT\}\}/g, t.nachherText) + .replace(/\{\{HINWEIS\}\}/g, t.hinweis) + .replace(/\{\{S2_TITEL\}\}/g, t.s2Titel) + .replace(/\{\{SCHRITT1_T\}\}/g, t.schritt1T).replace(/\{\{SCHRITT1_B\}\}/g, t.schritt1B) + .replace(/\{\{SCHRITT2_T\}\}/g, t.schritt2T).replace(/\{\{SCHRITT2_B\}\}/g, t.schritt2B) + .replace(/\{\{SCHRITT3_T\}\}/g, t.schritt3T).replace(/\{\{SCHRITT3_B\}\}/g, t.schritt3B) + .replace(/\{\{S3_TITEL\}\}/g, t.s3Titel) + .replace(/\{\{FORMULAR_KOPF\}\}/g, t.formularKopf) + .replace(/\{\{FORM_H3\}\}/g, t.formH3) + .replace(/\{\{FORM_TEXT\}\}/g, t.formText) + .replace(/\{\{BONUS\}\}/g, t.bonus) + .replace(/\{\{BREVO\}\}/g, BREVO) + .replace(/\{\{EMAIL_PLATZHALTER\}\}/g, t.emailPlatzhalter) + .replace(/\{\{CTA_FORM\}\}/g, t.ctaForm) + .replace(/\{\{KLEIN\}\}/g, t.klein) + .replace(/\{\{DATENSCHUTZ\}\}/g, t.datenschutz) + .replace(/\{\{IMPRESSUM\}\}/g, t.impressum) + .replace(/\{\{FUSS_FRAGE\}\}/g, t.fussFrage); +} + +let n = 0; +for (const s of SPRACHEN) { + fs.writeFileSync(path.join(AUS, `${s.code}.html`), seite(s), 'utf8'); + n++; +} + +// index.html (Deutsch, handgemacht) mitpflegen: hreflang + Sprachwähler +const idxPfad = path.join(AUS, 'index.html'); +let idx = fs.readFileSync(idxPfad, 'utf8'); +idx = idx.replace( + /( ]*>)/, + hreflangBlock() +); +idx = idx.replace( + /