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

@@ -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;
}