Anglicize tippen's codebase and finish pending UI/curriculum cleanup

- Rename all German identifiers, types, mode ids, file names, CSS classes
  and data-attributes to English throughout tippen/src; only user-facing
  text (lesson titles, word lists, labels, spoken praise) stays German.
- Add a word/nonsense-word list to the "Übung: die Grundstellung" home-row
  lesson in the curriculum.
- Remove the unused HandHint component and speech.ts, and carry forward
  the in-progress App.tsx/component/generator/progress edits from other
  sessions.
- Refresh the regenerated music-library cache index.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-12 00:07:18 +02:00
parent f97de193d8
commit 498243af46
38 changed files with 1425 additions and 1599 deletions

View File

@@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest";
import {
FINGERS,
GRUNDSTELLUNG,
HOME_ROW,
KEYBOARD_ROWS,
fingerOf,
handOf,
@@ -23,9 +23,9 @@ describe("fingerOf", () => {
for (const key of ALPHABET) {
// "ß".toUpperCase() is "SS" - two characters, and not a key. `event.key` never
// reports that, so the single-character case is the one that has to hold.
const gross = key.toUpperCase();
if ([...gross].length !== 1) continue;
expect(fingerOf(gross)?.id, gross).toBe(fingerOf(key)?.id);
const upper = key.toUpperCase();
if ([...upper].length !== 1) continue;
expect(fingerOf(upper)?.id, upper).toBe(fingerOf(key)?.id);
}
});
@@ -33,44 +33,44 @@ describe("fingerOf", () => {
for (const key of ["Enter", "F1", "€", ""]) expect(fingerOf(key)).toBeNull();
});
it("assigns the Grundstellung to the eight home fingers, left to right", () => {
it("assigns the home row to the eight home fingers, left to right", () => {
const expected = [
"links-klein",
"links-ring",
"links-mitte",
"links-zeige",
"rechts-zeige",
"rechts-mitte",
"rechts-ring",
"rechts-klein",
"left-pinky",
"left-ring",
"left-middle",
"left-index",
"right-index",
"right-middle",
"right-ring",
"right-pinky",
];
GRUNDSTELLUNG.forEach((key, i) => expect(fingerOf(key)?.id).toBe(expected[i]));
HOME_ROW.forEach((key, i) => expect(fingerOf(key)?.id).toBe(expected[i]));
});
it("gives each finger the home key it actually rests on", () => {
for (const key of GRUNDSTELLUNG) expect(homeKeyOf(key)).toBe(key);
for (const key of HOME_ROW) expect(homeKeyOf(key)).toBe(key);
expect(homeKeyOf(" ")).toBe(" ");
});
it("sends the two index fingers to their stretch keys", () => {
for (const key of "rtfgvb") expect(fingerOf(key)?.id).toBe("links-zeige");
for (const key of "zuhjnm") expect(fingerOf(key)?.id).toBe("rechts-zeige");
for (const key of "rtfgvb") expect(fingerOf(key)?.id).toBe("left-index");
for (const key of "zuhjnm") expect(fingerOf(key)?.id).toBe("right-index");
});
});
describe("hands", () => {
it("splits the letters into two disjoint, non-empty sets", () => {
const links = [...ALPHABET].filter((key) => handOf(key) === "links");
const rechts = [...ALPHABET].filter((key) => handOf(key) === "rechts");
expect(links.length).toBeGreaterThan(0);
expect(rechts.length).toBeGreaterThan(0);
expect(links.length + rechts.length).toBe(ALPHABET.length);
expect(links.some((key) => rechts.includes(key))).toBe(false);
const left = [...ALPHABET].filter((key) => handOf(key) === "left");
const right = [...ALPHABET].filter((key) => handOf(key) === "right");
expect(left.length).toBeGreaterThan(0);
expect(right.length).toBeGreaterThan(0);
expect(left.length + right.length).toBe(ALPHABET.length);
expect(left.some((key) => right.includes(key))).toBe(false);
});
it("shifts with the opposite hand", () => {
expect(shiftHandFor("a")).toBe("rechts");
expect(shiftHandFor("l")).toBe("links");
expect(shiftHandFor("a")).toBe("right");
expect(shiftHandFor("l")).toBe("left");
expect(shiftHandFor("Enter")).toBeNull();
});
});
@@ -80,8 +80,8 @@ describe("rows", () => {
for (const key of ALPHABET) expect(rowOf(key), key).not.toBeNull();
});
it("has the Grundstellung in the Grundreihe", () => {
for (const key of GRUNDSTELLUNG) expect(rowOf(key)).toBe("grund");
it("has the home row in the home row", () => {
for (const key of HOME_ROW) expect(rowOf(key)).toBe("home");
});
it("draws three rows, each with keys", () => {