# Altersvorsorge-Vergleich — Webanwendung Progressive Webanwendung (PWA) zum Vergleich dreier Gestaltungsvarianten der Altersvorsorge. Es handelt sich um das eigentliche Erzeugnis dieses Bestandes; hinsichtlich einer allgemeinen Einführung wird auf das [Wurzel-README](../README.md) verwiesen. Der Rechenkern ist aus einer zwischenzeitlich entfallenen Excel-Arbeitsmappe übernommen worden, welche ausschließlich über die Versionsgeschichte zugänglich ist; die Ergebnisse sind dieselben, die Bedienung ist jedoch auch denjenigen Personen eröffnet, welche eine Tabellenkalkulation nicht zu öffnen beabsichtigen. | Datei | Zweckbestimmung | |---|---| | `index.html` | **Die vollständige Anwendung.** Rechenkern, Bedienoberfläche und Diagramme in einer einzigen Datei, ohne externe Abhängigkeiten mit Ausnahme der Wörterbücher. Der Aufruf erfolgt mittels Doppelklicks. | | `i18n.de.js` | Wörterbuch Deutsch. Hauptsprache und Rückfallebene. **Vollständig.** | | `i18n.en.js` `i18n.nl.js` `i18n.fr.js` `i18n.la.js` `i18n.ja.js` | Englisch, Niederländisch, Französisch, Latein, Japanisch. **Vollständig** (459 Schlüssel). | | `i18n.nds.js` `i18n.bar.js` `i18n.eu.js` `i18n.eo.js` `i18n.tr.js` `i18n.uk.js` | Niederdeutsch, Bairisch, Baskisch, Esperanto, Türkisch, Ukrainisch. **Vollständig** (siehe § 3b). | | `i18n.got.js` `i18n.goh.js` `i18n.gmh.js` `i18n.grc.js` `i18n.sa.js` | Gotisch, Althochdeutsch, Mittelhochdeutsch, Altgriechisch, Sanskrit. **Vollständig.** | | `i18n.ine-x-proto.js` | Urindogermanisch in LIV²/Rix-Notation nebst Laryngalen und Asterisk. Ein Code nach ISO 639-3 ist nicht zu erlangen, da für Rekonstruate keine Codes vergeben werden; es wird daher der Privatuntertag `ine-x-proto` nach BCP 47 geführt. **Vollständig.** | | `i18n.jbo.js` `i18n.tok.js` | Lojban, Toki Pona. Toki Pona wird in sitelen Lasina (ASCII) vorgehalten; das Stilblatt setzt für `lang="tok"` ligaturfähige sitelen-pona-Zeichensätze, welche die ASCII-Wörter zu Logographen binden. Ist ein solcher Zeichensatz nicht installiert, verbleibt lesbares Latein anstelle leerer Kästchen. **Vollständig.** | | `i18n.akk-x-ob.js` | Altbabylonisch in Keilschrift (U+12000 ff.). Erzeugt aus `i18n.akk-x-ob.translit.js` mittels `node akk-keilschrift.js`; die Umschrift ist die Quelle, die Keilschrift das Erzeugnis. Die Codepunkte werden zur Bauzeit über die Unicode-Namenstabelle aufgelöst und nicht von Hand gesetzt. **Vollständig.** | | `manifest.json` | Bewirkt die Installierbarkeit (Bezeichnung, Farben, Symbole). | | `service-worker.js` | Offline-Zwischenspeicher, Verfahren `stale-while-revalidate`. | | `icon-*.png` | Symbole der Anwendung, 192 / 512 / 512-maskable. | --- ## § 1 Weitergabe — drei Wege **a) Ausschließlich die Dateien.** Es sind `index.html` nebst sämtlichen dreiundzwanzig `i18n.*.js` zu übersenden; sie gehören zusammen und haben in demselben Ordner zu liegen. Ein Doppelklick genügt, sämtliche Berechnungen werden durchgeführt, und die Eingaben werden im Browser vorgehalten. Es fehlt lediglich die PWA-Hülle — mithin das Symbol auf dem Startbildschirm sowie der Offline-Zwischenspeicher. Beides ist hier entbehrlich, da die Datei bereits auf dem Gerät vorliegt. Die Anwendung weist hierauf von sich aus hin. **b) Der vollständige Ordner auf einem Webspeicherplatz.** Ein beliebiges HTTPS-Hosting genügt (GitHub Pages, Netlify, ein Unterverzeichnis der eigenen Domäne). Sodann ist die Anwendung installierbar und offlinefähig. Ein Hintergrundsystem, eine Datenbank sowie eine Baukette bestehen nicht. ```bash # örtliche Erprobung einschließlich Dienstarbeiter: cd app && python3 -m http.server 8000 # -> http://localhost:8000 ``` Dienstarbeiter (*service worker*) sind auch über `http://localhost` betriebsfähig; localhost ist als sicherer Kontext ausdrücklich ausgenommen. **c) Als Verweis.** Die Schaltfläche *„Link mit meinen Zahlen kopieren"* kodiert den vollständigen Eingabestand base64url in den Fragmentbezeichner. Fragmente werden vom Browser **nicht** an den Server übermittelt (RFC 3986 § 3.5); der Verweis enthält mithin persönliche Zahlen, überträgt diese jedoch an niemanden außer den Empfänger. ## § 2 Verbleib der Daten Ausschließlich in `localStorage` unter dem Schlüssel `altersvorsorge.v1`, mithin im Browser der nutzenden Person. Ein Server, eine Auswertung, Schriftarten von fremden Domänen sowie externe Skripte bestehen nicht. Die einzigen Netzwerkzugriffe der Anwendung sind diejenigen, welche der Dienstarbeiter zum Zwecke seiner eigenen Aktualisierung vornimmt. ## § 3 Aufbau der Datei `index.html` ist in nummerierte Teile gegliedert: | Teil | Inhalt | |---|---| | 0 | **Sprachen** — `t()`, Sprachwahl, Rückfall auf Deutsch | | 1 | **Rechenkern** — Portierung des ursprünglichen Formelgenerators. Reine Funktionen, kein DOM | | 2 | Felddefinitionen: 80 Eingaben nebst Bereich, Einheit und Wörterbuchschlüssel | | 3 | Zustand, `localStorage`, Kodierung für den Weitergabeverweis | | 4 | Formatierung und Zahleneingabe, sprachabhängig | | 5 | Kennzahlen | | 6 | Aufbau der Bedienoberfläche | | 7 | Ergebniskarten nebst Δ-Anzeige | | 7b | Klartextfazit, Hinweis auf Beispielwerte, mitlaufende Ergebnisleiste | | 8 | Diagramme, ausschließlich Canvas | | 9 | Rechenweg | | 10 | Render-Schleife | | 11 | Installation und Offline-Betrieb | | 12 | Fensterrahmen: Titelleisten und Minimieren | | 13 | Kachelung: eine, zwei oder drei Fensterspalten | | 14 | Sprachumschaltung in der Bedienoberfläche | Der Rechenkern in Teil 1 ist **die einzige Stelle, an der gerechnet wird.** Er ist zeichengenau aus dem ursprünglichen Formelgenerator übertragen worden; Änderungen der Rechtslage sind mithin ausschließlich dort vorzunehmen. ### Brutto- und Nettobetrag sind gekoppelt Ein Umschalter „Vorgabe: Brutto / Netto" besteht nicht mehr. Beide Felder weisen dieselbe Größe aus, lediglich in verschiedener Währung: ``` N(B) = B − SV-Ersparnis_AN(B) − Steuerersparnis(B) ``` `N` ist auf `[0, Bruttogehalt]` stetig und wegen `dN/dB = 1 − Grenz-SV-Satz − Grenzsteuersatz > 0` streng monoton wachsend, mithin eine Bijektion auf `[0, N(Bruttogehalt)]`. Ein Umschalter wäre eine Auswahl zwischen einer Funktion und ihrer Umkehrfunktion, mithin keine Auswahl. `beitrag` verbleibt die einzige maßgebliche Größe; `netto_ziel` ist ein **abgeleitetes Feld** mit `get` (Vorwärtsrechnung, Jahr 0 der Ansparphase) und `set` (Intervallhalbierung, `bruttoVonNetto`). Beide werten dasselbe erste Jahr aus — Lohn- und Tarifindex betragen dort 1 —, weshalb die Richtungen exakt invers sind. Gemessen über 12 Parameterkombinationen × 5 Stützstellen: | Richtung | größter relativer Fehler | |---|---| | B → N → B | 2,3 · 10⁻⁸ | | N → B → N | 2,1 · 10⁻⁸ | Dies entspricht genau der Auflösung des Halbierungsverfahrens: 34 Halbierungen auf `[0, 250.000 €]` ergeben 1,5 · 10⁻⁵ €/Jahr, mithin gut ein Millionstel Cent im Monat. Die Monotonie ist ergänzend auf `1 … 1.500 €/Monat` in Ein-Euro-Schritten geprüft worden; die geringste beobachtete Steigung beträgt `dN/dB = 0,545`, mithin tragen Steuer und Sozialabgaben zusammen niemals mehr als 45,5 vom Hundert des Bruttobeitrags. Fällt der Nettoaufwand für das erste Jahr auf null — weil zu diesem Zeitpunkt bereits ein Ausscheiden vorliegt —, so existiert die Umkehrung nicht. Die Anwendung weist hierauf hin, anstatt untätig zu verbleiben. ## § 3b Dreiundzwanzig Sprachfassungen Deutsch ist die Hauptsprache; sämtliche übrigen Fassungen sind Übersetzungen derselben Rechtslage und nicht etwa ein zweiter Rechtsstand. **Die Normzitate verbleiben in sämtlichen Sprachfassungen in deutscher Sprache** (`§ 1a BetrAVG`, `§ 226 Abs. 2 S. 2 SGB V`, …) — es handelt sich um die Primärquellen, für welche eine amtliche Übersetzung nicht vorliegt; eine eigene wäre insoweit keine Hilfe, sondern eine Fehlerquelle. Gleichermaßen verbleiben zwei Produktbezeichnungen unübersetzt, da es sich um Eigennamen handelt: `Altersvorsorgedepot` und `Versorgungsbezüge`; im Japanischen nebst Glosse (`Versorgungsbezüge(企業年金等の給付)`). | | Sprachen | Schlüssel | |---|---|---| | **vollständig** | `de` `de-x-amt` `de-x-sales` `en` `nl` `fr` `la` `ja` `nds` `bar` `eu` `eo` `tr` `uk` `got` `goh` `gmh` `grc` `sa` `ine-x-proto` `jbo` `tok` `akk-x-ob` | 459 | | **teilweise** | — | — | Sämtliche dreiundzwanzig Sprachfassungen sind zwischenzeitlich vollständige Wörterbücher (459 von 459 Schlüsseln); die Tabellenzeile „teilweise" verbleibt, weil `TEILWEISE` in `index.html` als Mechanismus fortbesteht — sie ist lediglich derzeit unbesetzt. Ursprünglich erfolgte die Auswahl strukturell und nicht nach Zeichenzahl: zuerst übersetzt wurde dasjenige, was betätigt oder als Überschrift gelesen wird — Feldbeschriftungen, Einheiten, Auswahlwerte, Fenstertitel, Kennzahlen, Tabellenköpfe, Diagrammlegenden, Meldungen; die ausführlichen juristischen Erläuterungen (die `?`-Texte an den Feldern, das Fazit, die Notizen unter den Feldern, der gesamte Rechenweg) sind erst in einer zweiten Fassung hinzugetreten. Für die drei historischen Sprachstufen sowie für Sanskrit und Altgriechisch ist der Vertrauensgrad in diesen Fließtextpassagen entsprechend geringer als in den Feldbeschriftungen selbst; die genauen Prozentsätze sowie die dort neu geprägten Fachbegriffe sind den Kopfkommentaren der jeweiligen `i18n.*.js`-Datei zu entnehmen. **Die drei alten germanischen Fassungen** (`got` Gotisch, `goh` Althochdeutsch, `gmh` Mittelhochdeutsch) sind nicht als Scherz zu verstehen, sondern als Probe darauf, wie viel Fachsprache eine Sprachstufe zu tragen vermag. Lediglich `goh` und `gmh` sind Vorstufen des Deutschen; **das Gotische ist ostgermanisch und mithin eine Schwester, keine Ahnin** — es steht hier, weil es das älteste umfangreich überlieferte Germanisch überhaupt darstellt. Das Ergebnis ist ein deutliches Gefälle, welches genau der Verstädterung folgt: - **Gotisch** verfügt mit der Wulfila-Bibel über ein Korpus von rund 3.000 Lexemen, von welchen praktisch keines wirtschaftlicher Natur ist. Belegt sind immerhin `faihu` (Vermögen), `gild` (Abgabe), `wokrs` (Zins, Lk 19,23 *miþ wokra*), `mizdo` (Lohn), `asneis` (Lohnarbeiter). Alles Übrige — `haubidafaihu` für Kapital, `gagaleikeins` für Vergleich — ist geprägt. Vertrauensgrad ≈ 30 vom Hundert. - **Althochdeutsch** gewinnt durch Tatian und Notker: `gelt`, `zins`, `lon`, `wuohhar` sind belegt, und **`widarmezzon` steht im Tatian genau für lateinisch *comparare*** — der Fenstertitel ist mithin kein Kunstwort. Vertrauensgrad ≈ 50 vom Hundert. - **Mittelhochdeutsch** ist die tragfähigste Stufe, da bereits eine städtische Geld- und Rechtssprache besteht. Drei Treffer sind keine Prägung, sondern der jeweilige Terminus: **`houbetguot`** ist das Kapital, **`lîpgedinge`** die lebenslange Leibrente, **`tiurunge`** der Preisanstieg, mithin die Inflation. Hinzu treten `gülte`, `stiure`, `wuocher`, `gewin`, `koste`. Vertrauensgrad ≈ 65 vom Hundert. **Das Gotische steht in lateinischer Umschrift** (Streitberg) und nicht im Wulfila-Alphabet (U+10330–1034F). Maßgeblich hierfür ist der Grundsatz gemäß § 2: die Anwendung lädt keine Schriften von fremden Domänen. Für die gotische Schrift liegt auf keinem verbreiteten System eine vorinstallierte Datei vor — 𐌰𐌻𐌻𐌰𐌹𐌼 erschiene als leere Kästchen. Die Umschrift ist ohnehin diejenige Form, in welcher das Gotische gelesen wird. Wer die Schrift wünscht, bedarf einer eingebetteten Schriftart und mithin einer abweichenden Grundsatzentscheidung. ### Registervarianten des Deutschen: eingerichtet **„Beamtendeutsch" und „Vertrieb"** sind keine Sprachen, sondern Stilebenen derselben Sprache; sie werden daher nach BCP 47 § 2.2.7 unter `de` mit privatem Untertag geführt: `de-x-amt` und `de-x-sales`, in `i18n.de-x-amt.js` und `i18n.de-x-sales.js`. Abweichend von den übrigen Sprachfassungen genügt hier keine Teilfassung: der Witz liegt gerade im Fließtext, welchen eine Teilübersetzung fortließe. Derselbe § 1a BetrAVG lautet im Amtsdeutsch „Ein Rechtsanspruch besteht ausschließlich bis zur Höhe von 4 vom Hundert der Beitragsbemessungsgrenze der Rentenversicherung" und im Vertriebsdeutsch „Bis zu 4 % on top — geschenkt vom Gesetzgeber!" — beide Fassungen beschreiben exakt dieselbe Rechtslage, und der Vergleich ist der Punkt. Die Zahlen ändern sich auch dort nicht; `pruefe.js` prüft dies wie bei jeder anderen Sprache ohne Sonderfall. Technisch waren hierfür drei Änderungen erforderlich: `pickLang()` erkennt seither zusätzlich zur Grundsprache beliebig viele `-x-[a-z0-9]{1,8}`-Untertags; `LANGS` und `DICT` haben Einträge mit Bindestrich erhalten; `LOCALES` und `GRUPPEN` bedurften hingegen **keiner** neuen Einträge, da deren bestehende `||`-Rückfälle (`'de-DE'` bzw. `'.'`) für beide Varianten bereits das Zutreffende liefern. Die Sprachschaltfläche weist nicht den vollständigen Code aus (`DE-X-AMT` wäre für die zweizeilige Schaltfläche zu lang), sondern lediglich den Teil nach dem letzten Bindestrich (`AMT`, `SALES`); `lang="…"` sowie das Autonym im `title` tragen weiterhin den vollständigen Code bzw. die vollständige Bezeichnung. ### Vorgemerkt, noch nicht eingerichtet **Rechtsläufige Sprachen (`he`, `fa`, `ar`).** Die Übersetzung stellt den geringeren Aufwand dar. Aufwendig ist Dreierlei: `applyStatic()` hat neben `lang` auch `dir` zu setzen; im Stilblatt sind `margin-left`/`-right` durch die logischen Eigenschaften zu ersetzen, da andernfalls die Kachelung kippt; und Teil 8 zeichnet auf Canvas, wo **ein Bidi-Algorithmus nicht besteht** — Achsen, Legenden und der Wasserfall wären mithin von Hand zu spiegeln. Hinzu treten `fa-u-nu-latn` und `ar-u-nu-latn` in `LOCALES`, da ICU andernfalls ostarabische Ziffern (۱۲۳۴) neben einem `€` liefert. Die Einzelheiten sind als Kommentarblock in `index.html` unmittelbar bei `TEILWEISE` niedergelegt. **Codes.** ISO 639-1, soweit ein solcher besteht, im Übrigen 639-3. Dreibuchstabig sind `grc` (**nicht** `el` — dies wäre Neugriechisch), `nds` und `bar`; für keine der drei Sprachen besteht ein zweibuchstabiger Code. `pickLang()` erkennt daher `[a-z]{2,3}` als Grundcode, fakultativ gefolgt von den vorgenannten `-x-…`-Untertags. **Wahl der Sprache**, in nachstehender Reihenfolge: 1. `?lang=…` in der Adresse — weitergabefähig, überschreibt alles Übrige, 2. die vorgehaltene Wahl in `localStorage` unter `altersvorsorge.lang`, 3. `navigator.language`, nach BCP-47-Teilkette (`xx` oder `xx-…`). **Latein, Altgriechisch, Sanskrit und Esperanto werden niemals selbsttätig gewählt** — ein Browser, welcher `la` meldet, meint dies mit an Sicherheit grenzender Wahrscheinlichkeit nicht als Anzeigesprache. Die Schaltflächen tragen das Kürzel, der `title` hingegen das **Autonym** (`Українська`, `Plattdüütsch`, `संस्कृतम्`) und nicht die übersetzte Bezeichnung. Wer Ukrainisch sucht, erkennt `Українська` auch dann, wenn die Oberfläche gegenwärtig auf Baskisch eingestellt ist; nebenbei werden hierdurch 14 × 14 Wörterbucheinträge eingespart. **Zahlenformat.** `LOCALES` bildet jeden Code auf ein ICU-Tag ab, `GRUPPEN` auf das Tausenderzeichen, welches `parseNum()` beim mehrdeutigen `1,234` heranzieht. Sprachen ohne eigene ICU-Daten (`nds`, `bar`, `eo`, `la`, `grc`, `sa`) erhalten `de-DE`: Devanāgarī-Ziffern neben einem `€` wären eine Schikane und keine Genauigkeit, griechische Buchstabenzahlen erst recht. `fr` gruppiert mit U+202F, `uk` mit U+00A0 — beides so, wie ICU es tatsächlich setzt, nachgeprüft gegen `formatToParts`. **Zu Latein und Japanisch.** Das Latein ist pragmatisches Neulatein: klassische Syntax, jedoch gebildete Neuprägungen für die Moderne (`pensio operativa`, `impensa pura`, `valor praesens`, `usura interna`). Römische Ziffern wären ein Witz zu Lasten der Lesbarkeit — und die Trennzeichenkonvention ist ohnehin jünger als jede lateinische Quelle. Das Japanische folgt demjenigen, was für Software dieser Art dort üblich ist: Erläuterungstexte in です・ます, Feldbeschriftungen als Nominalphrasen im 体言止め. Für die Schrift ist der `--ui`-Stapel um MS PGothic, Hiragino, Yu Gothic und Meiryo erweitert worden — eine Rasterschrift mit harten Kanten ist dem Gegenstand angemessen. Der japanische Satzbau erzwingt dasjenige, wozu die Funktionsform der Einträge bestimmt ist. Das Fazit lautet im Deutschen „X liegt vorn mit W — D mehr als Y", im Japanischen hingegen `Xが首位です(W)。YをD上回ります。` — das Verb am Ende, die Vergleichsgröße mit を anstelle von „als". Als Verkettung fester Bausteine ließe sich dies nicht herstellen. Der Umschalter oben im Kopffenster schreibt beides fort, mithin Speicher und Adresse. Der Weitergabeverweis führt die Suchzeichenfolge mit, der Zustand verbleibt im Fragment; beides stört sich nicht. **Aufbau der Wörterbücher.** Ein Eintrag ist entweder eine Zeichenkette oder eine Funktion `(p, f) → string`. Die Funktionsform ist keine Bequemlichkeit, sondern zwingend erforderlich: ein Satz ist nicht die Verkettung seiner Teile. Stellung, Numerus und Rektion hängen an der Sprache, und `'mehr als ' + nom` ist lediglich so lange tragfähig, wie beide Sprachen denselben Satzbau aufweisen. Den Funktionen werden daher **Rohwerte** übergeben — Zahlen und keine fertigen Textstücke —, und die Formatierung erfolgt selbsttätig über `f` (`f.eur`, `f.pct`, `f.nf2`, …). Sichtbar wird der Unterschied etwa im Fazit: das Deutsche bedarf dort eines Genitivs (`der bAV`), das Englische einer Präposition. ``` t('n.beitrag.ueber8', { v8: v8 }) de: 'Über 8 % der Beitragsbemessungsgrenze RV (' + f.eur(p.v8) + ' im Jahr). …' en: 'Above 8 % of the pension-insurance contribution ceiling (' + f.eur(p.v8) + ' per year). …' ``` **Schlüsselschema.** Eingabefelder liegen unter `f.:.label|hint|unit|o`, die Optionen mithin unter ihrem *Wert* und nicht unter ihrem Index; sodann verbleibt die Zuordnung zutreffend, wenn eine Option hinzutritt. `FIELDS`, `OPTS` und `METRICS` führen ihre Texte nicht mehr als Feld, sondern als `Object.defineProperty`-Zugriffsfunktion: `f.label` steht unverändert an jeder Aufrufstelle und liefert nach einem Sprachwechsel von selbst den neuen Wert. **Fehlt ein Eintrag**, so greift Deutsch; fehlt auch dieser, so erscheint der Schlüssel selbst im Klartext. Ein stiller Leerstring wäre die schlechtere Wahl, da er unbemerkt verschwände. **Zahlen.** Umgeschaltet wird ausschließlich die Zifferngruppierung — `de` und `la` → `de-DE`, `en` → `en-GB`, `ja` → `ja-JP`; die Währung verbleibt durchgängig der nachgestellte Euro: `75.000,00 €` bzw. `75,000.00 €`. Die Eingabe nimmt **beide** Schreibweisen an, damit ein Sprachwechsel eine eingegebene Zahl nicht entwertet. Die Regel in `parseNum` lautet: stehen beide Zeichen im Text, so ist das rechte das Dezimalzeichen; steht lediglich eines und folgen ihm genau drei Ziffern, so handelt es sich um die Tausendergruppe der gegenwärtigen Sprache (`GRUPPEN`: `.` für de und la, `,` für en und ja). Damit verbleibt allein `1,234` mehrdeutig — und genau dort entscheidet die Sprache. **Was ein Sprachwechsel nicht anfasst:** die Eingaben, den Referenzstand und die Ergebnisse. `setLang` baut lediglich diejenigen Teile neu auf, deren Beschriftungen beim Aufbau festgeschrieben werden (Kennzahlenleiste, Registerkarten, Felder, Fenstertitel); alles Übrige zeichnet `refresh()` ohnehin bei jedem Durchgang. Der Referenzstand hält daher den *Feldschlüssel* vor und nicht den fertigen Satz; andernfalls stünde nach dem Wechsel „vor der Änderung von …" noch in der vormaligen Sprache da. **Prüfung.** `pruefe.js` (Entwicklungswerkzeug, wird vom Dienstarbeiter nicht ausgeliefert) lädt die Seite kopflos in jsdom, schaltet sämtliche dreiundzwanzig Sprachfassungen durch, klappt jeden Abschnitt auf, erzwingt über fünf Szenarien die bedingten Texte und prüft: kein unaufgelöster Schlüssel, keine deutschen Reste im englischen Modus außer den zugelassenen Fachbegriffen, kein sichtbar verbliebener Schlüssel, und — die eigentliche Invariante — **identische Rechenergebnisse in sämtlichen dreiundzwanzig Sprachfassungen**. Die Liste der Wörterbücher liest das Skript aus `index.html` aus, anstatt sie zu pflegen: eine neue Sprache soll den Test nicht stillschweigend an einem leeren Objekt vorbeilaufen lassen. Das Regex für die `