fix(i18n): drop dot and dash separators from visible strings

Every bundle value that chained facts with " · " now reads as a phrase,
a comma list or a parenthesis, in all seven locales, and the em-dash
separators in the day, documents, correlation, sharing, environment,
vaccination and Apple Health import strings become sentences or clauses.

The day view's running list names the record first, with the dose in
the name and a life event's category as a chip, and puts a quiet day
count below: "Day 4, since 31 December" instead of a dot chain. Document
meta, location periods, vaccination rows and mood crosstab rows drop
their composed dots too.

A guard walks every bundle and fails on any " · " outside a reasoned
allowlist, and on an allowlist entry that no longer needs its place.
This commit is contained in:
Marc-André Bombeck committed 2026-10-09 13:37:14 +02:00
1 parent d8a3614120
commit 94542e7f2d
39 files changed
+1027 -881

No files matched your search

@@ -757,7 +757,7 @@ describe("doctor-report surgical history section", () => {
);
const text = await extractText(bytes);
expect(text).toContain("Operationen und Eingriffe");
expect(text).toMatch(/Knee · Links/);
expect(text).toMatch(/Knee \(Links\)/);
});
it("omits the section when there is no procedure", async () => {
@@ -819,7 +819,7 @@ describe("doctor-report condition body site", () => {
it("prints the site with its side in the report's language", async () => {
const text = await render(CONDITIONS, "de");
expect(text).toContain("Körperstelle");
expect(text).toMatch(/Knee · Links/);
expect(text).toMatch(/Knee \(Links\)/);
});
it("keeps the old table when no condition names a site", async () => {
@@ -100,7 +100,7 @@ describe("readCoachCorrelations", () => {
pValue: 0.001,
qValue: 0.02,
interpretation:
"Higher time in daylight tends to go with higher next-day sleep duration in your data — a pattern worth watching, not a cause.",
"Higher time in daylight tends to go with higher next-day sleep duration in your data. It is a pattern to watch, not a cause.",
lagDays: 1,
},
],
@@ -345,7 +345,7 @@ describe("executeCoachTool", () => {
lagDays: 1,
n: 42,
r: 0.31,
note: "Higher time in daylight tends to go with higher next-day sleep duration in your data — a pattern worth watching, not a cause.",
note: "Higher time in daylight tends to go with higher next-day sleep duration in your data. It is a pattern to watch, not a cause.",
},
],
coincident: {
@@ -118,7 +118,7 @@ describe("formatRelationsBlock — cross-metric correlations, descriptive only",
const rels: RelevantCorrelation[] = [
{
interpretation:
"Higher time in daylight tends to go with higher next-day sleep duration in your data — a pattern worth watching, not a cause.",
"Higher time in daylight tends to go with higher next-day sleep duration in your data. It is a pattern to watch, not a cause.",
n: 42,
r: 0.51,
},
@@ -457,7 +457,7 @@ describe("generateMetricStatus — generation path", () => {
vi.mocked(getRelevantCorrelationsForMetric).mockResolvedValueOnce([
{
interpretation:
"Higher time in daylight tends to go with lower next-day resting heart rate in your data — a pattern worth watching, not a cause.",
"Higher time in daylight tends to go with lower next-day resting heart rate in your data. It is a pattern to watch, not a cause.",
n: 35,
r: -0.46,
},
@@ -157,8 +157,8 @@ describe("buildCoachReadStrip — the pattern line speaks the reader's language"
// A sentence that is different but wrong is still a broken page.
expect(note).toBe(
"Wenn die Symptomstärke höher liegt, scheint die Schlafdauer am " +
"Folgetag nach bisheriger Datenlage eher niedriger auszufallen — ein " +
"Muster, das Beachtung verdient, keine Ursache.",
"Folgetag nach bisheriger Datenlage eher niedriger auszufallen. Das ist " +
"ein Muster, das Beachtung verdient, keine Ursache.",
);
});
@@ -170,8 +170,8 @@ describe("buildCoachReadStrip — the pattern line speaks the reader's language"
expect(strip.driver).not.toBeNull();
expect(strip.driver!.note).toBe(
"Higher symptom severity looks like it goes with lower next-day sleep " +
"duration in your data, on the evidence so far — a pattern worth " +
"watching, not a cause.",
"duration in your data, on the evidence so far. It is a pattern " +
"to watch, not a cause.",
);
});