feat(browser): expand cuisine taxonomy to 13 categories + 105 subcategories
- 5 new top-level categories: BBQ & Smoke, Central American, African, Pacific & Oceania, Central Asian & Caucasus - British/Irish split into British + Irish + Scottish with regional keywords - Scandinavian: dish-level keyword expansion to fix zero-count gap - Mediterranean: Israeli → Jewish (Ashkenazi/Sephardic/NY deli/z'houg/hawaiij); Palestinian, Yemeni, Egyptian, Syrian added; Moroccan moved to African - Mexican: +Baja/Cal-Mex, +Mexico City - Asian: +Hong Kong, +Cambodian, +Laotian, +Mongolian (16 subcategories) - Indian: +Bangladeshi, +Pakistani, +Sri Lankan, +Nepali (8 subcategories) - Latin American: full Caribbean depth (Jamaican, Puerto Rican, Dominican, Haitian, Trinidad); +Argentinian, +Venezuelan, +Chilean - American: +Pacific Northwest, +Hawaiian; BBQ promoted to own category - BBQ & Smoke: 8 regional styles (Texas, Carolina, KC, Memphis, Alabama, Kentucky, St. Louis, Backyard) - feat(shopping): locale_config.py — Amazon/Instacart/Walmart locale routing for multi-currency affiliate link support (#114) - chore: gitleaks allowlist for Amazon grocery dept IDs in locale_config.py
This commit is contained in:
parent
0bef082ff0
commit
69e2ca7914
3 changed files with 490 additions and 66 deletions
|
|
@ -3,6 +3,16 @@
|
|||
[extend]
|
||||
path = "/Library/Development/CircuitForge/circuitforge-hooks/gitleaks.toml"
|
||||
|
||||
# ── Global allowlist ──────────────────────────────────────────────────────────
|
||||
# Amazon grocery department IDs (rh=n:<10-digit>) false-positive as phone
|
||||
# numbers. locale_config.py is a static lookup table with no secrets.
|
||||
|
||||
[allowlist]
|
||||
# Amazon grocery dept IDs (rh=n:<digits>) false-positive as phone numbers.
|
||||
regexes = [
|
||||
'''rh=n:\d{8,12}''',
|
||||
]
|
||||
|
||||
# ── Test fixture allowlists ───────────────────────────────────────────────────
|
||||
|
||||
[[rules]]
|
||||
|
|
|
|||
|
|
@ -43,88 +43,204 @@ DOMAINS: dict[str, dict] = {
|
|||
},
|
||||
},
|
||||
"Mexican": {
|
||||
"keywords": ["mexican", "tex-mex", "taco", "enchilada", "burrito",
|
||||
"salsa", "guacamole"],
|
||||
"keywords": ["mexican", "taco", "enchilada", "burrito", "salsa",
|
||||
"guacamole", "mole", "tamale"],
|
||||
"subcategories": {
|
||||
"Oaxacan": ["oaxacan", "oaxaca", "mole negro", "tlayuda",
|
||||
"chapulines", "mezcal"],
|
||||
"chapulines", "mezcal", "tasajo", "memelas"],
|
||||
"Yucatecan": ["yucatecan", "yucatan", "cochinita pibil", "poc chuc",
|
||||
"sopa de lima", "panuchos"],
|
||||
"Veracruz": ["veracruz", "huachinango", "picadas", "enfrijoladas"],
|
||||
"Street Food": ["taco", "elote", "tlacoyos", "torta",
|
||||
"tamale", "quesadilla"],
|
||||
"sopa de lima", "panuchos", "papadzules"],
|
||||
"Veracruz": ["veracruz", "veracruzana", "huachinango",
|
||||
"picadas", "enfrijoladas", "caldo de mariscos"],
|
||||
"Street Food": ["taco", "elote", "tlacoyos", "torta", "tamale",
|
||||
"quesadilla", "tostada", "sope", "gordita"],
|
||||
"Mole": ["mole", "mole negro", "mole rojo", "mole verde",
|
||||
"mole poblano"],
|
||||
"mole poblano", "mole amarillo", "pipián"],
|
||||
"Baja / Cal-Mex": ["baja", "baja california", "cal-mex", "baja fish taco",
|
||||
"fish taco", "carne asada fries", "california burrito",
|
||||
"birria", "birria tacos", "quesabirria",
|
||||
"lobster puerto nuevo", "tijuana", "ensenada",
|
||||
"agua fresca", "caesar salad tijuana"],
|
||||
"Mexico City": ["mexico city", "chilaquiles", "tlayuda cdmx",
|
||||
"tacos de canasta", "torta ahogada", "pozole",
|
||||
"chiles en nogada"],
|
||||
},
|
||||
},
|
||||
"Asian": {
|
||||
"keywords": ["asian", "chinese", "japanese", "thai", "korean", "vietnamese",
|
||||
"stir fry", "stir-fry", "ramen", "sushi"],
|
||||
"stir fry", "stir-fry", "ramen", "sushi", "malaysian",
|
||||
"taiwanese", "singaporean", "burmese", "cambodian",
|
||||
"laotian", "mongolian", "hong kong"],
|
||||
"subcategories": {
|
||||
"Korean": ["korean", "kimchi", "bibimbap", "bulgogi", "japchae",
|
||||
"doenjang", "gochujang"],
|
||||
"doenjang", "gochujang", "tteokbokki", "sundubu",
|
||||
"galbi", "jjigae", "kbbq", "korean fried chicken"],
|
||||
"Japanese": ["japanese", "sushi", "ramen", "tempura", "miso",
|
||||
"teriyaki", "udon", "soba", "bento", "yakitori"],
|
||||
"teriyaki", "udon", "soba", "bento", "yakitori",
|
||||
"tonkatsu", "onigiri", "okonomiyaki", "takoyaki",
|
||||
"kaiseki", "izakaya"],
|
||||
"Chinese": ["chinese", "dim sum", "fried rice", "dumplings", "wonton",
|
||||
"spring roll", "szechuan", "sichuan", "cantonese",
|
||||
"chow mein", "mapo", "lo mein"],
|
||||
"chow mein", "mapo tofu", "lo mein", "hot pot",
|
||||
"peking duck", "char siu", "congee"],
|
||||
"Thai": ["thai", "pad thai", "green curry", "red curry",
|
||||
"coconut milk", "lemongrass", "satay", "tom yum"],
|
||||
"coconut milk", "lemongrass", "satay", "tom yum",
|
||||
"larb", "khao man gai", "massaman", "pad see ew"],
|
||||
"Vietnamese": ["vietnamese", "pho", "banh mi", "spring rolls",
|
||||
"vermicelli", "nuoc cham", "bun bo"],
|
||||
"vermicelli", "nuoc cham", "bun bo hue",
|
||||
"banh xeo", "com tam", "bun cha"],
|
||||
"Filipino": ["filipino", "adobo", "sinigang", "pancit", "lumpia",
|
||||
"kare-kare", "lechon"],
|
||||
"kare-kare", "lechon", "sisig", "halo-halo",
|
||||
"dinuguan", "tinola", "bistek"],
|
||||
"Indonesian": ["indonesian", "rendang", "nasi goreng", "gado-gado",
|
||||
"tempeh", "sambal"],
|
||||
"tempeh", "sambal", "soto", "opor ayam",
|
||||
"bakso", "mie goreng", "nasi uduk"],
|
||||
"Malaysian": ["malaysian", "laksa", "nasi lemak", "char kway teow",
|
||||
"satay malaysia", "roti canai", "bak kut teh",
|
||||
"cendol", "mee goreng mamak", "curry laksa"],
|
||||
"Taiwanese": ["taiwanese", "beef noodle soup", "lu rou fan",
|
||||
"oyster vermicelli", "scallion pancake taiwan",
|
||||
"pork chop rice", "three cup chicken",
|
||||
"bubble tea", "stinky tofu", "ba wan"],
|
||||
"Singaporean": ["singaporean", "chicken rice", "chili crab",
|
||||
"singaporean laksa", "bak chor mee", "rojak",
|
||||
"kaya toast", "nasi padang", "satay singapore"],
|
||||
"Burmese": ["burmese", "myanmar", "mohinga", "laphet thoke",
|
||||
"tea leaf salad", "ohn no khao swe",
|
||||
"mont di", "nangyi thoke"],
|
||||
"Hong Kong": ["hong kong", "hk style", "pineapple bun",
|
||||
"wonton noodle soup", "hk milk tea", "egg tart",
|
||||
"typhoon shelter crab", "char siu bao", "jook",
|
||||
"congee hk", "silk stocking tea", "dan tat",
|
||||
"siu mai hk", "cheung fun"],
|
||||
"Cambodian": ["cambodian", "khmer", "amok", "lok lak",
|
||||
"kuy teav", "bai sach chrouk", "nom banh chok",
|
||||
"samlor korko", "beef loc lac"],
|
||||
"Laotian": ["laotian", "lao", "larb", "tam mak hoong",
|
||||
"or lam", "khao niaw", "ping kai",
|
||||
"naem khao", "khao piak sen", "mok pa"],
|
||||
"Mongolian": ["mongolian", "buuz", "khuushuur", "tsuivan",
|
||||
"boodog", "airag", "khorkhog", "bansh",
|
||||
"guriltai shol", "suutei tsai"],
|
||||
"South Asian Fusion": ["south asian fusion", "indo-chinese",
|
||||
"hakka chinese", "chilli chicken",
|
||||
"manchurian", "schezwan"],
|
||||
},
|
||||
},
|
||||
"Indian": {
|
||||
"keywords": ["indian", "curry", "lentil", "dal", "tikka", "masala",
|
||||
"biryani", "naan", "chutney"],
|
||||
"biryani", "naan", "chutney", "pakistani", "sri lankan",
|
||||
"bangladeshi", "nepali"],
|
||||
"subcategories": {
|
||||
"North Indian": ["north indian", "punjabi", "mughal", "tikka masala",
|
||||
"naan", "tandoori", "butter chicken", "palak"],
|
||||
"naan", "tandoori", "butter chicken", "palak paneer",
|
||||
"chole", "rajma", "aloo gobi"],
|
||||
"South Indian": ["south indian", "tamil", "kerala", "dosa", "idli",
|
||||
"sambar", "rasam", "coconut chutney"],
|
||||
"Bengali": ["bengali", "mustard fish", "hilsa", "shorshe"],
|
||||
"Gujarati": ["gujarati", "dhokla", "thepla", "undhiyu"],
|
||||
"sambar", "rasam", "coconut chutney", "appam",
|
||||
"fish curry kerala", "puttu", "payasam"],
|
||||
"Bengali": ["bengali", "mustard fish", "hilsa", "shorshe ilish",
|
||||
"mishti doi", "rasgulla", "kosha mangsho"],
|
||||
"Gujarati": ["gujarati", "dhokla", "thepla", "undhiyu",
|
||||
"khandvi", "fafda", "gujarati dal"],
|
||||
"Pakistani": ["pakistani", "nihari", "haleem", "seekh kebab",
|
||||
"karahi", "biryani karachi", "chapli kebab",
|
||||
"halwa puri", "paya"],
|
||||
"Sri Lankan": ["sri lankan", "kottu roti", "hoppers", "pol sambol",
|
||||
"sri lankan curry", "lamprais", "string hoppers",
|
||||
"wambatu moju"],
|
||||
"Bangladeshi": ["bangladeshi", "bangladesh", "dhaka biryani",
|
||||
"shutki", "pitha", "hilsa curry", "kacchi biryani",
|
||||
"bhuna khichuri", "doi maach", "rezala"],
|
||||
"Nepali": ["nepali", "dal bhat", "momos", "sekuwa",
|
||||
"sel roti", "gundruk", "thukpa"],
|
||||
},
|
||||
},
|
||||
"Mediterranean": {
|
||||
"keywords": ["mediterranean", "greek", "middle eastern", "turkish",
|
||||
"moroccan", "lebanese"],
|
||||
"lebanese", "jewish", "palestinian", "yemeni", "egyptian",
|
||||
"syrian", "iraqi", "jordanian"],
|
||||
"subcategories": {
|
||||
"Greek": ["greek", "feta", "tzatziki", "moussaka", "spanakopita",
|
||||
"souvlaki", "dolmades"],
|
||||
"souvlaki", "dolmades", "spanakopita", "tiropita",
|
||||
"galaktoboureko"],
|
||||
"Turkish": ["turkish", "kebab", "borek", "meze", "baklava",
|
||||
"lahmacun"],
|
||||
"Moroccan": ["moroccan", "tagine", "couscous", "harissa",
|
||||
"chermoula", "preserved lemon"],
|
||||
"lahmacun", "menemen", "pide", "iskender",
|
||||
"kisir", "simit"],
|
||||
"Syrian": ["syrian", "fattet hummus", "kibbeh syria",
|
||||
"muhammara", "maklouba syria", "sfeeha",
|
||||
"halawet el jibn"],
|
||||
"Lebanese": ["lebanese", "middle eastern", "hummus", "falafel",
|
||||
"tabbouleh", "kibbeh", "fattoush"],
|
||||
"Israeli": ["israeli", "shakshuka", "sabich", "za'atar",
|
||||
"tahini"],
|
||||
"tabbouleh", "kibbeh", "fattoush", "manakish",
|
||||
"kafta", "sfiha"],
|
||||
"Jewish": ["jewish", "israeli", "ashkenazi", "sephardic",
|
||||
"shakshuka", "sabich", "za'atar", "tahini",
|
||||
"zhug", "zhoug", "s'khug", "z'houg",
|
||||
"hawaiij", "hawaij", "hawayej",
|
||||
"matzo", "latke", "rugelach", "babka", "challah",
|
||||
"cholent", "gefilte fish", "brisket", "kugel",
|
||||
"new york jewish", "new york deli", "pastrami",
|
||||
"knish", "lox", "bagel and lox", "jewish deli"],
|
||||
"Palestinian": ["palestinian", "musakhan", "maqluba", "knafeh",
|
||||
"maftoul", "freekeh", "sumac chicken"],
|
||||
"Yemeni": ["yemeni", "saltah", "lahoh", "bint al-sahn",
|
||||
"zhug", "zhoug", "hulba", "fahsa",
|
||||
"hawaiij", "hawaij", "hawayej"],
|
||||
"Egyptian": ["egyptian", "koshari", "molokhia", "mahshi",
|
||||
"ful medames", "ta'ameya", "feteer meshaltet"],
|
||||
},
|
||||
},
|
||||
"American": {
|
||||
"keywords": ["american", "southern", "bbq", "barbecue", "comfort food",
|
||||
"cajun", "creole"],
|
||||
"keywords": ["american", "southern", "comfort food", "cajun", "creole",
|
||||
"hawaiian", "tex-mex", "soul food"],
|
||||
"subcategories": {
|
||||
"Southern": ["southern", "soul food", "fried chicken",
|
||||
"collard greens", "cornbread", "biscuits and gravy"],
|
||||
"collard greens", "cornbread", "biscuits and gravy",
|
||||
"mac and cheese", "sweet potato pie", "okra"],
|
||||
"Cajun/Creole": ["cajun", "creole", "new orleans", "gumbo",
|
||||
"jambalaya", "etouffee", "dirty rice"],
|
||||
"BBQ": ["bbq", "barbecue", "smoked", "brisket", "pulled pork",
|
||||
"ribs", "pit"],
|
||||
"jambalaya", "etouffee", "dirty rice", "po'boy",
|
||||
"muffuletta", "red beans and rice"],
|
||||
"Tex-Mex": ["tex-mex", "southwestern", "chili", "fajita",
|
||||
"queso"],
|
||||
"queso", "breakfast taco", "chile con carne"],
|
||||
"New England": ["new england", "chowder", "lobster", "clam",
|
||||
"maple", "yankee"],
|
||||
"maple", "yankee", "boston baked beans",
|
||||
"johnnycake", "fish and chips"],
|
||||
"Pacific Northwest": ["pacific northwest", "pnw", "dungeness crab",
|
||||
"salmon", "cedar plank", "razor clam",
|
||||
"geoduck", "chanterelle", "marionberry"],
|
||||
"Hawaiian": ["hawaiian", "hawaii", "plate lunch", "loco moco",
|
||||
"poke", "spam musubi", "kalua pig", "lau lau",
|
||||
"haupia", "poi", "manapua", "garlic shrimp",
|
||||
"saimin", "huli huli", "malasada"],
|
||||
},
|
||||
},
|
||||
"BBQ & Smoke": {
|
||||
"keywords": ["bbq", "barbecue", "smoked", "pit", "smoke ring",
|
||||
"low and slow", "brisket", "pulled pork", "ribs"],
|
||||
"subcategories": {
|
||||
"Texas BBQ": ["texas bbq", "central texas bbq", "brisket",
|
||||
"beef ribs", "post oak", "salt and pepper rub",
|
||||
"east texas bbq", "lockhart", "franklin style"],
|
||||
"Carolina BBQ": ["carolina bbq", "north carolina bbq", "whole hog",
|
||||
"vinegar sauce", "lexington style", "eastern nc",
|
||||
"south carolina bbq", "mustard sauce"],
|
||||
"Kansas City BBQ": ["kansas city bbq", "kc bbq", "burnt ends",
|
||||
"sweet bbq sauce", "tomato molasses sauce",
|
||||
"baby back ribs kc"],
|
||||
"Memphis BBQ": ["memphis bbq", "dry rub ribs", "wet ribs",
|
||||
"memphis style", "dry rub pork"],
|
||||
"Alabama BBQ": ["alabama bbq", "white sauce", "alabama white sauce",
|
||||
"smoked chicken alabama"],
|
||||
"Kentucky BBQ": ["kentucky bbq", "mutton bbq", "owensboro bbq",
|
||||
"black dip", "western kentucky barbecue"],
|
||||
"St. Louis BBQ": ["st louis bbq", "st. louis ribs", "st louis cut ribs",
|
||||
"st louis style spare ribs"],
|
||||
"Backyard Grill": ["backyard bbq", "cookout", "grilled burgers",
|
||||
"charcoal grill", "kettle grill", "tailgate"],
|
||||
},
|
||||
},
|
||||
"European": {
|
||||
"keywords": ["french", "german", "spanish", "british", "irish",
|
||||
"scandinavian"],
|
||||
"keywords": ["french", "german", "spanish", "british", "irish", "scottish",
|
||||
"welsh", "scandinavian", "nordic", "eastern european"],
|
||||
"subcategories": {
|
||||
"French": ["french", "provencal", "beurre", "crepe",
|
||||
"ratatouille", "cassoulet", "bouillabaisse"],
|
||||
|
|
@ -132,26 +248,164 @@ DOMAINS: dict[str, dict] = {
|
|||
"tortilla espanola", "chorizo"],
|
||||
"German": ["german", "bratwurst", "sauerkraut", "schnitzel",
|
||||
"pretzel", "strudel"],
|
||||
"British/Irish": ["british", "irish", "english", "pub food",
|
||||
"shepherd's pie", "bangers", "scones"],
|
||||
"British": ["british", "english", "pub food", "cornish",
|
||||
"shepherd's pie", "bangers", "toad in the hole",
|
||||
"coronation chicken", "london", "londoner",
|
||||
"cornish pasty", "ploughman's"],
|
||||
"Irish": ["irish", "ireland", "colcannon", "coddle",
|
||||
"irish stew", "soda bread", "boxty", "champ"],
|
||||
"Scottish": ["scottish", "scotland", "haggis", "cullen skink",
|
||||
"cranachan", "scotch broth", "glaswegian",
|
||||
"neeps and tatties", "tablet"],
|
||||
"Scandinavian": ["scandinavian", "nordic", "swedish", "norwegian",
|
||||
"danish", "gravlax", "meatballs"],
|
||||
"danish", "finnish", "gravlax", "swedish meatballs",
|
||||
"lefse", "smörgåsbord", "fika", "crispbread",
|
||||
"cardamom bun", "herring", "æbleskiver",
|
||||
"lingonberry", "lutefisk", "janssons frestelse",
|
||||
"knäckebröd", "kladdkaka"],
|
||||
"Eastern European": ["eastern european", "polish", "russian", "ukrainian",
|
||||
"czech", "hungarian", "pierogi", "borscht",
|
||||
"goulash", "kielbasa", "varenyky", "pelmeni"],
|
||||
},
|
||||
},
|
||||
"Latin American": {
|
||||
"keywords": ["latin american", "peruvian", "argentinian", "colombian",
|
||||
"cuban", "caribbean", "brazilian"],
|
||||
"cuban", "caribbean", "brazilian", "venezuelan", "chilean"],
|
||||
"subcategories": {
|
||||
"Peruvian": ["peruvian", "ceviche", "lomo saltado", "anticucho",
|
||||
"aji amarillo"],
|
||||
"aji amarillo", "causa", "leche de tigre",
|
||||
"arroz con leche peru", "pollo a la brasa"],
|
||||
"Brazilian": ["brazilian", "churrasco", "feijoada", "pao de queijo",
|
||||
"brigadeiro"],
|
||||
"brigadeiro", "coxinha", "moqueca", "vatapa",
|
||||
"caipirinha", "acai bowl"],
|
||||
"Colombian": ["colombian", "bandeja paisa", "arepas", "empanadas",
|
||||
"sancocho"],
|
||||
"sancocho", "ajiaco", "buñuelos", "changua"],
|
||||
"Argentinian": ["argentinian", "asado", "chimichurri", "empanadas argentina",
|
||||
"milanesa", "locro", "dulce de leche", "medialunas"],
|
||||
"Venezuelan": ["venezuelan", "pabellón criollo", "arepas venezuela",
|
||||
"hallacas", "cachapas", "tequeños", "caraotas"],
|
||||
"Chilean": ["chilean", "cazuela", "pastel de choclo", "curanto",
|
||||
"sopaipillas", "charquicán", "completo"],
|
||||
"Cuban": ["cuban", "ropa vieja", "moros y cristianos",
|
||||
"picadillo", "mojito"],
|
||||
"Caribbean": ["caribbean", "jamaican", "jerk", "trinidadian",
|
||||
"plantain", "roti"],
|
||||
"picadillo", "lechon cubano", "vaca frita",
|
||||
"tostones", "platanos maduros"],
|
||||
"Jamaican": ["jamaican", "jerk chicken", "jerk pork", "ackee saltfish",
|
||||
"curry goat", "rice and peas", "escovitch",
|
||||
"jamaican patty", "callaloo jamaica", "festival"],
|
||||
"Puerto Rican": ["puerto rican", "mofongo", "pernil", "arroz con gandules",
|
||||
"sofrito", "pasteles", "tostones pr", "tembleque",
|
||||
"coquito", "asopao"],
|
||||
"Dominican": ["dominican", "mangu", "sancocho dominicano",
|
||||
"pollo guisado", "habichuelas guisadas",
|
||||
"tostones dominicanos", "morir soñando"],
|
||||
"Haitian": ["haitian", "griot", "pikliz", "riz et pois",
|
||||
"joumou", "akra", "pain patate", "labouyi"],
|
||||
"Trinidad": ["trinidadian", "doubles", "roti trinidad", "pelau",
|
||||
"callaloo trinidad", "bake and shark",
|
||||
"curry duck", "oil down"],
|
||||
},
|
||||
},
|
||||
"Central American": {
|
||||
"keywords": ["central american", "salvadoran", "guatemalan",
|
||||
"honduran", "nicaraguan", "costa rican", "panamanian"],
|
||||
"subcategories": {
|
||||
"Salvadoran": ["salvadoran", "el salvador", "pupusas", "curtido",
|
||||
"sopa de pata", "nuégados", "atol shuco"],
|
||||
"Guatemalan": ["guatemalan", "pepián", "jocon", "kak'ik",
|
||||
"hilachas", "rellenitos", "fiambre"],
|
||||
"Costa Rican": ["costa rican", "gallo pinto", "casado",
|
||||
"olla de carne", "arroz con leche cr",
|
||||
"tres leches cr"],
|
||||
"Honduran": ["honduran", "baleadas", "sopa de caracol",
|
||||
"tapado", "machuca", "catrachitas"],
|
||||
"Nicaraguan": ["nicaraguan", "nacatamal", "vigorón", "indio viejo",
|
||||
"gallo pinto nicaragua", "güirilas"],
|
||||
},
|
||||
},
|
||||
"African": {
|
||||
"keywords": ["african", "west african", "east african", "ethiopian",
|
||||
"nigerian", "ghanaian", "kenyan", "south african",
|
||||
"senegalese", "tunisian"],
|
||||
"subcategories": {
|
||||
"West African": ["west african", "nigerian", "ghanaian",
|
||||
"jollof rice", "egusi soup", "fufu", "suya",
|
||||
"groundnut stew", "kelewele", "kontomire",
|
||||
"waakye", "ofam", "bitterleaf soup"],
|
||||
"Senegalese": ["senegalese", "senegal", "thieboudienne",
|
||||
"yassa", "mafe", "thiou", "ceebu jen",
|
||||
"domoda"],
|
||||
"Ethiopian & Eritrean": ["ethiopian", "eritrean", "injera", "doro wat",
|
||||
"kitfo", "tibs", "shiro", "misir wat",
|
||||
"gomen", "ful ethiopian", "tegamino"],
|
||||
"East African": ["east african", "kenyan", "tanzanian", "ugandan",
|
||||
"nyama choma", "ugali", "sukuma wiki",
|
||||
"pilau kenya", "mandazi", "matoke",
|
||||
"githeri", "irio"],
|
||||
"North African": ["north african", "tunisian", "algerian", "libyan",
|
||||
"brik", "lablabi", "merguez", "shakshuka tunisian",
|
||||
"harissa tunisian", "couscous algerian"],
|
||||
"South African": ["south african", "braai", "bobotie", "boerewors",
|
||||
"bunny chow", "pap", "chakalaka", "biltong",
|
||||
"malva pudding", "koeksister", "potjiekos"],
|
||||
"Moroccan": ["moroccan", "tagine", "couscous morocco",
|
||||
"harissa", "chermoula", "preserved lemon",
|
||||
"pastilla", "mechoui", "bastilla"],
|
||||
},
|
||||
},
|
||||
"Pacific & Oceania": {
|
||||
"keywords": ["pacific", "oceania", "polynesian", "melanesian",
|
||||
"micronesian", "maori", "fijian", "samoan", "tongan",
|
||||
"hawaiian", "australian", "new zealand"],
|
||||
"subcategories": {
|
||||
"Māori / New Zealand": ["maori", "new zealand", "hangi", "rewena bread",
|
||||
"boil-up", "paua", "kumara", "pavlova nz",
|
||||
"whitebait fritter", "kina", "hokey pokey"],
|
||||
"Australian": ["australian", "meat pie", "lamington",
|
||||
"anzac biscuits", "damper", "barramundi",
|
||||
"vegemite", "pavlova australia", "tim tam",
|
||||
"sausage sizzle", "chiko roll", "fairy bread"],
|
||||
"Fijian": ["fijian", "fiji", "kokoda", "lovo",
|
||||
"rourou", "palusami fiji", "duruka",
|
||||
"vakalolo"],
|
||||
"Samoan": ["samoan", "samoa", "palusami", "oka",
|
||||
"fa'ausi", "chop suey samoa", "sapasui",
|
||||
"koko alaisa", "supo esi"],
|
||||
"Tongan": ["tongan", "tonga", "lu pulu", "'ota 'ika",
|
||||
"fekkai", "faikakai topai", "kapisi pulu"],
|
||||
"Papua New Guinean": ["papua new guinea", "png", "mumu",
|
||||
"sago", "aibika", "kaukau",
|
||||
"taro png", "coconut crab"],
|
||||
"Hawaiian": ["hawaiian", "hawaii", "poke", "loco moco",
|
||||
"plate lunch", "kalua pig", "haupia",
|
||||
"spam musubi", "poi", "malasada"],
|
||||
},
|
||||
},
|
||||
"Central Asian & Caucasus": {
|
||||
"keywords": ["central asian", "caucasus", "georgian", "armenian", "uzbek",
|
||||
"afghan", "persian", "iranian", "azerbaijani", "kazakh"],
|
||||
"subcategories": {
|
||||
"Persian / Iranian": ["persian", "iranian", "ghormeh sabzi", "fesenjan",
|
||||
"tahdig", "joojeh kabab", "ash reshteh",
|
||||
"zereshk polo", "khoresh", "mast o khiar",
|
||||
"kashk-e-bademjan", "mirza ghasemi",
|
||||
"baghali polo"],
|
||||
"Georgian": ["georgian", "georgia", "khachapuri", "khinkali",
|
||||
"churchkhela", "ajapsandali", "satsivi",
|
||||
"pkhali", "lobiani", "badrijani nigvzit"],
|
||||
"Armenian": ["armenian", "dolma armenia", "lahmajoun",
|
||||
"manti armenia", "ghapama", "basturma",
|
||||
"harissa armenia", "nazook", "tolma"],
|
||||
"Azerbaijani": ["azerbaijani", "azerbaijan", "plov azerbaijan",
|
||||
"dolma azeri", "dushbara", "levengi",
|
||||
"shah plov", "gutab"],
|
||||
"Uzbek": ["uzbek", "uzbekistan", "plov", "samsa",
|
||||
"lagman", "shashlik", "manti uzbek",
|
||||
"non bread", "dimlama", "sumalak"],
|
||||
"Afghan": ["afghan", "afghanistan", "kabuli pulao", "mantu",
|
||||
"bolani", "qorma", "ashak", "shorwa",
|
||||
"aushak", "borani banjan"],
|
||||
"Kazakh": ["kazakh", "beshbarmak", "kuyrdak", "baursak",
|
||||
"kurt", "shubat", "kazy"],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
160
app/services/recipe/locale_config.py
Normal file
160
app/services/recipe/locale_config.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
"""
|
||||
Shopping locale configuration.
|
||||
|
||||
Maps a locale key to Amazon domain, currency metadata, and retailer availability.
|
||||
Instacart and Walmart are US/CA-only; all other locales get Amazon only.
|
||||
Amazon Fresh (&i=amazonfresh) is US-only — international domains use the general
|
||||
grocery department (&rh=n:16310101) where available, plain search elsewhere.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
|
||||
class LocaleConfig(TypedDict):
|
||||
amazon_domain: str
|
||||
amazon_grocery_dept: str # URL fragment for grocery department on this locale's site
|
||||
currency_code: str
|
||||
currency_symbol: str
|
||||
instacart: bool
|
||||
walmart: bool
|
||||
|
||||
|
||||
LOCALES: dict[str, LocaleConfig] = {
|
||||
"us": {
|
||||
"amazon_domain": "amazon.com",
|
||||
"amazon_grocery_dept": "i=amazonfresh",
|
||||
"currency_code": "USD",
|
||||
"currency_symbol": "$",
|
||||
"instacart": True,
|
||||
"walmart": True,
|
||||
},
|
||||
"ca": {
|
||||
"amazon_domain": "amazon.ca",
|
||||
"amazon_grocery_dept": "rh=n:6967215011", # Grocery dept on .ca # gitleaks:allow
|
||||
"currency_code": "CAD",
|
||||
"currency_symbol": "CA$",
|
||||
"instacart": True,
|
||||
"walmart": False,
|
||||
},
|
||||
"gb": {
|
||||
"amazon_domain": "amazon.co.uk",
|
||||
"amazon_grocery_dept": "rh=n:340831031", # Grocery dept on .co.uk
|
||||
"currency_code": "GBP",
|
||||
"currency_symbol": "£",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"au": {
|
||||
"amazon_domain": "amazon.com.au",
|
||||
"amazon_grocery_dept": "rh=n:5765081051", # Pantry/grocery on .com.au # gitleaks:allow
|
||||
"currency_code": "AUD",
|
||||
"currency_symbol": "A$",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"nz": {
|
||||
# NZ has no Amazon storefront — route to .com.au as nearest option
|
||||
"amazon_domain": "amazon.com.au",
|
||||
"amazon_grocery_dept": "rh=n:5765081051", # gitleaks:allow
|
||||
"currency_code": "NZD",
|
||||
"currency_symbol": "NZ$",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"de": {
|
||||
"amazon_domain": "amazon.de",
|
||||
"amazon_grocery_dept": "rh=n:340843031", # Lebensmittel & Getränke
|
||||
"currency_code": "EUR",
|
||||
"currency_symbol": "€",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"fr": {
|
||||
"amazon_domain": "amazon.fr",
|
||||
"amazon_grocery_dept": "rh=n:197858031",
|
||||
"currency_code": "EUR",
|
||||
"currency_symbol": "€",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"it": {
|
||||
"amazon_domain": "amazon.it",
|
||||
"amazon_grocery_dept": "rh=n:525616031",
|
||||
"currency_code": "EUR",
|
||||
"currency_symbol": "€",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"es": {
|
||||
"amazon_domain": "amazon.es",
|
||||
"amazon_grocery_dept": "rh=n:599364031",
|
||||
"currency_code": "EUR",
|
||||
"currency_symbol": "€",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"nl": {
|
||||
"amazon_domain": "amazon.nl",
|
||||
"amazon_grocery_dept": "rh=n:16584827031",
|
||||
"currency_code": "EUR",
|
||||
"currency_symbol": "€",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"se": {
|
||||
"amazon_domain": "amazon.se",
|
||||
"amazon_grocery_dept": "rh=n:20741393031",
|
||||
"currency_code": "SEK",
|
||||
"currency_symbol": "kr",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"jp": {
|
||||
"amazon_domain": "amazon.co.jp",
|
||||
"amazon_grocery_dept": "rh=n:2246283051", # gitleaks:allow
|
||||
"currency_code": "JPY",
|
||||
"currency_symbol": "¥",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"in": {
|
||||
"amazon_domain": "amazon.in",
|
||||
"amazon_grocery_dept": "rh=n:2454178031", # gitleaks:allow
|
||||
"currency_code": "INR",
|
||||
"currency_symbol": "₹",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"mx": {
|
||||
"amazon_domain": "amazon.com.mx",
|
||||
"amazon_grocery_dept": "rh=n:10737659011",
|
||||
"currency_code": "MXN",
|
||||
"currency_symbol": "MX$",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"br": {
|
||||
"amazon_domain": "amazon.com.br",
|
||||
"amazon_grocery_dept": "rh=n:17878420011",
|
||||
"currency_code": "BRL",
|
||||
"currency_symbol": "R$",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
"sg": {
|
||||
"amazon_domain": "amazon.sg",
|
||||
"amazon_grocery_dept": "rh=n:6981647051", # gitleaks:allow
|
||||
"currency_code": "SGD",
|
||||
"currency_symbol": "S$",
|
||||
"instacart": False,
|
||||
"walmart": False,
|
||||
},
|
||||
}
|
||||
|
||||
DEFAULT_LOCALE = "us"
|
||||
|
||||
|
||||
def get_locale(key: str) -> LocaleConfig:
|
||||
"""Return locale config for *key*, falling back to US if unknown."""
|
||||
return LOCALES.get(key, LOCALES[DEFAULT_LOCALE])
|
||||
Loading…
Reference in a new issue