Fold the side-effect tag through the shared helper

The three locale matchers were built in parallel and each grew its own
fold. Two of them are the same function: the side-effect tag fold and
foldForMatch agree character for character, so one now calls the other.

The third stays. foldLabel decomposes with NFKD, maps sharp s to ss and
joins with underscores; foldForMatch decomposes with NFD, leaves sharp s
alone and joins with spaces. That is a disagreement about who typed the
text, not an accident: one side of a lab comparison is a shipped label
retyped or prose a lab printed, where tolerating a different spelling
claims more than the fold can prove, while someone naming a metric to an
assistant is composing rather than reproducing. Both docblocks now say
so and name the other.
This commit is contained in:
Marc-André Bombeck committed 2026-08-23 14:58:51 +02:00
1 parent 5f8af25815
commit 4f2c90b66c
2 files changed
+21 -8

No files matched your search

+18
View File
@@ -18,6 +18,24 @@
* Client-safe: no message bundles are imported here, so a client component may
* use these. Building an index OVER the bundles is a server concern and lives
* in `./shared-resolve`.
*
* ## Why there is a second fold, and when to reach for it
*
* `./localised-label-index` carries `foldLabel`, and the two disagree ON
* PURPOSE rather than by accident. That one decomposes with NFKD, maps "ß" to
* "ss" and "œ" to "oe", and joins with "_"; this one decomposes with NFD,
* leaves "ß" alone, and joins with spaces.
*
* The difference is who typed the text. Here the other side of the comparison
* is a shipped label a person retyped, or prose a lab printed, so tolerating a
* DIFFERENT SPELLING would be reaching beyond what the fold can honestly
* claim. There, someone is naming a metric to an assistant in their own words,
* and "Suessstoff" for "Süßstoff" is the same request; the wider fold earns
* its keep because the caller is composing, not reproducing.
*
* Keep them apart. Whichever you pick, apply it to BOTH sides of the
* comparison — a fold on one side only is an exact-string match in a
* disguise.
*/
/** Curly, modifier and backtick apostrophes a keyboard or word processor emits. */
+3 -8
View File
@@ -21,6 +21,8 @@
* therefore lives server-side in `./glp1-side-effect-tag-match`.
*/
import { foldForMatch } from "@/lib/i18n/fold-for-match";
/**
* The catalogue, in display order. `key` is the stable machine value that
* crosses the API and the Coach prompt; `labelKey` is the i18n key the chip
@@ -85,14 +87,7 @@ export const GLP1_SIDE_EFFECT_TAG_LABEL_KEYS: Record<
* the label the matcher indexes.
*/
export function normaliseSideEffectTag(raw: string): string {
return raw
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[\u2018\u2019\u02bc'`]/g, " ")
.replace(/[-_/]/g, " ")
.replace(/\s+/g, " ")
.trim();
return foldForMatch(raw);
}
/**