feat: expand ingredient-alias seed list to ~137 entries, ignore accents in name matching (v0.86.0)

Ingredient-alias matching (pantry, can-cook, auto-deduct, shopping-list generation) now covers common bilingual EN/FR ingredients across all 8 grocery categories, up from ~10 staples.

Also: matching now ignores accents as well as case (NFD-normalize + strip combining marks) in both the alias resolver (lib/ingredient-match.ts) and the older name-fallback matcher (pantry-shopping-match.ts) — "café"/"Café"/"cafe" and "Épinard"/"epinard" all recognize as the same ingredient without needing every accent variant manually listed as an alias.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Arnaud
2026-07-24 19:07:57 +02:00
parent 4ae0bd580e
commit b243cc3b8b
9 changed files with 206 additions and 39 deletions
+158 -15
View File
@@ -1,22 +1,165 @@
import { db } from "./client";
import { tierDefinitions, ingredients } from "./schema";
// Starter set of canonical ingredients + common EN/FR synonyms, so pantry
// items and recipe ingredients written differently ("sel", "sel fin", "sel
// de table", "table salt") can still be recognized as the same thing (see
// lib/ingredient-match.ts). Deliberately small — grows over time as gaps
// are found, not meant to be exhaustive on day one.
// Canonical ingredients + common EN/FR synonyms, so pantry items and recipe
// ingredients written differently ("sel", "sel fin", "sel de table", "table
// salt") can still be recognized as the same thing (see
// lib/ingredient-match.ts). Broad everyday-cooking coverage, not exhaustive —
// grows over time via Admin -> Ingredients or by editing this list (safe to
// add more and re-run; onConflictDoNothing on name).
const STAPLE_INGREDIENTS: { name: string; aliases: string[]; category: string }[] = [
{ name: "salt", aliases: ["sel", "sel fin", "sel de table", "table salt", "fine salt", "sea salt", "sel de mer"], category: "spicesCondiments" },
{ name: "sugar", aliases: ["sucre", "sucre blanc", "white sugar", "granulated sugar", "sucre en poudre"], category: "pantry" },
{ name: "black pepper", aliases: ["pepper", "poivre", "poivre noir", "ground pepper", "poivre moulu"], category: "spicesCondiments" },
{ name: "flour", aliases: ["farine", "all-purpose flour", "farine de blé", "plain flour", "wheat flour"], category: "pantry" },
{ name: "butter", aliases: ["beurre", "unsalted butter", "beurre doux", "salted butter", "beurre demi-sel"], category: "dairyEggs" },
{ name: "milk", aliases: ["lait", "whole milk", "lait entier", "lait demi-écrémé"], category: "dairyEggs" },
{ name: "egg", aliases: ["eggs", "œuf", "oeuf", "œufs", "oeufs"], category: "dairyEggs" },
{ name: "onion", aliases: ["oignon", "oignons", "yellow onion", "onions"], category: "produce" },
{ name: "garlic", aliases: ["ail", "garlic clove", "gousse d'ail", "garlic cloves"], category: "produce" },
{ name: "olive oil", aliases: ["huile d'olive", "extra virgin olive oil", "huile d'olive vierge extra"], category: "pantry" },
// Produce
{ name: "onion", aliases: ["onions", "yellow onion", "oignon", "oignons"], category: "produce" },
{ name: "red onion", aliases: ["red onions", "oignon rouge", "oignons rouges"], category: "produce" },
{ name: "shallot", aliases: ["shallots", "échalote", "échalotes", "echalote", "echalotes"], category: "produce" },
{ name: "scallion", aliases: ["scallions", "green onion", "green onions", "spring onion", "oignon vert", "oignons verts", "ciboule"], category: "produce" },
{ name: "garlic", aliases: ["garlic clove", "garlic cloves", "ail", "gousse d'ail", "gousses d'ail"], category: "produce" },
{ name: "ginger", aliases: ["fresh ginger", "gingembre"], category: "produce" },
{ name: "carrot", aliases: ["carrots", "carotte", "carottes"], category: "produce" },
{ name: "celery", aliases: ["celery stalk", "celery stalks", "céleri", "celeri", "branche de céleri"], category: "produce" },
{ name: "potato", aliases: ["potatoes", "pomme de terre", "pommes de terre"], category: "produce" },
{ name: "sweet potato", aliases: ["sweet potatoes", "patate douce", "patates douces"], category: "produce" },
{ name: "tomato", aliases: ["tomatoes", "tomate", "tomates"], category: "produce" },
{ name: "cherry tomato", aliases: ["cherry tomatoes", "tomate cerise", "tomates cerises"], category: "produce" },
{ name: "cucumber", aliases: ["cucumbers", "concombre", "concombres"], category: "produce" },
{ name: "zucchini", aliases: ["zucchinis", "courgette", "courgettes"], category: "produce" },
{ name: "bell pepper", aliases: ["bell peppers", "poivron", "poivrons", "poivron rouge", "poivron vert"], category: "produce" },
{ name: "chili pepper", aliases: ["chili", "chile", "chilli", "piment", "piments"], category: "produce" },
{ name: "broccoli", aliases: ["brocoli"], category: "produce" },
{ name: "cauliflower", aliases: ["chou-fleur", "chou fleur"], category: "produce" },
{ name: "spinach", aliases: ["épinard", "épinards", "epinard", "epinards"], category: "produce" },
{ name: "lettuce", aliases: ["laitue"], category: "produce" },
{ name: "kale", aliases: ["chou kale"], category: "produce" },
{ name: "cabbage", aliases: ["chou"], category: "produce" },
{ name: "mushroom", aliases: ["mushrooms", "champignon", "champignons"], category: "produce" },
{ name: "avocado", aliases: ["avocados", "avocat", "avocats"], category: "produce" },
{ name: "lemon", aliases: ["lemons", "citron", "citrons"], category: "produce" },
{ name: "lime", aliases: ["limes", "citron vert", "citrons verts"], category: "produce" },
{ name: "orange", aliases: ["oranges", "orange fruit"], category: "produce" },
{ name: "apple", aliases: ["apples", "pomme", "pommes"], category: "produce" },
{ name: "banana", aliases: ["bananas", "banane", "bananes"], category: "produce" },
{ name: "leek", aliases: ["leeks", "poireau", "poireaux"], category: "produce" },
{ name: "fresh basil", aliases: ["basil", "basilic"], category: "produce" },
{ name: "fresh parsley", aliases: ["parsley", "persil"], category: "produce" },
{ name: "fresh cilantro", aliases: ["cilantro", "coriander leaves", "coriandre fraîche", "coriandre"], category: "produce" },
{ name: "fresh mint", aliases: ["mint", "menthe"], category: "produce" },
{ name: "fresh thyme", aliases: ["thyme", "thym"], category: "produce" },
{ name: "fresh rosemary", aliases: ["rosemary", "romarin"], category: "produce" },
// Dairy & eggs
{ name: "butter", aliases: ["unsalted butter", "salted butter", "beurre", "beurre doux", "beurre demi-sel"], category: "dairyEggs" },
{ name: "milk", aliases: ["whole milk", "lait", "lait entier", "lait demi-écrémé"], category: "dairyEggs" },
{ name: "egg", aliases: ["eggs", "œuf", "œufs", "oeuf", "oeufs"], category: "dairyEggs" },
{ name: "heavy cream", aliases: ["whipping cream", "crème fraîche épaisse", "crème entière", "creme fraiche"], category: "dairyEggs" },
{ name: "sour cream", aliases: ["crème aigre"], category: "dairyEggs" },
{ name: "plain yogurt", aliases: ["yogurt", "yoghurt", "yaourt", "yaourt nature"], category: "dairyEggs" },
{ name: "cheddar cheese", aliases: ["cheddar", "cheddar cheese grated"], category: "dairyEggs" },
{ name: "parmesan cheese", aliases: ["parmesan", "parmigiano"], category: "dairyEggs" },
{ name: "mozzarella cheese", aliases: ["mozzarella"], category: "dairyEggs" },
{ name: "feta cheese", aliases: ["feta"], category: "dairyEggs" },
{ name: "goat cheese", aliases: ["fromage de chèvre", "chevre"], category: "dairyEggs" },
{ name: "cream cheese", aliases: ["fromage à tartiner", "philadelphia"], category: "dairyEggs" },
{ name: "ricotta cheese", aliases: ["ricotta"], category: "dairyEggs" },
// Meat & seafood
{ name: "chicken breast", aliases: ["chicken breasts", "blanc de poulet", "escalope de poulet"], category: "meatSeafood" },
{ name: "chicken thigh", aliases: ["chicken thighs", "cuisse de poulet", "cuisses de poulet"], category: "meatSeafood" },
{ name: "whole chicken", aliases: ["poulet entier", "poulet"], category: "meatSeafood" },
{ name: "ground beef", aliases: ["minced beef", "bœuf haché", "boeuf hache", "viande hachée"], category: "meatSeafood" },
{ name: "beef steak", aliases: ["steak", "steak de bœuf", "bifteck"], category: "meatSeafood" },
{ name: "ground pork", aliases: ["minced pork", "porc haché"], category: "meatSeafood" },
{ name: "pork chop", aliases: ["pork chops", "côte de porc", "côtes de porc"], category: "meatSeafood" },
{ name: "bacon", aliases: ["lardons", "lardon"], category: "meatSeafood" },
{ name: "sausage", aliases: ["sausages", "saucisse", "saucisses"], category: "meatSeafood" },
{ name: "ham", aliases: ["jambon"], category: "meatSeafood" },
{ name: "salmon", aliases: ["saumon"], category: "meatSeafood" },
{ name: "tuna", aliases: ["thon"], category: "meatSeafood" },
{ name: "shrimp", aliases: ["prawns", "crevette", "crevettes"], category: "meatSeafood" },
{ name: "cod", aliases: ["morue", "cabillaud"], category: "meatSeafood" },
{ name: "mussels", aliases: ["moule", "moules"], category: "meatSeafood" },
{ name: "tofu", aliases: ["tofu firme"], category: "meatSeafood" },
// Bakery
{ name: "bread", aliases: ["pain"], category: "bakery" },
{ name: "baguette", aliases: ["french baguette"], category: "bakery" },
{ name: "tortilla", aliases: ["tortillas", "wrap", "wraps"], category: "bakery" },
{ name: "pita bread", aliases: ["pita", "pain pita"], category: "bakery" },
{ name: "breadcrumbs", aliases: ["bread crumbs", "chapelure", "panko"], category: "bakery" },
{ name: "puff pastry", aliases: ["pâte feuilletée", "pate feuilletee"], category: "bakery" },
{ name: "pie crust", aliases: ["pâte brisée", "pate brisee"], category: "bakery" },
// Frozen
{ name: "frozen peas", aliases: ["peas", "petits pois", "petits pois surgelés"], category: "frozen" },
{ name: "frozen corn", aliases: ["corn", "maïs", "mais", "maïs surgelé"], category: "frozen" },
{ name: "ice cream", aliases: ["glace"], category: "frozen" },
// Pantry
{ name: "sugar", aliases: ["white sugar", "granulated sugar", "sucre", "sucre blanc", "sucre en poudre"], category: "pantry" },
{ name: "brown sugar", aliases: ["sucre roux", "sucre brun", "cassonade"], category: "pantry" },
{ name: "flour", aliases: ["all-purpose flour", "plain flour", "wheat flour", "farine", "farine de blé"], category: "pantry" },
{ name: "olive oil", aliases: ["extra virgin olive oil", "huile d'olive", "huile d'olive vierge extra"], category: "pantry" },
{ name: "vegetable oil", aliases: ["cooking oil", "sunflower oil", "huile végétale", "huile de tournesol"], category: "pantry" },
{ name: "rice", aliases: ["white rice", "riz", "riz blanc"], category: "pantry" },
{ name: "pasta", aliases: ["spaghetti", "penne", "pâtes", "pates"], category: "pantry" },
{ name: "couscous", aliases: ["couscous grains"], category: "pantry" },
{ name: "quinoa", aliases: ["quinoa grains"], category: "pantry" },
{ name: "lentils", aliases: ["lentil", "lentilles", "lentille"], category: "pantry" },
{ name: "chickpeas", aliases: ["chickpea", "garbanzo beans", "pois chiches", "pois chiche"], category: "pantry" },
{ name: "black beans", aliases: ["haricots noirs"], category: "pantry" },
{ name: "kidney beans", aliases: ["red beans", "haricots rouges"], category: "pantry" },
{ name: "canned tomatoes", aliases: ["diced tomatoes", "tomates en conserve", "tomates concassées"], category: "pantry" },
{ name: "tomato paste", aliases: ["concentré de tomate", "concentre de tomate"], category: "pantry" },
{ name: "tomato sauce", aliases: ["sauce tomate", "coulis de tomate"], category: "pantry" },
{ name: "vegetable stock", aliases: ["vegetable broth", "bouillon de légumes", "bouillon legumes"], category: "pantry" },
{ name: "chicken stock", aliases: ["chicken broth", "bouillon de poulet"], category: "pantry" },
{ name: "beef stock", aliases: ["beef broth", "bouillon de bœuf", "bouillon de boeuf"], category: "pantry" },
{ name: "baking powder", aliases: ["levure chimique"], category: "pantry" },
{ name: "baking soda", aliases: ["bicarbonate of soda", "bicarbonate de soude", "bicarbonate"], category: "pantry" },
{ name: "yeast", aliases: ["active dry yeast", "levure de boulanger", "levure boulangère"], category: "pantry" },
{ name: "vanilla extract", aliases: ["vanilla", "extrait de vanille", "vanille"], category: "pantry" },
{ name: "honey", aliases: ["miel"], category: "pantry" },
{ name: "maple syrup", aliases: ["sirop d'érable", "sirop derable"], category: "pantry" },
{ name: "peanut butter", aliases: ["beurre de cacahuète", "beurre de cacahuete"], category: "pantry" },
{ name: "coconut milk", aliases: ["lait de coco"], category: "pantry" },
{ name: "chocolate chips", aliases: ["pépites de chocolat", "pepites de chocolat"], category: "pantry" },
{ name: "dark chocolate", aliases: ["chocolat noir"], category: "pantry" },
{ name: "cornstarch", aliases: ["corn starch", "cornflour", "maïzena", "maizena", "fécule de maïs"], category: "pantry" },
{ name: "soy sauce", aliases: ["sauce soja", "sauce soya"], category: "pantry" },
{ name: "vinegar", aliases: ["white vinegar", "vinaigre", "vinaigre blanc"], category: "pantry" },
{ name: "balsamic vinegar", aliases: ["vinaigre balsamique"], category: "pantry" },
{ name: "almonds", aliases: ["almond", "amande", "amandes"], category: "pantry" },
{ name: "walnuts", aliases: ["walnut", "noix"], category: "pantry" },
{ name: "raisins", aliases: ["raisin", "raisins secs"], category: "pantry" },
// Spices & condiments
{ name: "salt", aliases: ["table salt", "fine salt", "sea salt", "sel", "sel fin", "sel de table", "sel de mer"], category: "spicesCondiments" },
{ name: "black pepper", aliases: ["pepper", "ground pepper", "poivre", "poivre noir", "poivre moulu"], category: "spicesCondiments" },
{ name: "paprika", aliases: ["paprika doux"], category: "spicesCondiments" },
{ name: "cumin", aliases: ["ground cumin", "cumin moulu", "cumin poudre"], category: "spicesCondiments" },
{ name: "cinnamon", aliases: ["ground cinnamon", "cannelle", "cannelle moulue"], category: "spicesCondiments" },
{ name: "nutmeg", aliases: ["muscade", "noix de muscade"], category: "spicesCondiments" },
{ name: "chili powder", aliases: ["piment en poudre", "poudre de piment"], category: "spicesCondiments" },
{ name: "cayenne pepper", aliases: ["cayenne", "poivre de cayenne"], category: "spicesCondiments" },
{ name: "turmeric", aliases: ["curcuma"], category: "spicesCondiments" },
{ name: "curry powder", aliases: ["curry", "poudre de curry"], category: "spicesCondiments" },
{ name: "bay leaf", aliases: ["bay leaves", "laurier", "feuille de laurier"], category: "spicesCondiments" },
{ name: "oregano", aliases: ["origan"], category: "spicesCondiments" },
{ name: "dried thyme", aliases: ["thym séché", "thym sec"], category: "spicesCondiments" },
{ name: "dried basil", aliases: ["basilic séché"], category: "spicesCondiments" },
{ name: "mustard", aliases: ["dijon mustard", "moutarde", "moutarde de dijon"], category: "spicesCondiments" },
{ name: "ketchup", aliases: ["tomato ketchup", "ketchup tomate"], category: "spicesCondiments" },
{ name: "mayonnaise", aliases: ["mayo", "mayonnaise sauce"], category: "spicesCondiments" },
{ name: "hot sauce", aliases: ["sauce piquante"], category: "spicesCondiments" },
{ name: "garlic powder", aliases: ["ail en poudre", "poudre d'ail"], category: "spicesCondiments" },
{ name: "onion powder", aliases: ["oignon en poudre", "poudre d'oignon"], category: "spicesCondiments" },
// Beverages
{ name: "coffee", aliases: ["ground coffee", "café", "cafe"], category: "beverages" },
{ name: "tea", aliases: ["thé", "the"], category: "beverages" },
{ name: "orange juice", aliases: ["jus d'orange", "jus dorange"], category: "beverages" },
{ name: "red wine", aliases: ["vin rouge"], category: "beverages" },
{ name: "white wine", aliases: ["vin blanc"], category: "beverages" },
{ name: "sparkling water", aliases: ["eau gazeuse", "eau pétillante"], category: "beverages" },
];
async function seed() {