From f17819f1c28971807eaff174fd1e02a897822003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Wed, 11 Nov 2026 22:47:40 +0100 Subject: [PATCH] fix(settings): English addresses for the health record and checkups pages Two Settings pages had German words in their address in every language: /settings/gesundheitsakte and /settings/layout/vorsorge. They are /settings/health-record and /settings/layout/checkups now, and the old addresses (and the older /settings/sharing and /settings/vorsorge) redirect permanently, so bookmarks and links in old reports keep working; the report range a since-last-visit link carries in its query passes through. The in-app links, the tour, the command palette, the anchor forwards and the e2e specs use the new addresses, and the two message groups follow the new slugs. --- e2e/doctor-report-delegate.spec.ts | 4 ++-- e2e/doctor-report.spec.ts | 2 +- e2e/mobile-route-overflow.spec.ts | 2 +- e2e/settings-admin-one-piece.spec.ts | 4 ++-- e2e/settings-export.spec.ts | 8 ++++---- messages/de.json | 4 ++-- messages/en.json | 4 ++-- messages/es.json | 4 ++-- messages/fr.json | 4 ++-- messages/it.json | 4 ++-- messages/ko.json | 4 ++-- messages/nl.json | 4 ++-- messages/pl.json | 4 ++-- messages/pt-BR.json | 4 ++-- messages/ru.json | 4 ++-- next.config.ts | 16 ++++++++++++++-- src/__tests__/customize-shortcut-guard.test.ts | 2 +- src/__tests__/settings-legacy-routes.test.ts | 18 ++++++++++++++++++ src/components/day/since-last-visit.tsx | 2 +- .../measurement-reminders/vorsorge-section.tsx | 2 +- .../__tests__/gesundheitsakte-section.test.tsx | 10 +++++----- .../settings/__tests__/layout-groups.test.ts | 10 +++++----- .../settings/__tests__/layout-section.test.tsx | 10 +++++----- .../__tests__/section-frame-harness.tsx | 2 +- .../settings/__tests__/settings-shell.test.tsx | 16 ++++++++-------- .../settings/gesundheitsakte-section.tsx | 2 +- src/components/settings/layout-groups.ts | 7 ++++--- .../settings/settings-anchor-forward.tsx | 2 +- .../settings/settings-section-loader.tsx | 4 ++-- src/components/settings/settings-shell.tsx | 4 ++-- src/lib/command-palette/settings-cards.ts | 8 ++++---- src/lib/onboarding/tour-state.ts | 2 +- src/lib/record-settings/classification.ts | 2 +- src/lib/settings/section-slugs.ts | 9 +++++---- 34 files changed, 110 insertions(+), 78 deletions(-) diff --git a/e2e/doctor-report-delegate.spec.ts b/e2e/doctor-report-delegate.spec.ts index 6cf5db593..28a69ca88 100644 --- a/e2e/doctor-report-delegate.spec.ts +++ b/e2e/doctor-report-delegate.spec.ts @@ -8,7 +8,7 @@ * record the delegate may only read, 200 inside the one it manages. * * The UI half proves something narrower, and the file says so rather than - * implying the route's boundary twice. `/settings/gesundheitsakte` is a + * implying the route's boundary twice. `/settings/health-record` is a * PERSONAL destination: inside SOMEBODY ELSE's record the shell answers it with * the "not part of shared access" panel at every adult grant level — READ, * WRITE and MANAGE alike — so the export card is never rendered for a delegate @@ -149,7 +149,7 @@ async function leaveRecord(page: Page): Promise { * card was never offered. */ async function openGesundheitsakte(page: Page): Promise { - await page.goto("/settings/gesundheitsakte", { + await page.goto("/settings/health-record", { waitUntil: "domcontentloaded", }); await expect( diff --git a/e2e/doctor-report.spec.ts b/e2e/doctor-report.spec.ts index b8909cd2a..1f5f02e9e 100644 --- a/e2e/doctor-report.spec.ts +++ b/e2e/doctor-report.spec.ts @@ -247,7 +247,7 @@ async function openReportPanel(page: Page): Promise { response.request().method() === "GET" && new URL(response.url()).pathname === "/api/share-links", ); - await page.goto("/settings/gesundheitsakte", { + await page.goto("/settings/health-record", { waitUntil: "domcontentloaded", }); await boundaryHydrated; diff --git a/e2e/mobile-route-overflow.spec.ts b/e2e/mobile-route-overflow.spec.ts index 127ad3a3c..af82b1cc1 100644 --- a/e2e/mobile-route-overflow.spec.ts +++ b/e2e/mobile-route-overflow.spec.ts @@ -92,7 +92,7 @@ const DYNAMIC_ROUTES: Record = { "labs", "illness", "documents", - "vorsorge", + "checkups", ].map((group) => `/settings/layout/${group}`), "/settings/modules/[module]": async () => MODULE_SETTINGS_PAGE_IDS.map((module) => `/settings/modules/${module}`), diff --git a/e2e/settings-admin-one-piece.spec.ts b/e2e/settings-admin-one-piece.spec.ts index 2b8e70726..f567665f8 100644 --- a/e2e/settings-admin-one-piece.spec.ts +++ b/e2e/settings-admin-one-piece.spec.ts @@ -53,7 +53,7 @@ const SETTINGS_ROUTES = [ "/settings/sources", "/settings/environment", "/settings/export", - "/settings/gesundheitsakte", + "/settings/health-record", "/settings/privacy", "/settings/api", "/settings/mcp", @@ -76,7 +76,7 @@ const LAYOUT_CHILD_ROUTES = [ "/settings/layout/medications", "/settings/layout/labs", "/settings/layout/illness", - "/settings/layout/vorsorge", + "/settings/layout/checkups", "/settings/modules/medications", "/settings/modules/mood", "/settings/modules/labs", diff --git a/e2e/settings-export.spec.ts b/e2e/settings-export.spec.ts index 0fe1bae84..1bbcfab5c 100644 --- a/e2e/settings-export.spec.ts +++ b/e2e/settings-export.spec.ts @@ -14,7 +14,7 @@ import { STORAGE_STATE_PATH } from "./setup/global-setup"; * 2. The import surfaces (v1.15.7, issue #281) render: the Apple Health * and generic-JSON cards. * 3. The full health-record export panel lives on its own top-level - * `/settings/gesundheitsakte` section (v1.18.0 S5) — including the + * `/settings/health-record` section (v1.18.0 S5) — including the * "included data" disclosure, which a first run opens and which stays * operable in both directions. * 4. The scope picker mounts twice on that page (the export panel and the @@ -45,7 +45,7 @@ async function openGesundheitsakte(page: Page): Promise { response.request().method() === "GET" && new URL(response.url()).pathname === "/api/share-links", ); - await page.goto("/settings/gesundheitsakte", { + await page.goto("/settings/health-record", { waitUntil: "domcontentloaded", }); await boundaryHydrated; @@ -57,7 +57,7 @@ test.describe("Settings → Export & Import", () => { test("renders all export surfaces with stable testids", async ({ page }) => { await page.goto("/settings/export", { waitUntil: "domcontentloaded" }); // v1.18.0 — the full health-record export moved to its own - // `/settings/gesundheitsakte` section. The Export & Import page keeps + // `/settings/health-record` section. The Export & Import page keeps // the four CSV/backup tiles with the `export-card-*` shape. for (const id of [ "export-card-measurements-csv", @@ -250,7 +250,7 @@ test.describe("Settings → Export & Import", () => { page, }) => { // The disclosure that fronts the scope picker on - // `/settings/gesundheitsakte`. An account with no saved selection is a + // `/settings/health-record`. An account with no saved selection is a // first run, and a first run opens it: that is the only place the standard // template is applied, and a template hidden behind a closed disclosure // would be opt-out wearing a hat. diff --git a/messages/de.json b/messages/de.json index 10b553178..cce360766 100644 --- a/messages/de.json +++ b/messages/de.json @@ -5627,7 +5627,7 @@ "title": "Krankheitstagebuch", "description": "Listenansicht und Reihenfolge der Episoden." }, - "vorsorge": { + "checkups": { "title": "Vorsorge", "description": "Listenansicht und Reihenfolge der Erinnerungen." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Alles außer Reihenfolge und Ansicht findest du auf der Seite des Moduls unter Module." } }, - "gesundheitsakte": { + "health-record": { "title": "Gesundheitsakte", "subtitle": "Exportiere eine vollständige, arzttaugliche Gesundheitsakte." }, diff --git a/messages/en.json b/messages/en.json index 3ef7d027e..b55f263f8 100644 --- a/messages/en.json +++ b/messages/en.json @@ -5627,7 +5627,7 @@ "title": "Illness journal", "description": "List view and episode order." }, - "vorsorge": { + "checkups": { "title": "Checkups", "description": "List view and reminder order." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Everything beyond order and view lives on the module's page under Modules." } }, - "gesundheitsakte": { + "health-record": { "title": "Health record", "subtitle": "Export a complete, clinician-ready health record." }, diff --git a/messages/es.json b/messages/es.json index 77e17bb18..fef36b4d8 100644 --- a/messages/es.json +++ b/messages/es.json @@ -5627,7 +5627,7 @@ "title": "Diario de enfermedades", "description": "Vista de lista y orden de episodios." }, - "vorsorge": { + "checkups": { "title": "Revisiones", "description": "Vista de lista y orden de recordatorios." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Todo lo demás está en la página del módulo, en Módulos." } }, - "gesundheitsakte": { + "health-record": { "title": "Historial médico", "subtitle": "Exporta un historial de salud completo, listo para el médico." }, diff --git a/messages/fr.json b/messages/fr.json index a868039e6..b18d66500 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -5627,7 +5627,7 @@ "title": "Journal des maladies", "description": "Vue en liste et ordre des épisodes." }, - "vorsorge": { + "checkups": { "title": "Examens", "description": "Vue en liste et ordre des rappels." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Tout le reste se trouve sur la page du module, dans Modules." } }, - "gesundheitsakte": { + "health-record": { "title": "Dossier médical", "subtitle": "Exportez un dossier de santé complet, prêt pour le médecin." }, diff --git a/messages/it.json b/messages/it.json index de6ead102..d623a19c3 100644 --- a/messages/it.json +++ b/messages/it.json @@ -5627,7 +5627,7 @@ "title": "Diario delle malattie", "description": "Vista elenco e ordine degli episodi." }, - "vorsorge": { + "checkups": { "title": "Controlli", "description": "Vista elenco e ordine dei promemoria." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Tutto il resto è nella pagina del modulo, in Moduli." } }, - "gesundheitsakte": { + "health-record": { "title": "Cartella clinica", "subtitle": "Esporta una cartella clinica completa, pronta per il medico." }, diff --git a/messages/ko.json b/messages/ko.json index 8d9875804..8c086acc2 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -5627,7 +5627,7 @@ "title": "아픈 날 일지", "description": "목록 보기와 에피소드 순서." }, - "vorsorge": { + "checkups": { "title": "건강검진", "description": "목록 보기와 알림 순서." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "순서와 보기 외의 설정은 모듈의 페이지에 있습니다." } }, - "gesundheitsakte": { + "health-record": { "title": "건강 기록", "subtitle": "임상의에게 바로 건넬 수 있는 완전한 건강 기록을 내보내요." }, diff --git a/messages/nl.json b/messages/nl.json index 4bdcab77e..9210b1c8f 100644 --- a/messages/nl.json +++ b/messages/nl.json @@ -5627,7 +5627,7 @@ "title": "Ziektedagboek", "description": "Lijstweergave en volgorde van episodes." }, - "vorsorge": { + "checkups": { "title": "Preventieve controles", "description": "Lijstweergave en volgorde van herinneringen." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Al het andere staat op de pagina van de module onder Modules." } }, - "gesundheitsakte": { + "health-record": { "title": "Gezondheidsdossier", "subtitle": "Exporteer een volledig gezondheidsdossier dat klaar is voor je zorgverlener." }, diff --git a/messages/pl.json b/messages/pl.json index 53d9ed244..e4a1d7e50 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -5627,7 +5627,7 @@ "title": "Dziennik chorób", "description": "Widok listy i kolejność epizodów." }, - "vorsorge": { + "checkups": { "title": "Badania kontrolne", "description": "Widok listy i kolejność przypomnień." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Wszystko poza kolejnością i widokiem jest na stronie modułu w Modułach." } }, - "gesundheitsakte": { + "health-record": { "title": "Dokumentacja zdrowotna", "subtitle": "Eksportuj kompletną dokumentację zdrowotną gotową dla lekarza." }, diff --git a/messages/pt-BR.json b/messages/pt-BR.json index 32656f07b..ce5cec34a 100644 --- a/messages/pt-BR.json +++ b/messages/pt-BR.json @@ -5627,7 +5627,7 @@ "title": "Diário de doenças", "description": "Visualização em lista e ordem dos episódios." }, - "vorsorge": { + "checkups": { "title": "Check-ups", "description": "Visualização em lista e ordem dos lembretes." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Tudo além da ordem e da visualização fica na página do módulo, em Módulos." } }, - "gesundheitsakte": { + "health-record": { "title": "Registro de saúde", "subtitle": "Exporte um registro de saúde completo, pronto para o clínico." }, diff --git a/messages/ru.json b/messages/ru.json index fcf9c31de..5a736e6cd 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -5627,7 +5627,7 @@ "title": "Дневник болезней", "description": "Вид списка и порядок эпизодов." }, - "vorsorge": { + "checkups": { "title": "Профилактика", "description": "Вид списка и порядок напоминаний." }, @@ -6052,7 +6052,7 @@ "moduleSettingsDescription": "Всё, кроме порядка и вида, настраивается на странице модуля в разделе «Модули»." } }, - "gesundheitsakte": { + "health-record": { "title": "Медицинская карта", "subtitle": "Экспортируйте полную медицинскую карту, готовую для врача." }, diff --git a/next.config.ts b/next.config.ts index 25c5c3724..1f78d2058 100644 --- a/next.config.ts +++ b/next.config.ts @@ -230,7 +230,19 @@ const nextConfig: NextConfig = { }, { source: "/settings/vorsorge", - destination: "/settings/layout/vorsorge", + destination: "/settings/layout/checkups", + permanent: true, + }, + // The health record and checkups pages had German addresses in every + // language; the English ones replace them, and the old ones redirect. + { + source: "/settings/gesundheitsakte", + destination: "/settings/health-record", + permanent: true, + }, + { + source: "/settings/layout/vorsorge", + destination: "/settings/layout/checkups", permanent: true, }, // v1.25.7 — clinician share links fold into the Gesundheitsakte section @@ -238,7 +250,7 @@ const nextConfig: NextConfig = { // to the anchor there. { source: "/settings/sharing", - destination: "/settings/gesundheitsakte#sharing", + destination: "/settings/health-record#sharing", permanent: true, }, // v1.22.0 — the preventive-care surface moved from the German slug diff --git a/src/__tests__/customize-shortcut-guard.test.ts b/src/__tests__/customize-shortcut-guard.test.ts index 4fe9624ea..1b5e4e1a6 100644 --- a/src/__tests__/customize-shortcut-guard.test.ts +++ b/src/__tests__/customize-shortcut-guard.test.ts @@ -215,7 +215,7 @@ describe("the customise shortcut is withheld inside somebody else's record", () export function Page() { const { inSharedRecord } = useRecordCapabilities(); const wrench = !inSharedRecord ? ( - Customise + Customise ) : null; return wrench; } diff --git a/src/__tests__/settings-legacy-routes.test.ts b/src/__tests__/settings-legacy-routes.test.ts index 870b11045..1c764f5b5 100644 --- a/src/__tests__/settings-legacy-routes.test.ts +++ b/src/__tests__/settings-legacy-routes.test.ts @@ -50,6 +50,7 @@ const HISTORICAL_SETTINGS_PATHS: readonly string[] = [ "/settings/api", "/settings/mcp", "/settings/gesundheitsakte", + "/settings/health-record", "/settings/sharing", "/settings/export", "/settings/advanced", @@ -72,6 +73,7 @@ const HISTORICAL_SETTINGS_PATHS: readonly string[] = [ "/settings/layout/illness", "/settings/layout/documents", "/settings/layout/vorsorge", + "/settings/layout/checkups", ]; interface Redirect { @@ -151,6 +153,22 @@ describe("historical Settings addresses", () => { expect(unlisted).toEqual([]); }); + it("sends the old German addresses to their English ones", async () => { + const redirects = await settingsRedirects(); + expect(resolve("/settings/gesundheitsakte", redirects)).toBe( + "/settings/health-record", + ); + expect(resolve("/settings/sharing", redirects)).toBe( + "/settings/health-record", + ); + expect(resolve("/settings/layout/vorsorge", redirects)).toBe( + "/settings/layout/checkups", + ); + expect(resolve("/settings/vorsorge", redirects)).toBe( + "/settings/layout/checkups", + ); + }); + it("keeps the v1.44 moves addressable", async () => { const redirects = await settingsRedirects(); expect(resolve("/settings/layout/mood", redirects)).toBe( diff --git a/src/components/day/since-last-visit.tsx b/src/components/day/since-last-visit.tsx index 488781784..a2ffe35be 100644 --- a/src/components/day/since-last-visit.tsx +++ b/src/components/day/since-last-visit.tsx @@ -321,7 +321,7 @@ export function SinceLastVisit({ className="min-h-11 sm:min-h-9" >