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.
This commit is contained in:
Marc-André Bombeck committed 2026-07-17 23:12:12 +02:00
1 parent 8c0b200a5b
commit cffebd78db
7 files changed
+84 -1

No files matched your search

+6
View File
@@ -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)"
},
+6
View File
@@ -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)"
},
+6
View File
@@ -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)"
},
+6
View File
@@ -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)"
},
+6
View File
@@ -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)"
},
+6
View File
@@ -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)"
},
+48 -1
View File
@@ -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;
}