feat(mental-health): show Brazil's crisis line to pt-BR readers

A Brazilian Portuguese reader who answered PHQ-9 item 9 saw the
international set: 112 and two directories. They now see CVV (Centro de
Valorização da Vida), 188 by phone and the chat at cvv.org.br, free and
answering around the clock, with SAMU's 192 as the emergency number.
Both were checked against cvv.org.br and the Ministry of Health's SAMU
page. A bare "pt" or "pt-PT" keeps the international set, because 188
does not connect from Portugal.

The CVV label is translated in every bundle, and a test pins that every
resource of every locale's set resolves its label in that locale.
This commit is contained in:
Marc-André Bombeck committed 2026-10-22 15:15:48 +02:00
1 parent 36a1485b91
commit 6c15a66cde
11 files changed
+79

No files matched your search

+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (rund um die Uhr, kostenlos, vertraulich)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (24/7, free, confidential)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (24/7, gratuito y confidencial)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (24h/24, 7j/7, gratuit et confidentiel)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (24/7, gratuito e riservato)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (24시간 연중무휴, 무료, 비밀 보장)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (dag en nacht, gratis, vertrouwelijk)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (całodobowo, bezpłatnie i poufnie)"
}
},
"instrumentDescription": {
+3
View File
@@ -11069,6 +11069,9 @@
},
"crisisTextLine": {
"name": "Crisis Text Line"
},
"cvv": {
"name": "CVV, Centro de Valorização da Vida (24 horas, gratuito, sigiloso)"
}
},
"instrumentDescription": {
@@ -0,0 +1,36 @@
import { describe, expect, it } from "vitest";
import { locales } from "@/lib/i18n/config";
import { getServerTranslator } from "@/lib/i18n/server-translator";
import { crisisResourcesForLocale } from "../crisis-resources";
describe("crisisResourcesForLocale", () => {
it("gives a Brazilian Portuguese reader CVV and SAMU", () => {
const set = crisisResourcesForLocale("pt-BR");
expect(set.emergencyNumber).toBe("192");
expect(set.resources[0]).toEqual({
id: "cvv",
contacts: ["188", "cvv.org.br/chat"],
});
});
it("keeps the international set for Portuguese outside Brazil", () => {
// 188 does not connect from Portugal.
for (const locale of ["pt", "pt-PT"]) {
const set = crisisResourcesForLocale(locale);
expect(set.emergencyNumber).toBe("112");
expect(set.resources.map((r) => r.id)).not.toContain("cvv");
}
});
it("names every resource of every locale's set in that locale", () => {
for (const locale of locales) {
const { t } = getServerTranslator(locale);
for (const resource of crisisResourcesForLocale(locale).resources) {
const key = `mentalHealth.crisisResource.${resource.id}.name`;
expect(t(key), `${locale} ${key}`).not.toBe(key);
}
}
});
});
+16
View File
@@ -98,6 +98,19 @@ const US: CrisisResourceSet = {
],
};
/**
* Brazil (pt-BR) — CVV by phone and chat, SAMU as the emergency number.
* Both numbers are free and answer around the clock (cvv.org.br; the
* Ministry of Health's SAMU 192 page).
*/
const BR: CrisisResourceSet = {
emergencyNumber: "192",
resources: [
{ id: "cvv", contacts: ["188", "cvv.org.br/chat"] },
{ id: "findahelpline", contacts: ["findahelpline.com"] },
],
};
/**
* 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
@@ -117,5 +130,8 @@ export function crisisResourcesForLocale(
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;
// Brazilian Portuguese only: CVV's 188 does not connect from Portugal, so a
// bare "pt" or "pt-PT" keeps the international set.
if (lc === "pt-br" || lc === "pt_br" || lc === "br") return BR;
return INTERNATIONAL;
}