summaryrefslogtreecommitdiff
path: root/app/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'app/README.md')
-rw-r--r--app/README.md107
1 files changed, 102 insertions, 5 deletions
diff --git a/app/README.md b/app/README.md
index 3a87f05..8727649 100644
--- a/app/README.md
+++ b/app/README.md
@@ -5,7 +5,11 @@ Ergebnisse, aber bedienbar von Menschen, die keine Tabellenkalkulation aufmachen
| Datei | Rolle |
|---|---|
-| `index.html` | **Die ganze App.** Rechenkern, Oberfläche, Diagramme, Texte — eine Datei, keine externen Abhängigkeiten. Läuft per Doppelklick. |
+| `index.html` | **Die ganze App.** Rechenkern, Oberfläche, Diagramme — eine Datei, keine externen Abhängigkeiten außer den vier Wörterbüchern. Läuft per Doppelklick. |
+| `i18n.de.js` | Wörterbuch Deutsch. Hauptsprache und Rückfallebene. |
+| `i18n.en.js` | Wörterbuch Englisch. |
+| `i18n.la.js` | Wörterbuch Latein. |
+| `i18n.ja.js` | Wörterbuch Japanisch. |
| `manifest.json` | Macht die App installierbar (Name, Farben, Symbole). |
| `service-worker.js` | Offline-Cache, `stale-while-revalidate`. |
| `icon-*.png` | App-Symbole, 192 / 512 / 512-maskable. |
@@ -14,7 +18,8 @@ Ergebnisse, aber bedienbar von Menschen, die keine Tabellenkalkulation aufmachen
## 1. Weitergeben — drei Wege
-**a) Nur die Datei.** `index.html` verschicken. Sie ist vollständig autark: Doppelklick genügt,
+**a) Nur die Dateien.** `index.html` samt den vier `i18n.*.js` verschicken — sie gehören
+zusammen und müssen im selben Ordner liegen. Doppelklick genügt,
alles rechnet, Eingaben werden im Browser gespeichert. Was fehlt, ist nur die PWA-Hülle —
kein Symbol auf dem Startbildschirm, kein Offline-Cache. Beides braucht es hier auch nicht,
die Datei liegt ja schon auf dem Gerät. Die App sagt das dem Nutzer auch selbst.
@@ -45,14 +50,15 @@ selbst zu aktualisieren.
## 3. Aufbau der Datei
-`index.html` ist in elf nummerierte Teile gegliedert:
+`index.html` ist in nummerierte Teile gegliedert:
| Teil | Inhalt |
|---|---|
+| 0 | **Sprachen** — `t()`, Sprachwahl, Rückfall auf Deutsch |
| 1 | **Rechenkern** — Portierung von `build_bav.py`. Reine Funktionen, kein DOM |
-| 2 | Felddefinitionen: 80 Eingaben mit Bereich, Einheit, Erklärung, Fundstelle |
+| 2 | Felddefinitionen: 80 Eingaben mit Bereich, Einheit, Wörterbuchschlüssel |
| 3 | Zustand, `localStorage`, Kodierung für den Teilen-Link |
-| 4 | Formatierung (de-DE, Komma als Dezimaltrenner in beiden Richtungen) |
+| 4 | Formatierung und Zahleneingabe, sprachabhängig |
| 5 | Kennzahlen |
| 6 | Aufbau der Oberfläche |
| 7 | Ergebniskarten mit Δ-Anzeige |
@@ -63,6 +69,7 @@ selbst zu aktualisieren.
| 11 | Installation und Offline-Betrieb |
| 12 | Fensterrahmen: Titelleisten und Minimieren |
| 13 | Kachelung: ein, zwei oder drei Fensterspalten |
+| 14 | Sprachumschaltung in der Oberfläche |
Der Rechenkern in Teil 1 ist **die einzige Stelle, an der gerechnet wird.** Er ist zeichengenau
aus `build_bav.py` übertragen; Änderungen an der Rechtslage gehören in beide Dateien.
@@ -99,6 +106,85 @@ Bruttobeitrags.
Fällt der Nettoaufwand für das erste Jahr auf null — weil man dann bereits ausgeschieden ist —,
existiert die Umkehrung nicht. Die App sagt das statt still nichts zu tun.
+## 3b. Vier Sprachen
+
+Deutsch ist die Hauptsprache; Englisch, Latein und Japanisch sind Übersetzungen derselben
+Rechtslage, kein zweiter Rechtsstand. **Die Normzitate bleiben in allen Sprachen deutsch**
+(`§ 1a BetrAVG`, `§ 226 Abs. 2 S. 2 SGB V`, …) — sie sind die Primärquellen und haben keine
+amtliche Übersetzung; eine eigene wäre hier keine Hilfe, sondern eine Fehlerquelle. Ebenso
+bleiben zwei Produktnamen stehen, weil sie Eigennamen sind: `Altersvorsorgedepot` und
+`Versorgungsbezüge`; im Japanischen mit Glosse (`Versorgungsbezüge(企業年金等の給付)`).
+
+**Wahl der Sprache**, in dieser Reihenfolge:
+
+1. `?lang=de|en|la|ja` in der Adresse — teilbar, überschreibt alles,
+2. die gemerkte Wahl in `localStorage` unter `altersvorsorge.lang`,
+3. `navigator.language`: `ja…` → Japanisch, `en…` → Englisch, sonst Deutsch.
+ **Latein wird nie automatisch gewählt** — ein Browser, der `la` meldet, meint es fast sicher
+ nicht als Anzeigesprache.
+
+**Zu den beiden neuen Fassungen.** Das Latein ist pragmatisches Neulatein: klassische Syntax,
+aber gebildete Neuprägungen für Moderne (`pensio operativa`, `impensa pura`, `valor praesens`,
+`usura interna`). Römische Ziffern wären ein Witz auf Kosten der Lesbarkeit — und die
+Trennzeichenkonvention ist ohnehin jünger als jede lateinische Quelle. Das Japanische folgt
+dem, was für Software dieser Art dort üblich ist: Erklärtexte in です・ます, Feldbeschriftungen
+als Nominalphrasen im 体言止め. Für die Schrift ist der `--ui`-Stapel um MS PGothic, Hiragino,
+Yu Gothic und Meiryo erweitert — eine Rasterschrift mit harten Kanten passt zum Thema.
+
+Der japanische Satzbau erzwingt, wofür die Funktionsform der Einträge da ist. Das Fazit lautet
+im Deutschen „X liegt vorn mit W — D mehr als Y“, im Japanischen dagegen
+`Xが首位です(W)。YをD上回ります。` — Verb am Ende, Vergleichsgröße mit を statt „als“. Als
+Verkettung fester Bausteine ließe sich das nicht bauen.
+
+Der Umschalter oben im Kopffenster schreibt beides fort, Speicher und Adresse. Der Teilen-Link
+nimmt die Suchzeichenfolge mit, der Zustand steckt weiter 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 notwendig: ein Satz ist
+nicht die Verkettung seiner Teile. Stellung, Numerus und Rektion hängen an der Sprache, und
+`'mehr als ' + nom` funktioniert nur, solange beide Sprachen denselben Satzbau haben. Deshalb
+bekommen die Funktionen **Rohwerte** — Zahlen, keine fertigen Textstücke — und formatieren
+selbst über `f` (`f.eur`, `f.pct`, `f.nf2`, …). Sichtbar wird der Unterschied etwa im Fazit:
+das Deutsche braucht dort einen Genitiv (`der bAV`), das Englische eine 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.<src>:<key>.label|hint|unit|o<wert>`,
+die Optionen also unter ihrem *Wert*, nicht unter ihrem Index — dann bleibt die Zuordnung
+richtig, wenn eine Option dazukommt. `FIELDS`, `OPTS` und `METRICS` tragen 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**, greift Deutsch; fehlt auch der, erscheint der Schlüssel selbst im
+Klartext. Ein stiller Leerstring wäre die schlechtere Wahl — er verschwindet unbemerkt.
+
+**Zahlen.** Umgeschaltet wird nur die Zifferngruppierung — `de` und `la` → `de-DE`,
+`en` → `en-GB`, `ja` → `ja-JP`; die Währung bleibt überall der nachgestellte Euro:
+`75.000,00 €` bzw. `75,000.00 €`. Die Eingabe nimmt **beide**
+Schreibweisen an, damit ein Sprachwechsel keine getippte Zahl entwertet. Die Regel in
+`parseNum`: stehen beide Zeichen im Text, ist das rechte das Dezimalzeichen; steht nur eines
+und folgen ihm genau drei Ziffern, ist es die Tausendergruppe der aktuellen Sprache
+(`GRUPPEN`: `.` für de und la, `,` für en und ja). Damit
+bleibt allein `1,234` mehrdeutig — und genau dort entscheidet die Sprache.
+
+**Was ein Sprachwechsel nicht anfasst:** die Eingaben, den Referenzstand und die Ergebnisse.
+`setLang` baut nur die Teile neu, deren Beschriftungen beim Aufbau festgeschrieben werden
+(Kennzahlenleiste, Registerkarten, Felder, Fenstertitel); alles Übrige zeichnet `refresh()`
+ohnehin bei jedem Durchgang. Der Referenzstand merkt sich deshalb den *Feldschlüssel* und
+nicht den fertigen Satz — sonst stünde nach dem Wechsel „vor der Änderung von …“ noch in der
+alten Sprache da.
+
+**Prüfung.** `pruefe.js` (Entwicklungswerkzeug, wird vom Service Worker nicht ausgeliefert) lädt die Seite kopflos in
+jsdom, schaltet alle vier Sprachen 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 erlaubten Fachbegriffen, kein sichtbar gebliebener Schlüssel, und
+— die eigentliche Invariante —
+**identische Rechenergebnisse in allen vier Sprachen**.
+
## 4. Prüfung
Der Kern ist gegen die Excel-Mappe geprüft, sechs unabhängige Fälle, jeweils rund 20 Aggregate:
@@ -111,6 +197,10 @@ Der Kern ist gegen die Excel-Mappe geprüft, sechs unabhängige Fälle, jeweils
| **AVD verrentet** | 5,2 · 10⁻¹⁵ |
| **AVD verrentet + 30 % Einmalbetrag** | 3,6 · 10⁻¹⁵ |
| **beide Produkte verrentet, Splitting, PKV, andere Zeitachse, 2 Kinder** | 4,4 · 10⁻¹⁵ |
+| **fester AG-Zuschuss 100 €/Monat** | exakt (< 10⁻⁹ auf allen Jahreswerten) |
+| **fester Zuschuss 400 €/Monat, 4-%-Topf erschöpft** | exakt |
+| **fester Zuschuss mit Mindestschwelle, ober- und unterhalb** | exakt |
+| **Mindestschwelle + Modus 2 (Bisektion über die Sprungstelle)** | exakt |
> Der Prüfanker ist **erhalten geblieben**: `build_bav.py` wurde für die Depotverrentung
> mitgezogen (neue Eingaben, drei neue Spalten im Blatt `Auszahlung`, zweite Memo-Zeile im
@@ -177,6 +267,13 @@ Die Testskripte liegen unter `outputs/tests/`, `./tests/alle.sh` fährt alles du
sättigt; der Monatsbeitrag meldet das Überschreiten der 4-%- und der 8-%-Grenze der
Beitragsbemessungsgrenze RV. Beides sind Schwellen, an denen der Regler seine Wirkung
verliert oder die Rechtslage wechselt — ohne Hinweis dreht man ratlos weiter.
+- **Fester Arbeitgeberzuschuss** (Regler „Fester Zuschuss zusätzlich“, darunter der Schalter
+ für die Dynamisierung, unter „Weitere Angaben“ die Mindest-Eigenleistung). Tarifvertragliche
+ Festbeträge — Deutsche Bahn und viele andere — hängen nicht am Umwandlungsbetrag und stehen
+ neben den 15 % des § 1a Abs. 1a BetrAVG. Der Regler meldet, wenn der Festbetrag den 4-%-Topf
+ des § 1 Abs. 1 S. 1 Nr. 9 SvEV vorrangig belegt und dadurch die eigene Umwandlung verdrängt,
+ und warnt oberhalb von 4 % der BBG-RV (2026: 338 €/Monat), wo das Modell die dann fällige
+ Beitragspflicht des Überhangs bewusst nicht gegenrechnet.
- **Klartext-Fazit** in einem Satz: wer vorn liegt, um wie viel, und welcher Posten des
Wasserfalls den Abstand hauptsächlich trägt. Beschreibend formuliert, nicht empfehlend.
Angehängt ein Belastbarkeitstest über ±1 Prozentpunkt Bruttorendite, der ausdrücklich sagt,