mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
The PHQ-9, GAD-7, WHO-5 and SCI now have text in every app language instead of falling back to the English original. Each instrument and language is one file under src/lib/mental-health/wording/ that declares what it is: a published validated translation reproduced word for word, with its source and terms in `source`, or a translation written for HealthLog, faithful to the English and on the same scale. Validated versions added: the Pfizer PHQ-9 for France, the Netherlands, Korea and Brazil, the Pfizer GAD-7 for the Netherlands, Korea and Brazil, the PRU Dutch WHO-5, the Korean WHO-5 validation (J Korean Geriatr Psychiatry 2010) and the Polish SCI validation (Sci Rep 2026). The SCI in the other languages and the WHO-5 in Brazilian Portuguese carry HealthLog's own translation; each file names any validated version found and why it is not used. Where the text is unvalidated, the check-in shows a note that the result is orientation and a one-tap switch to the English original. Each language loads as its own chunk when a questionnaire surface needs it. The item text, answers, stems and the PHQ-9 follow-up leave every message bundle, so a translator never sees them; the i18n guard now requires that no bundle carries them, and the registry test requires every instrument in every language with the item count and anchor scores the scoring expects. CONTRIBUTING explains where the wording lives and how to propose a validated version.
57 lines
2.2 KiB
TypeScript
57 lines
2.2 KiB
TypeScript
/**
|
|
* How a surface reads questionnaire text out of one language's wording: the
|
|
* answer label of an item, the stem above it. Data-free, so a client surface
|
|
* imports it without pulling every language in; the text itself comes from
|
|
* `./wording/load.ts` on the client and `./wording/resolve.ts` on the server.
|
|
*
|
|
* Every instrument has wording in every app language (`./wording/`). Where a
|
|
* validated translation is published, that translation is reproduced word for
|
|
* word; where none is, a translation written for HealthLog stands in, and the
|
|
* surfaces show a note beside it with a one-tap switch to the English
|
|
* original. The text never lives in `messages/*.json`, so a translator editing
|
|
* the bundles cannot reword an item by accident (`i18n-locale-integrity.test.ts`
|
|
* holds every bundle clear of it).
|
|
*/
|
|
import { localeFromLanguageTag, type Locale } from "@/lib/i18n/config";
|
|
|
|
import { INSTRUMENTS, type InstrumentId } from "./instruments";
|
|
import { SINGLE_ANCHOR_GROUP, type InstrumentWording } from "./wording/types";
|
|
|
|
/**
|
|
* The app language whose questionnaire text a reader of `locale` is shown;
|
|
* a language the app does not ship reads the English original.
|
|
*/
|
|
export function wordingLocale(locale: string): Locale {
|
|
return localeFromLanguageTag(locale) ?? "en";
|
|
}
|
|
|
|
/** Instruments whose form carries the unscored functional follow-up. */
|
|
export function hasFunctionalItem(id: InstrumentId): boolean {
|
|
return id === "PHQ9";
|
|
}
|
|
|
|
/** The anchor group an item's answers come from. */
|
|
export function anchorGroup(id: InstrumentId, itemIndex: number): string {
|
|
return INSTRUMENTS[id].optionGroups?.[itemIndex] ?? SINGLE_ANCHOR_GROUP;
|
|
}
|
|
|
|
/** The label of answer `value` to item `itemIndex`. */
|
|
export function anchorText(
|
|
id: InstrumentId,
|
|
wording: InstrumentWording,
|
|
itemIndex: number,
|
|
value: number,
|
|
): string {
|
|
return wording.anchors[anchorGroup(id, itemIndex)][value];
|
|
}
|
|
|
|
/** The stem the source form prints above item `itemIndex`, or null. */
|
|
export function stemText(
|
|
id: InstrumentId,
|
|
wording: InstrumentWording,
|
|
itemIndex: number,
|
|
): string | null {
|
|
const stemId = INSTRUMENTS[id].stemIds[itemIndex];
|
|
return stemId ? (wording.stems[stemId] ?? null) : null;
|
|
}
|