Filipe, 22.09.2026: "ersetze die zentrale durch, Die IrrenAnstalt.
genau so geschrieben bitte. und alles was treff heißt oder wo treff
steht soll durch Rudel ersetzt werden bitte."
Die Schreibweise "IrrenAnstalt" mit grossem A in der Mitte ist so
gewollt. Das steht als Hinweis daneben, damit sie beim naechsten Mal
niemand "korrigiert".
WAS UMBENANNT WURDE: alles, was jemand LIEST -- Kachelnamen,
Ueberschriften, Markenzeilen, Saetze, Meldungen, Aufgabenvorlagen.
116 Zeilen in 42 Dateien.
WAS BLEIBT: Adressen (treff-regeln.html), Bezeichner (TREFF_ROLLEN),
Datenbankwerte (bereich = 'treff'), Abfrageteile (b=treff). Eine
Adresse umzubenennen bricht jedes Lesezeichen, und ein Datenbankwert
umzuschreiben waere eine Umstellung ohne Gegenwert. Dieselbe
Entscheidung wie heute frueh bei Dogi-Media, wo material.html auch
material.html geblieben ist.
DREI GRAMMATIKFEHLER IM EIGENEN ENTWURF, alle vor dem Ausliefern
gefunden -- ein blindes Ersetzen reicht hier nicht:
1. "der Treff" ist maennlich, "das Rudel" saechlich. Ohne Tabelle
waere ueberall "Der Rudel" gestanden. (Und "Treffer" waere zu
"Rudeler" geworden, "Treffen" zu "Rudelen" -- deshalb greift die
Regel nur bei Wortgrenze und nie vor einem Kleinbuchstaben.)
2. BINDESTRICH-ZUSAMMENSETZUNGEN. In "der Treff-Chat" gehoert der
Artikel zu "Chat", nicht zu "Treff". Der erste Durchlauf machte
daraus "das Rudel-Chat", "das Rudel-Kacheln" und "ein Rudel-Raum".
Jetzt greift die Artikelregel nur, wenn das Wort allein steht.
3. GESCHUETZTE LEERZEICHEN. In den Markenzeilen steht
`Der Treff`, damit die zwei Woerter nicht umbrechen. Das
Muster hat daran vorbeigegriffen: "Der Rudel", auf fuenf
Seiten. Jetzt wird das Trennzeichen mitgefasst und unveraendert
wieder eingesetzt.
Gefunden wurden alle drei, weil jede einzelne der 116 Zeilen vor dem
Schreiben als ALT/NEU ausgegeben und gelesen wurde -- und danach
gezielt nach falschen Artikeln gesucht ("den Rudel", "der Rudel",
"einen Rudel"). Uebrig blieben sechs Treffer, und die sind alle
richtig: "einen Rudel-Raum", "der Rudel-Chat", "den Rudel-Regeln" --
Zusammensetzungen, bei denen der Artikel zum letzten Wort gehoert.
UND ZWEI PRUEFUNGEN, die die Umbenennung nicht mitbekommen haetten:
`/Treff/.test(...)` und `/Treff/i.test(...)`. Ein regulaerer Ausdruck
ist keine Zeichenkette -- sie haetten ab sofort nach einem Wort
gesucht, das die Seite nicht mehr sagt, und waeren still rot geworden,
ohne dass etwas kaputt ist.
Geprueft, alle gruen: pruef-treff, pruef-treffchat,
pruef-deutsche-texte, pruef-uebernahme, pruef-crew-adresse,
pruef-willkommen, pruef-wege-nach-draussen, pruef-vorlagen,
pruef-start-ansicht, pruef-struktur.
Co-Authored-By: Claude Opus 5 <[email protected]>
252 lines
12 KiB
JavaScript
252 lines
12 KiB
JavaScript
/* =====================================================================
|
|
TEXT FUER MENSCHEN TRAEGT UMLAUTE (16.09.2026)
|
|
|
|
Auf dem Aufgabenbrett des Teams stand, gut lesbar, in der Erklaerung
|
|
unter der Kategorie Chat-Moderation:
|
|
|
|
"Was im Livechat passiert, waehrend gesendet wird. Loeschen,
|
|
stummschalten, begruessen, deeskalieren."
|
|
|
|
Vierzehn Kategorien und drei Stufen -- vierundzwanzig solcher
|
|
Stellen. Keine Pruefung hat es gesehen: Der Text war inhaltlich
|
|
richtig, der Katalog vollstaendig, die Seite gruen. Aufgefallen ist
|
|
es erst auf einem Bildschirmfoto.
|
|
|
|
---------------------------------------------------------------------
|
|
WARUM ES PASSIERT IST -- UND WIEDER PASSIEREN WUERDE
|
|
|
|
Kommentare sind in diesem Haus bewusst ohne Umlaute geschrieben, und
|
|
Aenderungen an grossen Dateien laufen ueber Hilfsskripte, die an
|
|
Umlauten und Maskierungen gern scheitern. Wer in so einem Skript Text
|
|
schreibt, schreibt ihn reflexhaft in ASCII. Fuer einen Kommentar ist
|
|
das gleichgueltig. Fuer einen Satz, den ein Mensch liest, ist es ein
|
|
Fehler -- und einer, der keine Fehlermeldung erzeugt.
|
|
|
|
Ein Warnhinweis daneben haette nicht geholfen. Das steht so in den
|
|
Hausregeln, aus einem anderen Schaden: Ein Kommentar, der vor einem
|
|
Fehler warnt, verhindert ihn nicht. Er wird beim naechsten Mal nicht
|
|
gelesen. Deshalb eine Pruefung.
|
|
|
|
---------------------------------------------------------------------
|
|
WAS SIE SEHEN KANN -- UND WAS NICHT
|
|
|
|
Rechnerisch entscheiden laesst es sich NICHT. "ue" ist in "Feuer",
|
|
"Steuer", "neue" und "aktuell" voellig richtig, "ae" in "Michael",
|
|
"oe" in "Poesie", und "ss" stimmt in jedem zweiten deutschen Wort.
|
|
Ein Muster aus blossen Buchstabenfolgen wuerde entweder alles
|
|
durchlassen oder staendig falschen Alarm schlagen.
|
|
|
|
Deshalb eine Liste von Wortstuecken, die als Ersatzschreibung
|
|
praktisch eindeutig sind ("waehr", "loesch", "begruess", "ueber").
|
|
Sie ist ein NETZ, kein Beweis: Sie findet das Haeufige und kann
|
|
Seltenes durchlassen. Das ist ehrlich so gemeint -- eine Pruefung,
|
|
die ihre Grenze nennt, ist mehr wert als eine, die mehr verspricht,
|
|
als sie haelt.
|
|
|
|
Vor dem Bauen gemessen: null Fehlalarme auf 174 Katalogtexten und
|
|
28 ausgelieferten Seiten.
|
|
|
|
---------------------------------------------------------------------
|
|
UND WARUM DIE SKRIPTE NICHT MITGEPRUEFT WERDEN
|
|
|
|
Ausprobiert -- und es war das Aufschlussreichste an der Sache: In den
|
|
38 Skripten unter workspace/assets/js schlug dieselbe Liste 71 Mal
|
|
an, und KEIN EINZIGER Treffer war ein Fehler. Es waren Feldnamen
|
|
("f-geraet"), Stilklassen ("team-karte__ueber"), Adressen
|
|
("/workspace/api/uebersicht"), Datenschluessel ("review_faellig").
|
|
Die muessen ASCII sein -- ein Umlaut waere dort der Fehler.
|
|
|
|
Eine Warnung, die immer kommt, ist keine Warnung mehr. Der sichtbare
|
|
Text aus den Skripten wird deshalb dort geprueft, wo er Text ist und
|
|
kein Bezeichner: am fertig gebauten Bildschirm, in
|
|
pruef-modi-katalog.
|
|
|
|
Aufrufen mit: node server/pruef-deutsche-texte.mjs
|
|
===================================================================== */
|
|
|
|
import { readdirSync, readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { ersatzschreibungen } from "./helfer-deutsch.mjs";
|
|
|
|
/* Pfade am Ort DIESER Datei festmachen, nicht am Arbeitsverzeichnis.
|
|
Sonst misst die Pruefung verschiedene Dinge, je nachdem, aus welchem
|
|
Ordner sie gestartet wurde -- und findet im schlimmsten Fall gar
|
|
keine Seiten und meldet trotzdem "in Ordnung". */
|
|
const SEITEN_ORDNER = fileURLToPath(new URL("../workspace/", import.meta.url));
|
|
|
|
let fehler = 0, geprueft = 0;
|
|
const melde = (t) => console.log(t);
|
|
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
|
|
|
|
/* =======================================================================
|
|
1. DIE KATALOGE
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 1. Was in den Katalogen steht ===");
|
|
const [w, v, as, ts, ep] = await Promise.all([
|
|
import("./workspace.js"), import("./workspace-vorlagen.js"),
|
|
/* SEIT DEM 17.09.2026 AUCH DIESE DREI. Sie kamen an einem Tag dazu
|
|
-- 113 fertige Einträge, 40 Entwicklungspunkte, 6 Befindensfragen
|
|
-- und diese Prüfung war die ganze Zeit grün, ohne eine Zeile
|
|
davon gelesen zu haben. Ein Katalog, den die Sprachprüfung nicht
|
|
kennt, ist ein Katalog ohne Sprachprüfung. */
|
|
import("./workspace-arbeit-start.js"),
|
|
import("./workspace-treff-start.js"),
|
|
import("./workspace-entwicklungs-punkte.js"),
|
|
]);
|
|
|
|
const texte = [];
|
|
for (const k of w.MODI_KATEGORIEN) texte.push([`Kategorie ${k.wert}`, `${k.name} ${k.text}`]);
|
|
for (const s of w.MODI_STUFEN) texte.push([`Stufe ${s.wert}`, `${s.name} ${s.text}`]);
|
|
for (const g of v.MODI_GRUPPEN) texte.push([`Gruppe ${g.schluessel}`, `${g.name} ${g.text}`]);
|
|
for (const a of v.MODI_AUFGABEN_FLACH) texte.push([`Modi ${a.schluessel}`, `${a.titel} ${a.text}`]);
|
|
for (const a of v.MODI_KATALOG) texte.push([`Agentur ${a.schluessel}`, `${a.titel} ${a.text}`]);
|
|
/* Die beiden Startkataloge -- abgeleitet aus ihren eigenen Schlüsseln,
|
|
nicht aus einer Liste hier. Kommt ein Bereich dazu, ist er dabei. */
|
|
for (const [bereich, liste] of Object.entries(as.ARBEIT_START)) {
|
|
for (const e of liste) texte.push([`Start ${bereich}`, `${e.titel} ${e.text ?? ""}`]);
|
|
}
|
|
for (const [bereich, liste] of Object.entries(ts.TREFF_START)) {
|
|
for (const e of liste) texte.push([`Rudel ${bereich}`, `${e.titel} ${e.text ?? ""}`]);
|
|
}
|
|
/* Und der Entwicklungskatalog samt seiner Blöcke und Stufen. */
|
|
for (const b of ep.ENTWICKLUNG_BLOECKE) texte.push([`Block ${b.schluessel}`, `${b.name} ${b.text}`]);
|
|
for (const e of ep.ENTWICKLUNG_ERWARTUNG) texte.push([`Erwartung ${e.schluessel}`, `${e.name} ${e.text}`]);
|
|
for (const pt of ep.ENTWICKLUNG_ALLE) texte.push([`Punkt ${pt.schluessel}`, `${pt.titel} ${pt.text}`]);
|
|
|
|
/* DIE ANZAHL GEHOERT IN DIE BEDINGUNG, nicht nur in den Meldetext.
|
|
Waere der Katalog leer, haette die Schleife darunter nichts zu tun
|
|
und wuerde ein sattes Gruen melden. */
|
|
/* 350 und nicht 400: Gemessen sind es am 17.09.2026 exakt 391. Die
|
|
Grenze ist eine SICHERUNG gegen "es wird gar nichts mehr geprueft",
|
|
keine Behauptung ueber die genaue Zahl -- deshalb mit Luft nach
|
|
unten und ohne Anspruch, gepflegt zu werden. Meine erste Fassung
|
|
stand auf 400 und war damit sofort rot: geraten statt gemessen. */
|
|
ok(texte.length >= 350, `${texte.length} ausgelieferte Katalogtexte gefunden`);
|
|
|
|
const schmutzig = texte.filter(([, t]) => ersatzschreibungen(t).length);
|
|
for (const [wo, t] of schmutzig) {
|
|
melde(` ${wo}: [${ersatzschreibungen(t).join(", ")}] ${t.slice(0, 70)}`);
|
|
}
|
|
ok(schmutzig.length === 0,
|
|
`keiner davon schreibt Umlaute als ae/oe/ue/ss (${schmutzig.length} Funde)`);
|
|
|
|
/* ZWEI BINDESTRICHE SIND KEIN GEDANKENSTRICH. Derselbe Reflex aus
|
|
demselben Grund: Im Kommentar ist "--" die Hausschreibweise, auf dem
|
|
Bildschirm sind es zwei Striche, die wie ein Tippfehler aussehen. */
|
|
const striche = texte.filter(([, t]) => t.includes("--"));
|
|
for (const [wo, t] of striche) melde(` ${wo}: ${t.slice(0, 70)}`);
|
|
ok(striche.length === 0,
|
|
`und keiner zwei Bindestriche statt eines Gedankenstrichs (${striche.length} Funde)`);
|
|
|
|
/* =======================================================================
|
|
2. DER SICHTBARE TEXT DER SEITEN
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 2. Was fest auf den Seiten steht ===");
|
|
{
|
|
let seiten = 0, stellen = 0;
|
|
for (const datei of readdirSync(SEITEN_ORDNER)) {
|
|
if (!datei.endsWith(".html")) continue;
|
|
seiten++;
|
|
/* Kommentare und Skriptbloecke raus -- dort ist ASCII richtig. */
|
|
const roh = readFileSync(SEITEN_ORDNER + datei, "utf8")
|
|
.replace(/<!--[\s\S]*?-->/g, " ")
|
|
.replace(/<(script|style)[\s\S]*?<\/\1>/g, " ");
|
|
for (const stueck of roh.split(/<[^>]*>/)) {
|
|
const t = stueck.trim();
|
|
if (t.length < 4) continue;
|
|
const treffer = ersatzschreibungen(t);
|
|
if (treffer.length) {
|
|
stellen++;
|
|
melde(` ${datei}: [${treffer.join(", ")}] ${t.slice(0, 70)}`);
|
|
}
|
|
}
|
|
}
|
|
ok(seiten >= 20, `${seiten} ausgelieferte Seiten durchgesehen`);
|
|
ok(stellen === 0, `ihr sichtbarer Text ist frei von Ersatzschreibungen (${stellen} Funde)`);
|
|
}
|
|
|
|
/* =======================================================================
|
|
2b. DIE BESCHRIFTUNGEN DER COMMUNITY-BEREICHE
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 2b. Was an den Brettern steht ===");
|
|
{
|
|
/* NACHGETRAGEN AM 17.09.2026, und der Weg dorthin gehoert dazu:
|
|
Auf einem Bildschirmfoto der Wunschliste stand "WAS IHR EUCH
|
|
WUENSCHT" und "FUER DEN STREAM". Diese Pruefung sah es nicht --
|
|
sie kannte die Kataloge und die festen Seitentexte, aber nicht die
|
|
Bereichseinstellungen, aus denen jede Ueberschrift und jede
|
|
Art-Beschriftung kommt.
|
|
|
|
Sechs Stellen waren es. Gefunden hat sie kein Gedankengang,
|
|
sondern ein Blick auf das fertige Bild -- deshalb steht das hier. */
|
|
const b = await import("./workspace-bereiche.js");
|
|
const texte = [];
|
|
const sammeln = (wo, wert) => {
|
|
if (typeof wert === "string" && wert.length > 2) texte.push([wo, wert]);
|
|
};
|
|
for (const [name, e] of Object.entries(b.BEREICHE || {})) {
|
|
for (const [feld, wert] of Object.entries(e)) {
|
|
sammeln(`${name}.${feld}`, wert);
|
|
if (wert && typeof wert === "object" && !Array.isArray(wert)) {
|
|
for (const [a, x] of Object.entries(wert)) sammeln(`${name}.${feld}.${a}`, x);
|
|
}
|
|
}
|
|
}
|
|
ok(texte.length >= 60, `${texte.length} Beschriftungen gefunden`);
|
|
const schmutzig = texte.filter(([, t]) => ersatzschreibungen(t).length);
|
|
for (const [wo, t] of schmutzig) {
|
|
melde(` ${wo}: [${ersatzschreibungen(t).join(", ")}] ${t}`);
|
|
}
|
|
ok(schmutzig.length === 0,
|
|
`keine schreibt Umlaute als ae/oe/ue/ss (${schmutzig.length} Funde)`);
|
|
}
|
|
|
|
/* =======================================================================
|
|
3. GEGENPROBE -- KANN DIE PRUEFUNG UEBERHAUPT ROT WERDEN?
|
|
======================================================================= */
|
|
melde("");
|
|
melde("=== 3. Die Gegenprobe ===");
|
|
{
|
|
/* WORTWOERTLICH DER TEXT, DER AM 16.09. AUF DEM BRETT STAND. Ohne
|
|
diese Zeile beweisen die Abschnitte darueber nichts: Eine Liste,
|
|
die nie anschlaegt, meldet immer "in Ordnung". */
|
|
const alt = "Was im Livechat passiert, waehrend gesendet wird. "
|
|
+ "Loeschen, stummschalten, begruessen, deeskalieren.";
|
|
const gefunden = ersatzschreibungen(alt);
|
|
ok(gefunden.length >= 3, `der alte Kategorietext schlaegt an (${gefunden.join(", ")})`);
|
|
|
|
/* UND DER SATZ VON HEUTE, an dem das Netz ein Loch hatte. Ohne ihn
|
|
waere nicht bewiesen, dass die Liste nachgezogen wurde. */
|
|
ok(ersatzschreibungen("Was ihr euch wuenscht").length > 0,
|
|
"auch \"wuenscht\" schlaegt an -- das tat es heute Morgen noch nicht");
|
|
|
|
/* UND DIE ANDERE RICHTUNG, genauso wichtig: Der reparierte Text darf
|
|
NICHT anschlagen. Sonst waere die Liste einfach zu breit. */
|
|
const neu = "Was im Livechat passiert, während gesendet wird. "
|
|
+ "Löschen, stummschalten, begrüßen, deeskalieren.";
|
|
ok(ersatzschreibungen(neu).length === 0, "der reparierte Text nicht");
|
|
|
|
/* DIE HAEUFIGSTEN ECHTEN WOERTER, in denen ae/oe/ue/ss korrekt sind.
|
|
Sie stehen hier, weil genau sie eine zu grobe Liste verraten
|
|
wuerden -- und weil "Feuer" und "neue" in echten Texten vorkommen. */
|
|
const echt = "Die neue Steuer ist teuer, das Feuer ein Abenteuer. "
|
|
+ "Michael liest Poesie, das Wasser ist nass, und dass es aktuell "
|
|
+ "regnet, muss uns nicht weiter stören.";
|
|
const falschAlarm = ersatzschreibungen(echt);
|
|
ok(falschAlarm.length === 0,
|
|
`echte ue/ae/oe/ss-Woerter loesen keinen Alarm aus (${falschAlarm.join(", ") || "keiner"})`);
|
|
|
|
/* UND DIE ZWEITE GEGENPROBE zum Gedankenstrich, aus demselben Grund. */
|
|
ok("Klar umrissen -- und erreichbar.".includes("--"),
|
|
"zwei Bindestriche werden als solche erkannt");
|
|
}
|
|
|
|
/* ------------------------------------------------------------------- */
|
|
melde("");
|
|
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
|
|
melde(fehler ? "NICHT IN ORDNUNG" : "ALLES IN ORDNUNG");
|
|
process.exit(fehler ? 1 : 0);
|