feat(mental-health): crisis contacts for South Korea

Korean, and any locale naming the region kr, resolves to 119 and the national suicide prevention line 109 instead of the international set.
This commit is contained in:
Marc-André Bombeck committed 2026-11-10 18:34:00 +01:00
1 parent d53eb1ec76
commit 2dfcadbea1
13 files changed
+77 -2

No files matched your search

+6
View File
@@ -17,6 +17,12 @@
keeps whichever style it has. `PATCH /api/cycle/feed-subscription`
accepts `forecastStyle` (`EXACT`, `MARGIN` or `BAND`) and the status
carries it. Migration `0495_cycle_feed_forecast_style`. (#1350)
- **Crisis contacts for South Korea.** A questionnaire answer that shows
the crisis card now gives a Korean reader, or anyone whose locale names
South Korea, the emergency number 119 and the national suicide
prevention line 109, which answers around the clock. Before, Korean
fell through to the international set with 112, which reaches the
police there, not an ambulance.
## [1.47.1] — 2026-11-07
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Belgien, rund um die Uhr, kostenlos, anonym)"
},
"suicidePrevention109": {
"name": "Suizidpräventions-Telefon 109 (Südkorea, rund um die Uhr, kostenlos)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Belgium, 24/7, free, anonymous)"
},
"suicidePrevention109": {
"name": "Suicide prevention line 109 (South Korea, 24/7, free)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Bélgica, 24 horas, gratuito, anónimo)"
},
"suicidePrevention109": {
"name": "Línea de prevención del suicidio 109 (Corea del Sur, 24 horas, gratuita)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Belgique, 24h/24, 7j/7, gratuit et anonyme)"
},
"suicidePrevention109": {
"name": "Ligne de prévention du suicide 109 (Corée du Sud, 24 h/24, gratuite)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Belgio, 24 ore su 24, gratuito, anonimo)"
},
"suicidePrevention109": {
"name": "Linea di prevenzione del suicidio 109 (Corea del Sud, 24 ore su 24, gratuita)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (벨기에, 24시간, 무료, 익명)"
},
"suicidePrevention109": {
"name": "자살예방상담전화 109 (24시간, 무료)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (België, dag en nacht, gratis, anoniem)"
},
"suicidePrevention109": {
"name": "Zelfmoordpreventielijn 109 (Zuid-Korea, dag en nacht, gratis)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Belgia, całą dobę, bezpłatnie, anonimowo)"
},
"suicidePrevention109": {
"name": "Telefon zapobiegania samobójstwom 109 (Korea Południowa, całodobowo, bezpłatnie)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Bélgica, 24 horas, gratuito, anônimo)"
},
"suicidePrevention109": {
"name": "Linha de prevenção do suicídio 109 (Coreia do Sul, 24 horas, gratuita)"
}
},
"instrumentDescription": {
+3
View File
@@ -11509,6 +11509,9 @@
},
"zelfmoordlijn1813": {
"name": "Zelfmoordlijn 1813 (Бельгия, круглосуточно, бесплатно, анонимно)"
},
"suicidePrevention109": {
"name": "Линия профилактики самоубийств 109 (Южная Корея, круглосуточно, бесплатно)"
}
},
"instrumentDescription": {
@@ -86,6 +86,21 @@ describe("crisisResourcesForLocale", () => {
}
});
it("gives a Korean reader 119 and the 109 suicide prevention line", () => {
for (const locale of ["ko", "ko-KR", "ko_KR", "kr", "en-KR"]) {
const set = crisisResourcesForLocale(locale);
expect(set.emergencyNumber, locale).toBe("119");
expect(set.resources, locale).toEqual([
{ id: "suicidePrevention109", contacts: ["109"] },
{ id: "findahelpline", contacts: ["findahelpline.com"] },
]);
}
const { t } = getServerTranslator("ko");
expect(
t("mentalHealth.crisisResource.suicidePrevention109.name"),
).toContain("109");
});
it("resolves the country from the region subtag whatever the language", () => {
const cases: Array<[string, string]> = [
["en-BE", "zelfmoordlijn1813"],
@@ -143,6 +158,7 @@ describe("crisisResourcesForLocale", () => {
"en-US",
"fr",
"nl",
"ko",
].flatMap((l) => crisisResourcesForLocale(l).resources.map((r) => r.id)),
);
for (const locale of locales) {
+25 -2
View File
@@ -178,6 +178,20 @@ const BE: CrisisResourceSet = {
],
};
/**
* South Korea (the region "kr", and Korean with no region, which is read
* almost only there). 119 is the emergency number for an ambulance. Since
* January 2024 the national suicide prevention line 109 has taken over the
* earlier counselling numbers and answers around the clock.
*/
const KR: CrisisResourceSet = {
emergencyNumber: "119",
resources: [
{ id: "suicidePrevention109", contacts: ["109"] },
{ id: "findahelpline", contacts: ["findahelpline.com"] },
],
};
/**
* Dutch with no region signal. The app ships one Dutch bundle, `nl`, read in
* the Netherlands and in Flanders alike, and the account keeps no country to
@@ -205,6 +219,7 @@ const BY_REGION: Readonly<Record<string, CrisisResourceSet>> = {
br: BR,
ch: CH,
de: DE,
kr: KR,
nl: NL,
pt: PT,
us: US,
@@ -235,7 +250,7 @@ function regionSubtag(tag: string): string | null {
* bundle (see PT_BR_AMBIGUOUS), so it keeps the ambiguous set. The web stores
* the app locale, which is otherwise a bare "de", "nl", "en", so it lands on
* the combined sets: never assume Germany, the Netherlands or Brazil when the
* region is unknown. A bare country code ("at", "ch", "us", "br", "be")
* region is unknown. A bare country code ("at", "ch", "us", "br", "be", "kr")
* still resolves to that country.
*/
export function crisisResourcesForLocale(
@@ -248,7 +263,14 @@ export function crisisResourcesForLocale(
const byRegion = BY_REGION[region];
if (byRegion) return byRegion;
}
if (lc === "at" || lc === "ch" || lc === "us" || lc === "br" || lc === "be") {
if (
lc === "at" ||
lc === "ch" ||
lc === "us" ||
lc === "br" ||
lc === "be" ||
lc === "kr"
) {
return BY_REGION[lc];
}
const language = lc.split("-")[0];
@@ -258,5 +280,6 @@ export function crisisResourcesForLocale(
if (language === "pt") return PT_BR_AMBIGUOUS;
// The bare "nl" the web stores, and any other Dutch tag: both countries.
if (language === "nl") return NL_BE;
if (language === "ko") return KR;
return INTERNATIONAL;
}