From cffebd78db7df90525acb7b503c39ba5656e1984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 17 Jul 2026 23:03:19 +0200 Subject: [PATCH] fix(mental-health): crisis card no longer sends AT/CH users DE-only numbers The PHQ-9 item-9 crisis card routed every "de" locale to the Germany-only TelefonSeelsorge freephone lines. Those numbers don't connect from Austria or Switzerland, so a Swiss or Austrian user in crisis was shown dead numbers first on the one surface where that costs the most. Add dedicated Austria (Telefonseelsorge 142) and Switzerland (Die Dargebotene Hand 143) resource sets. `User.locale` only ever stores a bare short code today, so an unqualified "de" now resolves to a combined DE/AT/CH set (112 first, then every country's own line) instead of defaulting to Germany; a region-qualified tag resolves to the exact country when one is available. --- messages/de.json | 6 +++ messages/en.json | 6 +++ messages/es.json | 6 +++ messages/fr.json | 6 +++ messages/it.json | 6 +++ messages/pl.json | 6 +++ src/lib/mental-health/crisis-resources.ts | 49 ++++++++++++++++++++++- 7 files changed, 84 insertions(+), 1 deletion(-) diff --git a/messages/de.json b/messages/de.json index 4346d1d38..9690017a4 100644 --- a/messages/de.json +++ b/messages/de.json @@ -8042,6 +8042,12 @@ "nummerGegenKummer": { "name": "Nummer gegen Kummer (für junge Menschen)" }, + "telefonSeelsorgeAt": { + "name": "Telefonseelsorge Österreich (rund um die Uhr, kostenlos, vertraulich)" + }, + "dargeboteneHand": { + "name": "Die Dargebotene Hand (rund um die Uhr, kostenlos, vertraulich)" + }, "krisenchat": { "name": "krisenchat (24/7-Chat, junge Menschen)" }, diff --git a/messages/en.json b/messages/en.json index b0f6e29ea..024f48eb3 100644 --- a/messages/en.json +++ b/messages/en.json @@ -8042,6 +8042,12 @@ "nummerGegenKummer": { "name": "Nummer gegen Kummer (for young people)" }, + "telefonSeelsorgeAt": { + "name": "Telefonseelsorge Österreich (24/7, free, confidential)" + }, + "dargeboteneHand": { + "name": "Die Dargebotene Hand (24/7, free, confidential)" + }, "krisenchat": { "name": "krisenchat (24/7 chat, young people)" }, diff --git a/messages/es.json b/messages/es.json index 80274cf85..0c376d378 100644 --- a/messages/es.json +++ b/messages/es.json @@ -8042,6 +8042,12 @@ "nummerGegenKummer": { "name": "Nummer gegen Kummer (para jóvenes)" }, + "telefonSeelsorgeAt": { + "name": "Telefonseelsorge Österreich (24/7, gratuito y confidencial)" + }, + "dargeboteneHand": { + "name": "Die Dargebotene Hand (24/7, gratuito y confidencial)" + }, "krisenchat": { "name": "krisenchat (chat 24/7, para jóvenes)" }, diff --git a/messages/fr.json b/messages/fr.json index efe4d56b1..f2e8009e9 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -8042,6 +8042,12 @@ "nummerGegenKummer": { "name": "Nummer gegen Kummer (pour les jeunes)" }, + "telefonSeelsorgeAt": { + "name": "Telefonseelsorge Österreich (24h/24, 7j/7, gratuit et confidentiel)" + }, + "dargeboteneHand": { + "name": "Die Dargebotene Hand (24h/24, 7j/7, gratuit et confidentiel)" + }, "krisenchat": { "name": "krisenchat (chat 24h/24, 7j/7, pour les jeunes)" }, diff --git a/messages/it.json b/messages/it.json index 2c077a936..03d0645d5 100644 --- a/messages/it.json +++ b/messages/it.json @@ -8042,6 +8042,12 @@ "nummerGegenKummer": { "name": "Nummer gegen Kummer (per i giovani)" }, + "telefonSeelsorgeAt": { + "name": "Telefonseelsorge Österreich (24/7, gratuito e riservato)" + }, + "dargeboteneHand": { + "name": "Die Dargebotene Hand (24/7, gratuito e riservato)" + }, "krisenchat": { "name": "krisenchat (chat 24/7, per i giovani)" }, diff --git a/messages/pl.json b/messages/pl.json index b84d2954b..63cefc5e2 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -8042,6 +8042,12 @@ "nummerGegenKummer": { "name": "Nummer gegen Kummer (dla młodych ludzi)" }, + "telefonSeelsorgeAt": { + "name": "Telefonseelsorge Österreich (całodobowo, bezpłatnie i poufnie)" + }, + "dargeboteneHand": { + "name": "Die Dargebotene Hand (całodobowo, bezpłatnie i poufnie)" + }, "krisenchat": { "name": "krisenchat (czat całodobowy, dla młodych ludzi)" }, diff --git a/src/lib/mental-health/crisis-resources.ts b/src/lib/mental-health/crisis-resources.ts index 808341979..bd3743977 100644 --- a/src/lib/mental-health/crisis-resources.ts +++ b/src/lib/mental-health/crisis-resources.ts @@ -49,6 +49,45 @@ const DE: CrisisResourceSet = { ], }; +/** Austria (at) — Telefonseelsorge Österreich + acute emergency. */ +const AT: CrisisResourceSet = { + emergencyNumber: "112", + resources: [ + { id: "telefonSeelsorgeAt", contacts: ["142", "telefonseelsorge.at"] }, + { id: "findahelpline", contacts: ["findahelpline.com"] }, + ], +}; + +/** Switzerland (ch) — Die Dargebotene Hand + acute emergency. */ +const CH: CrisisResourceSet = { + emergencyNumber: "112", + resources: [ + { id: "dargeboteneHand", contacts: ["143", "143.ch"] }, + { id: "findahelpline", contacts: ["findahelpline.com"] }, + ], +}; + +/** + * Combined DE/AT/CH set — used when the locale is the bare "de" code with no + * region hint. `User.locale` in this app is a short code ("de"/"en"/…), so a + * de-AT or de-CH self-hoster is otherwise indistinguishable from a de-DE one. + * Serving the Germany-only freephone numbers to them left a Swiss or + * Austrian user in crisis staring at numbers that don't connect from their + * country. Leads with 112 (works across all three), then every country's + * own line grouped together so nothing here is presented as DE-only. + */ +const DE_AT_CH: CrisisResourceSet = { + emergencyNumber: "112", + resources: [ + // Country-specific lines first, each set's own `findahelpline` entry + // dropped so the worldwide directory appears exactly once, at the end. + ...DE.resources.filter((r) => r.id !== "findahelpline"), + ...AT.resources.filter((r) => r.id !== "findahelpline"), + ...CH.resources.filter((r) => r.id !== "findahelpline"), + { id: "findahelpline", contacts: ["findahelpline.com"] }, + ], +}; + /** United States (en-US region hint) — 988 + Crisis Text Line. */ const US: CrisisResourceSet = { emergencyNumber: "911", @@ -63,12 +102,20 @@ const US: CrisisResourceSet = { * Resolve a crisis-resource set from the user's locale. Region detection is * coarse (locale prefix) and defaults to the international set — the goal is to * always surface SOMETHING actionable, never to be exhaustive. + * + * A region-qualified tag ("de-AT", "de_CH", …) resolves to the exact country + * set when the caller has one to give us. `User.locale` today only ever + * stores the bare short code, so in practice every "de" hits the DE_AT_CH + * branch below — that is the safe default for an unqualified "de": never + * assume Germany when the region is unknown. */ export function crisisResourcesForLocale( locale: string | null | undefined, ): CrisisResourceSet { const lc = (locale ?? "").toLowerCase(); - if (lc.startsWith("de")) return DE; + if (lc === "de-at" || lc === "de_at" || lc === "at") return AT; + if (lc === "de-ch" || lc === "de_ch" || lc === "ch") return CH; + if (lc.startsWith("de")) return DE_AT_CH; if (lc === "en-us" || lc.startsWith("en_us") || lc === "us") return US; return INTERNATIONAL; }