- Les instructions TheMealDB numérotées sur leur propre ligne ("1\n\ntexte...\n\n2\n\ntexte...") créaient des étapes parasites ne contenant qu'un chiffre — filtrées désormais (#52).
- Un ingrédient compté sans mot d'unité dans le texte source (ex. "4 Egg Yolks") laissait l'import bloqué sur "Importer" indéfiniment, sans indication visuelle de la ligne en cause — matchUnit retombe maintenant sur l'unité générique "piece" quand une quantité a été extraite, et RecipeImportForm/RecipeFormPage surlignent désormais toute ligne dont l'unité manque, avec un message explicite (#53).
- Ajout de INGREDIENT_LABEL_SYNONYMS_EN pour reconnaître des formulations alternatives fréquentes chez les sources anglophones ("vanilla pod" en plus de "vanilla bean") sans élargir INGREDIENT_LABELS_EN à un tableau pour ses ~550 entrées (#54).
- Effet de bord découvert en vérifiant #53 de bout en bout : deux lignes source résolues vers le même ingrédient catalogue (ex. "Egg Yolks"/"Eggs" -> "Œuf") faisaient planter la création en 500 (contrainte unique recipe_id+ingredient_id) au lieu d'un 400 propre. createRecipeSchema rejette maintenant les ingredientId en double, et le formulaire d'import surligne les doublons avant même de soumettre.
Vérifié de bout en bout dans le navigateur (import réel de la recette "Flan" depuis TheMealDB, jusqu'au planning) en plus des tests ajoutés.
Closes#52, #53, #54
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Ajoute une expression régulière anglaise à chacun des 26 TechStepMapping
du catalogue (locale "en"), en plus du "fr" existant — les recettes en
anglais (TheMealDB, etc.) peuvent désormais matcher leurs étapes.
- Nouveau apps/api/src/lib/ingredient-matcher.ts : moteur de matching pur
(nom d'ingrédient, unité, quantité) contre les catalogues Ingredient/Unit,
à partir de labels anglais écrits à la main (packages/shared/src/data/
catalog-labels-en.ts — 546 INGREDIENT_LABELS_EN + 17 UNIT_LABELS_EN avec
synonymes/abréviations). Tokenise et stem naïvement les deux côtés pour
tolérer pluriels et mots descriptifs superflus ; la correspondance la
plus spécifique (le plus de mots) l'emporte en cas de recoupement.
- extractQuantity() : lit un nombre en tête de texte libre (entier,
décimal, fraction simple ou nombre mixte) pour déduire la quantité et
l'unité quand la source ne les fournit pas séparément.
- Étend recipe-translation.ts : translateRecipe(recipe, locale) résout
aussi ingredientId/unitId/quantity de chaque ligne d'ingrédient — mais
uniquement pour locale "en" (seules langue avec des labels), pour ne pas
interroger la base inutilement ni halluciner un match dans une autre
langue.
- Ajoute cup/ounce/pound au catalogue Unit (toBaseFactor réel), absents
jusqu'ici alors que très fréquents dans les recettes anglaises.
- Vérifié en conditions réelles contre TheMealDB (Teriyaki Chicken
Casserole) : 8/9 ingrédients résolus avec la bonne quantité/unité, le
seul raté ("stir-fry vegetables") étant un mélange sans entrée dédiée au
catalogue — dégradation gracieuse (unitId/ingredientId: null) comme prévu.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>