Ramener les ligatures « œ » et « æ » à « oe » et « ae »

L'Œuvre de Zola, que la BnF écrit avec la ligature, était introuvable à
qui tape « oeuvre » : NFD sépare les accents mais laisse les ligatures.

Table explicite plutôt que NFKD, qui aurait aussi transformé les exposants,
les chiffres romains et les espaces insécables. Une normalisation de
recherche doit rester prévisible.

Sept colonnes normalisées en dépendent, dont cinq portent une unicité. Le
rattrapage au démarrage est donc étendu aux envies, séries, revues et
numéros — qui ne calculaient leurs formes qu'à l'écriture — et refuse toute
collision AVANT d'écrire : sinon l'exception tomberait au démarrage et le
serveur ne se lancerait plus.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mathieu
2026-08-19 22:25:59 +02:00
co-authored by Claude Opus 5
parent ca0a9dc18c
commit b97cf33494
7 changed files with 293 additions and 36 deletions
+39
View File
@@ -797,6 +797,45 @@ Deux formes cohabitent sur `Auteur`, et ce n'est pas une redondance :
La clé ne sait pas rapprocher les **initiales** (`P.F. Hamilton``Peter F. Hamilton`) : cela demande d'aligner les mots un à un, ce qui n'a pas d'équivalent SQL. Ce cas est traité en mémoire par `RapprochementAuteurs.Comparer`, sur une table qui compte au plus quelques centaines de lignes.
### Ligatures : « œ » vaut « oe » — corrigé le 2026-08-19
`NormalisationTexte` décompose en **NFD**, qui sépare les accents mais **laisse les ligatures
intactes** : `L'Œuvre` et `L'oeuvre` ne se rencontraient jamais. Zola a écrit *L'Œuvre*, que la
BnF orthographie avec la ligature — le livre était donc introuvable à qui tape « oeuvre », et
n'apparaissait pas grisé dans la bibliographie de son auteur.
**Table explicite plutôt que NFKD**, qui aurait fait bien davantage : `²``2`, `Ⅻ``XII`,
espaces insécables, formes de présentation. Une normalisation de recherche doit rester
prévisible : on ne défait que ce dont le besoin est constaté, soit `œ`/`Œ` et `æ`/`Æ`.
⚠️ **La ligature vaut deux lettres, elle ne coupe pas le mot** : `cœur``coeur`, pas
`co eur`. La ponctuation, elle, sépare toujours (`P.F.``p f`).
#### Changer cette fonction déplace des invariants en base
C'est ce qui avait fait repousser la correction, et le risque était réel : **sept colonnes
normalisées** en dépendent, dont **trois portent une unicité** (`Auteur.CleRegroupement`,
`LivreSouhaite (Utilisateur, TitreNormalise, AuteurNormalise)`, `Serie.TitreNormalise`,
`Revue.TitreNormalise`, `NumeroRevue (RevueId, NumeroNormalise)`).
`ServiceRenormalisation` a donc été étendu aux tables apparues après lui — envies, séries,
revues, numéros —, qui calculaient leurs formes **à l'écriture** et que rien ne rattrapait.
⚠️ **Une collision d'unicité au démarrage empêcherait le serveur de se lancer.** Si la nouvelle
règle rend identiques deux lignes qui ne l'étaient pas (« L'Œuvre » et « L'oeuvre »), l'écriture
échoue — et elle échoue *avant* que l'application ne réponde. Le service détecte donc la
collision avant d'écrire : **la ligne la plus ancienne prend la nouvelle forme, les suivantes
gardent l'ancienne**, et un avertissement est journalisé. Mal normalisée vaut infiniment mieux
que supprimée, ou qu'un serveur mort.
Le jeu des clés occupées part de l'état **actuel** de la base, et chaque ligne **libère la
sienne** avant de réserver la nouvelle : sans cette libération, toute ligne verrait sa nouvelle
valeur « déjà prise » dès qu'elle égale son ancienne, et rien ne serait jamais corrigé. Deux
tests couvrent le cas de collision et l'idempotence.
Les auteurs, eux, sont **fusionnés** et non laissés en double : c'est le comportement déjà en
place pour les variantes d'accent, et il vaut pour les ligatures sans rien changer.
### Reprise des données existantes
La migration recopie l'ancien contenu avec les moyens du bord, puis **`ServiceRenormalisation` finit le travail en C# au démarrage** — idempotent, il sert aussi de filet si les règles de normalisation changent un jour.