All checks were successful
PR Preview / test (pull_request) Has been skipped
Deploy Production / test (push) Successful in 6s
PR Preview / teardown-preview (pull_request) Successful in 14s
PR Preview / deploy-preview (pull_request) Has been skipped
Test / unit-test (push) Successful in 6s
Test / build-check (push) Successful in 4s
Deploy Production / deploy (push) Successful in 6s
Test / e2e-test (push) Successful in 53s
单元测试256个全部通过(新增14个): - recipeNameEn: 11个翻译测试 - 重复精油检查: 3个 后端: 补充"缓解"翻译词条 E2E: 改名重翻译、删除用户去重跳过 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
113 lines
5.3 KiB
Python
113 lines
5.3 KiB
Python
"""Auto-translate Chinese recipe names to English using keyword dictionary."""
|
|
|
|
# Common keywords in essential oil recipe names
|
|
_KEYWORDS = {
|
|
# Body parts
|
|
'头': 'Head', '头疗': 'Scalp Therapy', '头皮': 'Scalp', '头发': 'Hair',
|
|
'脸': 'Face', '面部': 'Face', '眼': 'Eye', '眼部': 'Eye',
|
|
'鼻': 'Nose', '鼻腔': 'Nasal', '耳': 'Ear',
|
|
'颈': 'Neck', '颈椎': 'Cervical', '肩': 'Shoulder', '肩颈': 'Neck & Shoulder',
|
|
'背': 'Back', '腰': 'Lower Back', '腰椎': 'Lumbar',
|
|
'胸': 'Chest', '腹': 'Abdomen', '腹部': 'Abdominal',
|
|
'手': 'Hand', '脚': 'Foot', '足': 'Foot', '膝': 'Knee', '关节': 'Joint',
|
|
'皮肤': 'Skin', '肌肤': 'Skin', '毛孔': 'Pore',
|
|
'乳腺': 'Breast', '子宫': 'Uterine', '私密': 'Intimate',
|
|
'淋巴': 'Lymph', '肝': 'Liver', '肾': 'Kidney', '脾': 'Spleen', '胃': 'Stomach',
|
|
'肺': 'Lung', '心': 'Heart', '肠': 'Intestinal',
|
|
'带脉': 'Belt Meridian', '经络': 'Meridian',
|
|
|
|
# Symptoms & conditions
|
|
'酸痛': 'Pain Relief', '疼痛': 'Pain Relief', '止痛': 'Pain Relief',
|
|
'感冒': 'Cold', '发烧': 'Fever', '咳嗽': 'Cough', '咽喉': 'Throat',
|
|
'过敏': 'Allergy', '鼻炎': 'Rhinitis', '哮喘': 'Asthma',
|
|
'湿疹': 'Eczema', '痘痘': 'Acne', '粉刺': 'Acne',
|
|
'炎症': 'Anti-Inflammatory', '消炎': 'Anti-Inflammatory',
|
|
'便秘': 'Constipation', '腹泻': 'Diarrhea', '消化': 'Digestion',
|
|
'失眠': 'Insomnia', '助眠': 'Sleep Aid', '好眠': 'Sleep Well', '安眠': 'Sleep',
|
|
'焦虑': 'Anxiety', '抑郁': 'Depression', '情绪': 'Emotional',
|
|
'压力': 'Stress', '放松': 'Relaxation', '舒缓': 'Soothing',
|
|
'头痛': 'Headache', '偏头痛': 'Migraine',
|
|
'水肿': 'Edema', '浮肿': 'Swelling',
|
|
'痛经': 'Menstrual Pain', '月经': 'Menstrual', '经期': 'Menstrual',
|
|
'更年期': 'Menopause', '荷尔蒙': 'Hormone',
|
|
'结节': 'Nodule', '囊肿': 'Cyst',
|
|
'灰指甲': 'Nail Fungus', '脚气': 'Athlete\'s Foot',
|
|
'白发': 'Gray Hair', '脱发': 'Hair Loss', '生发': 'Hair Growth',
|
|
'瘦身': 'Slimming', '减肥': 'Weight Loss', '纤体': 'Body Sculpting',
|
|
'紫外线': 'UV', '晒伤': 'Sunburn', '防晒': 'Sun Protection',
|
|
'抗衰': 'Anti-Aging', '抗皱': 'Anti-Wrinkle', '美白': 'Whitening',
|
|
'补水': 'Hydrating', '保湿': 'Moisturizing',
|
|
'排毒': 'Detox', '清洁': 'Cleansing', '净化': 'Purifying',
|
|
'驱蚊': 'Mosquito Repellent', '驱虫': 'Insect Repellent',
|
|
|
|
# Actions & methods
|
|
'护理': 'Care', '调理': 'Therapy', '修复': 'Repair', '养护': 'Nourish',
|
|
'按摩': 'Massage', '刮痧': 'Gua Sha', '拔罐': 'Cupping', '艾灸': 'Moxibustion',
|
|
'泡脚': 'Foot Soak', '泡澡': 'Bath', '精油浴': 'Oil Bath',
|
|
'热敷': 'Hot Compress', '冷敷': 'Cold Compress', '敷面': 'Face Mask',
|
|
'喷雾': 'Spray', '滚珠': 'Roll-On', '扩香': 'Diffuser',
|
|
'涂抹': 'Topical', '吸嗅': 'Inhalation',
|
|
'疏通': 'Unblock', '提升': 'Boost', '增强': 'Enhance', '促进': 'Promote',
|
|
'预防': 'Prevention', '改善': 'Improve',
|
|
'祛湿': 'Dampness Relief', '驱寒': 'Warming',
|
|
'化痰': 'Phlegm Relief', '健脾': 'Spleen Wellness',
|
|
'化湿': 'Dampness Clear', '缓解': 'Relief',
|
|
|
|
# Beauty
|
|
'美容': 'Beauty', '美发': 'Hair Care', '美体': 'Body Care',
|
|
'面膜': 'Face Mask', '发膜': 'Hair Mask', '眼霜': 'Eye Cream',
|
|
'精华': 'Serum', '乳液': 'Lotion', '洗发': 'Shampoo',
|
|
|
|
# General
|
|
'配方': 'Blend', '方': 'Blend', '包': 'Blend',
|
|
'增强版': 'Enhanced', '高配版': 'Premium', '基础版': 'Basic',
|
|
'男士': 'Men\'s', '女士': 'Women\'s', '儿童': 'Children\'s', '宝宝': 'Baby',
|
|
'日常': 'Daily', '夜间': 'Night', '早晨': 'Morning',
|
|
'呼吸': 'Respiratory', '呼吸系统': 'Respiratory System',
|
|
'免疫': 'Immunity', '免疫力': 'Immunity',
|
|
'细胞': 'Cellular', '律动': 'Rhythm',
|
|
}
|
|
|
|
# Longer keys first for greedy matching
|
|
_SORTED_KEYS = sorted(_KEYWORDS.keys(), key=len, reverse=True)
|
|
|
|
|
|
def auto_translate(name: str) -> str:
|
|
"""Translate a Chinese recipe name to English using keyword matching."""
|
|
if not name:
|
|
return ''
|
|
remaining = name.strip()
|
|
parts = []
|
|
i = 0
|
|
while i < len(remaining):
|
|
matched = False
|
|
for key in _SORTED_KEYS:
|
|
if remaining[i:i+len(key)] == key:
|
|
en = _KEYWORDS[key]
|
|
if en not in parts: # avoid duplicates
|
|
parts.append(en)
|
|
i += len(key)
|
|
matched = True
|
|
break
|
|
if not matched:
|
|
# Skip numbers, punctuation, and unrecognized chars
|
|
ch = remaining[i]
|
|
if ch.isascii() and ch.isalpha():
|
|
# Collect consecutive ASCII chars
|
|
j = i
|
|
while j < len(remaining) and remaining[j].isascii() and remaining[j].isalpha():
|
|
j += 1
|
|
word = remaining[i:j]
|
|
if word not in parts:
|
|
parts.append(word)
|
|
i = j
|
|
else:
|
|
i += 1
|
|
|
|
if parts:
|
|
result = ' '.join(parts)
|
|
# Title case each word but preserve apostrophes (Men's not Men'S)
|
|
return ' '.join(w[0].upper() + w[1:] if w else w for w in result.split())
|
|
# Fallback: return original name
|
|
return name
|