// 动作标题中文化引擎 v2 // 策略:短语词典(习语优先)→ 词元词典(大幅扩充)→ 词干归并 → 未知英文做音译兜底 // 保证 100% 中文化且无生硬英文残留;只保留数字与少数专有器械缩写(EZ/SZ/TRX/BOSU)。 import fs from 'fs'; const DATA = '/Users/wm/WorkBuddy/健身/fitness-coach/backend/src/exercises/data/exercises.json'; const PHRASES = [ ['push up', '俯卧撑'], ['pull up', '引体向上'], ['chin up', '下巴引体'], ['sit-up', '仰卧起坐'], ['pull-up', '引体向上'], ['push-up', '俯卧撑'], ['chin-up', '下巴引体'], ['bench press', '卧推'], ['incline bench', '上斜凳'], ['decline bench', '下斜凳'], ['flat bench', '平板凳'], ['chest press', '胸推'], ['shoulder press', '肩上推举'], ['overhead press', '过顶推举'], ['military press', '军用推举'], ['arnold press', '阿诺德推举'], ['landmine press', '地雷推举'], ['leg press', '腿举'], ['leg curl', '腿弯举'], ['leg extension', '腿屈伸'], ['calf raise', '提踵'], ['sit up', '仰卧起坐'], ['side bend', '侧屈'], ['v up', 'V字挺身'], ['good morning', '早安式'], ['romanian deadlift', '罗马尼亚硬拉'], ['stiff leg deadlift', '直腿硬拉'], ['sumo deadlift', '相扑硬拉'], ['hip thrust', '髋推'], ['glute bridge', '臀桥'], ['hip bridge', '臀桥'], ['wall sit', '靠墙静蹲'], ['wall ball', '墙球'], ['battle rope', '战绳'], ['mountain climber', '登山跑'], ['russian twist', '俄罗斯转体'], ['bicycle crunch', '蹬车卷腹'], ['reverse crunch', '反向卷腹'], ['cable crossover', '绳索夹胸'], ['pec deck', '夹胸器'], ['lat pulldown', '高位下拉'], ['pulldown', '下拉'], ['preacher curl', '传教士弯举'], ['hammer curl', '锤式弯举'], ['bicep curl', '二头弯举'], ['tricep extension', '三头下压'], ['triceps pushdown', '三头下压'], ['skull crusher', '仰卧臂屈伸'], ['lateral raise', '侧平举'], ['front raise', '前平举'], ['rear delt raise', '后束平举'], ['rear delt fly', '后束飞鸟'], ['face pull', '面拉'], ['kettlebell swing', '壶铃摆荡'], ['dumbbell swing', '哑铃摆荡'], ['jump squat', '深蹲跳'], ['jump lunge', '箭步蹲跳'], ['split squat', '分腿蹲'], ['bulgarian split squat', '保加利亚分腿蹲'], ['goblet squat', '高脚杯深蹲'], ['front squat', '前蹲'], ['back squat', '背蹲'], ['overhead squat', '过顶深蹲'], ['box jump', '跳箱'], ['burpee', '波比跳'], ['jumping jack', '开合跳'], ['bear crawl', '熊爬'], ['crab walk', '蟹行'], ['bird dog', '鸟狗式'], ['dead bug', '死虫式'], ['plank', '平板支撑'], ['side plank', '侧平板'], ['hollow hold', ' hollow支撑'], ['superman', '超人式'], ['resistance band', '阻力带'], ['mini band', '迷你弹力带'], ['loop band', '环形弹力带'], ['exercise ball', '健身球'], ['medicine ball', '药球'], ['stability ball', '瑞士球'], ['swiss ball', '瑞士球'], ['bosu ball', '博苏球'], ['foam roller', '泡沫轴'], ['foam roll', '泡沫轴'], ['ab wheel', '健腹轮'], ['wheel roller', '健腹轮'], ['smith machine', '史密斯机'], ['cable machine', '绳索器械'], ['ez bar', '曲杠'], ['ez barbell', '曲杠铃'], ['ez-bar', '曲杠'], ['ez-barbell', '曲杠铃'], ['pull up bar', '单杠'], ['pullup bar', '单杠'], ['parallel bars', '双杠'], ['body weight', '自重'], ['bodyweight', '自重'], ['overhand grip', '正握'], ['underhand grip', '反握'], ['neutral grip', '对握'], ['close grip', '窄握'], ['wide grip', '宽握'], ['reverse grip', '反握'], ['hammer grip', '锤式握'], ['mixed grip', '混握'], ['single leg', '单腿'], ['single arm', '单臂'], ['double leg', '双腿'], ['both legs', '双腿'], ['both arms', '双臂'], ['one leg', '单腿'], ['one arm', '单臂'], ['t bar', 'T杆'], ['t-bar', 'T杆'], ['dumbbell row', '哑铃划船'], ['barbell row', '杠铃划船'], ['incline row', '上斜划船'], ['seated row', '坐姿划船'], ['cable row', '绳索划船'], ['upright row', '直立划船'], ['inverted row', '反向划船'], ['bent over', '俯身'], ['bent-over', '俯身'], ['lying', '仰卧'], ['pullover', '过顶臂屈伸'], ['clean and press', '抓举推举'], ['clean', '抓举'], ['snatch', '挺举'], ['jerk', '上挺'], ['thruster', '推举蹲'], ['zercher squat', '泽彻深蹲'], ['pin presses', '销钉推'], ['hack squat', '哈克深蹲'], ['jefferson squat', '杰弗逊深蹲'], ['pendlay row', '彭德雷划船'], ['guillotine bench press', '断头台卧推'], ['jm bench press', '杰姆卧推'], ['rack pull', '架上拉'], ['skullcrusher', '碎颅者'], ['skull crusher', '碎颅者'], ['pin presses', '销钉推'], ['cuban press', '古巴推举'], ['scott press', '斯科特推举'], ['tate press', '泰特推举'], ['w-press', 'W推举'], ['waiter biceps curl', '侍者弯举'], ['zottman preacher curl', '佐特曼传教士弯举'], ['figure 8', '8字'], ['turkish get up', '土耳其起立'], ['pike push up', '派克俯卧撑'], ['diamond push-up', '钻石俯卧撑'], ['clap push up', '击掌俯卧撑'], ['clock push-up', '时钟俯卧撑'], ['spider curl', '蜘蛛弯举'], ['french press', '法式推举'], ['sumo pull through', '相扑穿插'], ['sissy squat', '少女深蹲'], ['cossack squats', '哥萨克深蹲'], ['pistol squat', '手枪深蹲'], ['potty squat', '幼儿深蹲'], ['frog crunch', '蛙式卷腹'], ['windmill', '风车'], ['renegade row', '叛徒划船'], ['see-saw press', '跷跷板推举'], ['gironda sternum chin', '吉龙达下胸引体'], ['world greatest stretch', '世界最佳拉伸'], ['butterfly yoga pose', '蝴蝶式瑜伽'], ['cobra', '眼镜蛇式'], ['sphinx', '狮身人面式'], ['upward facing dog', '上犬式'], ['child pose', '婴儿式'], ['pelvic tilt', '骨盆倾斜'], ['pelvic tilt into bridge', '骨盆倾斜成桥'], ['three bench dip', '三凳臂屈伸'], ['turkish get up', '土耳其起立'], ['skin the cat', '剥猫式'], ['v-bar', 'V杠'], ['sz-bar', '直杠'], ['arnold press', '阿诺德推举'], ['cuban press', '古巴推举'], ['incline t-raise', '上斜T上举'], ['cross body hammer curl', '交叉锤式弯举'], ['v sit', 'V坐'], ['rear lunge', '后箭步蹲'], ['side split squat', '侧分腿蹲'], ['side bent', '侧俯身'], ['arnold', '阿诺德'], ['cuban', '古巴'], ['decline shrug', '下斜耸肩'], ['cross body', '交叉'], ['biceps curl', '二头弯举'], ['incline curl', '上斜弯举'], ['concentration curl', '集中弯举'], ['v-up', 'V字挺身'], ['v-sit', 'V坐'], ['l-sit', 'L支撑'], ['l-pull-up', 'L引体'], ['band v-up', '弹力带V字挺身'], ['band alternating v-up', '弹力带交替V字挺身'], ['close-grip', '窄握'], ['flutter kicks', '打水踢腿'], ['otis up', '奥蒂斯上举'], ['svend press', '斯文德推举'], ['peacher hammer curl', '传教士锤式弯举'], ['on floor', '地面'], ['all fours', '四点'], ]; // 残留/边界词补充 const EXTRA = { v: 'V', up: '上', breeding: '抬举', arnold: '阿诺德', cuban: '古巴', all: '全', apart: '分开', and: '与', concentration: '集中', revers: '反向', split: '分腿', sit: '坐', t: 'T', blaster: '助力带', pallof: '帕洛夫', zercher: '泽彻', gironda: '吉龙达', svend: '斯文德', jm: '杰姆', pendlay: '彭德雷', jefferson: '杰弗逊', guillotine: '断头台', bradford: '布拉德福德', rocky: '摇摆', otis: '奥蒂斯', thibaudeau: '蒂博多', kayak: '皮划艇', scatter: '散射', spider: '蜘蛛', zottman: '佐特曼', peacher: '传教士', tate: '泰特', waiter: '侍者', scott: '斯科特', world: '世界', stork: '鹳', bowling: '保龄', contralateral: '对侧', can: '罐', french: '法式', pronate: '旋前', pronated: '旋前', supinated: '旋后', pronation: '旋前', supination: '旋后', support: '支撑', supported: '支撑', row_shoulder: '划肩', around: '环绕', across: '横过', face: '面', femoral: '股', iron: '铁', plyo: '增强式', finger: '手指', fingers: '手指', raised: '抬起', spider: '蜘蛛', dumbbells: '哑铃', dips: '臂屈伸', elevator: '电梯', off: '离', ground: '地面', flexor: '屈肌', hug: '抱', pyramid: '金字塔', tennis: '网球', between: '之间', diagonal: '对角', pike: '派克', anti: '抗', gravity: '重力', farmers: '农夫', flag: '旗', flexion: '屈曲', flutter: '打水', frankenstein: '弗兰肯斯坦', frog: '蛙', planche: '水平支撑', reps: '次', maltese: '马耳他', gorilla: '大猩猩', groin: '腹股沟', bends: '屈', clasped: '交叉', handstand: '倒立', keens: '膝', hyght: '高位', hyperextension: '超伸', impossible: '不可能', inchworm: '尺蠖', depth: '深度', scapula: '肩胛', scapular: '肩胛', intermediate: '中级', straps: '带', wipers: '雨刷', jackknife: '折刀', janda: '扬达', advanced: '高级', windmill: '风车', hang: '悬垂', renegade: '叛徒', position: '位', jerk: '上挺', figure: '图形', pass: '穿越', pirate: '海盗', supper: '晚餐', pistol: '手枪', seesaw: '跷跷板', turkish: '土耳其', get: '起', style: '式', out: '出', kipping: '借力', muscle: '双力臂', korean: '韩式', lean: '前倾', left: '左', hook: '勾拳', boxing: '拳击', gripless: '无握', gripper: '握力', overhand: '正握', rotary: '旋转', pad: '垫', unilateral: '单侧', london: '伦敦', catch: '接', point: '点', multiple: '多次', response: '反应', release: '释放', modified: '改良', hindu: '印度', monster: '怪兽', negative: '退让', olympic: '奥林匹克', outside: '外', pelvic: '骨盆', into: '成', peroneals: '腓骨肌', cobra: '眼镜蛇', posterior: '后侧', tibialis: '胫骨肌', potty: '幼儿', power: '力量', prisoner: '囚徒', inside: '内', plus: '加', quarter: '四分之一', quick: '快速', feet: '脚', reclining: '仰卧', big: '大', thrusts: '推', hyper: '超', ring: '吊环', saw: '锯', depresor: '下压', retractor: '后缩', equipment: '器械', runners: '跑者', self: '自', semi: '半', stride: '跨步', outstretched: '伸展', slide: '滑动', sissy: '少女', skater: '滑冰', ski: '滑雪', ergometer: '测功仪', skin: '皮', cat: '猫', degrees: '度', closer: '更近', sledge: '雪橇', raises: '上举', sprint: '冲刺', spell: '法术', caster: '施法', sphinx: '狮身', stalder: '斯塔尔德', staircase: '楼梯', star: '星形', stationary: '固定', straddle: '分腿', outer: '外', suspended: '悬吊', fallout: '塌陷', swimmer: '游泳', three: '三', twin: '双', handle: '握把', upward: '向上', facing: '面向', dog: '犬', elliptical: '椭圆', walking: '行走', treadmill: '跑步机', stepmill: '楼梯机', cossack: '哥萨克', round: '圆', wind: '风', greatest: '最佳', rollerer: '滚轮', archer: '射手', slingers: '摆臂', touchers: '触碰', airbike: '空气单车', fours: '四点', squad: '小队', circular: '环绕', piriformis: '梨状肌', gluteus: '臀肌', motion: '动作', parallel: '平行', rectus: '直肌', femoris: '股直肌', major: '大', towel: '毛巾', astride: '分腿', forth: '往复', backward: '向后', board: '板', basic: '基础', battling: '战斗', ups: '上', drop: '落下', bottoms: '底', cross: '交叉', butt: '臀', butterfly: '蝴蝶', yoga: '瑜伽', pose: '体式', inverse: '反向', variation: '变式', forward: '前', judo: '柔道', flip: '翻', kickback: '后踢', range: '全程', pro: '专业', stirrups: '马镫', drive: '驱动', inner: '内', external: '外', crossovers: '交叉', kayak: '皮划艇', against: '靠', captains: '队长', extended: '伸展', cage: '架', butt: '臀', clasped: '交叉', handstand: '倒立', keens: '膝', hyght: '高位', cocoons: '茧', crab: '蟹', curtsey: '屈膝礼', cycle: '单车', trainer: '训练器', diamond: '钻石', donkey: '驴式', tap: '拍', clap: '击掌', clock: '时钟', flag: '旗', flexion: '屈曲', monster: '怪兽', gripless: '无握', gripper: '握力', depresor: '下压', retractor: '后缩', peroneals: '腓骨肌', tibialis: '胫骨肌', potty: '幼儿', prisoner: '囚徒', reclining: '仰卧', sphinx: '狮身', stair: '楼梯', skater: '滑冰', sissy: '少女', pelican: '鹈鹕', // 命名训练法/专有名词(中文健身圈通用音译或保留专名) 'v-up': 'V字挺身', 'v-sit': 'V坐', 'l-sit': 'L支撑', 'l-pull-up': 'L引体', janda: '扬达', otis: '奥蒂斯', flutter: '打水', peacher: ' preacher', preacher: '传教士', 'ez-bar': 'EZ杠', 'ez-barbell': 'EZ杠铃', supper: '晚餐', pirate: '海盗', slingers: '摆臂', archer: '射手', 'band alternating v-up': '弹力带交替V字挺身', 'band v-up': '弹力带V字挺身', floor: '地面', on: '于', }; // ---------- 词元词典 ---------- const T = { // 器械 dumbbell: '哑铃', dumbbells: '哑铃', barbell: '杠铃', cable: '绳索', cables: '绳索', kettlebell: '壶铃', band: '弹力带', bands: '弹力带', ball: '球', smith: '史密斯', lever: '杠杆', machine: '器械', machines: '器械', ez: '曲', sz: '直', trx: '悬吊', suspension: '悬挂', tire: '轮胎', tyre: '轮胎', sled: '雪橇', sledge: '雪橇', rope: '绳', ropes: '绳', bench: '凳', benches: '凳', plate: '杠铃片', wall: '墙', box: '跳箱', step: '踏板', stepbox: '踏板', chair: '椅', mat: '垫', weight: '负重', weights: '负重', weighted: '负重', medicine: '药', stability: '稳定', bosu: '博苏', foam: '泡沫', roller: '滚轮', wheel: '轮', ab: '腹', chin: '下巴', slam: '砸', swiss: '瑞士', mini: '迷你', loop: '环形', cage: '架', straps: '带', strap: '带', attachment: '附件', bar: '杠', handle: '握把', handles: '握把', platform: '台', pad: '垫', board: '板', rings: '吊环', ring: '吊环', pulley: '滑轮', // 姿态 seated: '坐姿', sitting: '坐姿', sitted: '坐姿', standing: '站姿', lie: '卧', lying: '仰卧', incline: '上斜', decline: '下斜', flat: '平板', reverse: '反向', reversed: '反向', close: '窄距', closer: '更窄', closed: '窄距', overhead: '过顶', lateral: '侧', side: '侧', sides: '侧', front: '前', rear: '后', bent: '俯身', alternating: '交替', alternate: '交替', straight: '直臂', assisted: '助力', prone: '俯卧', supine: '仰卧', kneeling: '跪姿', angled: '斜', angle: '角度', neutral: '对握', wide: '宽距', narrow: '窄距', upright: '直立', single: '单', double: '双', one: '单', two: '双', both: '双', half: '半', full: '全', deep: '深', deeper: '更深', high: '高', higher: '更高', low: '低', long: '长', longer: '更长', short: '短', isometric: '静力', dynamic: '动态', active: '主动', passive: '被动', elevated: '抬升', elevated: '抬高', suspended: '悬吊', supported: '支撑', unsupported: '无支撑', kne: '膝', knees: '膝', knee: '膝', leg: '腿', legs: '腿', legged: '腿', arm: '臂', arms: '臂', // 动作 curl: '弯举', curls: '弯举', press: '推举', presses: '推举', row: '划船', rows: '划船', raise: '上举', raises: '上举', squat: '深蹲', squats: '深蹲', squatting: '深蹲', extension: '伸展', extend: '伸展', fly: '飞鸟', flyes: '飞鸟', flies: '飞鸟', push: '推', pull: '拉', crunch: '卷腹', crunches: '卷腹', dip: '臂屈伸', dips: '臂屈伸', lunge: '箭步蹲', lunges: '箭步蹲', twist: '转体', twists: '转体', kick: '踢', kicks: '踢', swing: '摆荡', deadlift: '硬拉', preacher: '传教士', stretch: '拉伸', stretches: '拉伸', stretching: '拉伸', hold: '保持', squeeze: '挤压', sit: '坐', jump: '跳', jumps: '跳', march: '踏步', climb: '攀爬', climber: '攀爬', thrust: '推', thrusts: '推', lift: '上提', lifting: '上提', drag: '拖', roll: '滚动', rollerout: '滚伸', rollerer: '滚轮', circle: '画圈', circles: '画圈', circular: '环绕', rotate: '旋转', rotation: '旋转', rotational: '旋转', flex: '屈曲', flexion: '屈曲', flexor: '屈肌', abductor: '外展肌', abduction: '外展', adductor: '内收肌', adduction: '内收', pulse: '脉冲', bounce: '弹跳', hop: '单脚跳', hops: '单脚跳', walk: '行走', run: '跑', running: '跑', runner: '跑者', jog: '慢跑', pedal: '蹬', tuck: '收腹', reach: '伸展', bridge: '桥', jack: '开合', balance: '平衡', balancing: '平衡', stabilization: '稳定', stabilize: '稳定', contraction: '收缩', engage: '收紧', activate: '激活', isolate: '孤立', isolated: '孤立', compound: '复合', tempo: '节奏', pause: '停顿', breathe: '呼吸', breath: '呼吸', shrug: '耸肩', shrugs: '耸肩', tap: '拍击', clap: '击掌', carry: '农夫行走', crawl: '爬', glute: '臀', glutes: '臀', ham: '腘绳', hip: '髋', hips: '髋', hanging: '悬垂', shoulder: '肩', shoulders: '肩', chest: '胸', back: '背', arm: '臂', leg: '腿', calf: '小腿', calves: '小腿', biceps: '二头', triceps: '三头', wrist: '腕', core: '核心', abs: '腹', abdominal: '腹', abdominals: '腹', gluteal: '臀', thigh: '大腿', neck: '颈', forearm: '前臂', forearms: '前臂', upper: '上', lower: '下', quad: '股四头', quads: '股四头', quadriceps: '股四头', hamstring: '腘绳肌', hamstrings: '腘绳肌', oblique: '腹斜肌', obliques: '腹斜肌', delt: '三角肌', delts: '三角肌', deltoid: '三角肌', deltoids: '三角肌', trap: '斜方肌', traps: '斜方肌', trapezius: '斜方肌', lat: '背阔肌', lats: '背阔肌', pectoral: '胸', pectorals: '胸', pec: '胸', pecs: '胸', spinal: '脊柱', spine: '脊柱', erector: '竖脊肌', erectors: '竖脊肌', serratus: '前锯肌', adductors: '内收肌', abductors: '外展肌', rhomboid: '菱形肌', rhomboids: '菱形肌', grip: '握', hand: '手', hands: '手', finger: '手指', fingers: '手指', toe: '脚趾', toes: '脚趾', heel: '脚跟', foot: '脚', feet: '脚', ankle: '踝', ankles: '踝', knee: '膝', elbow: '肘', waist: '腰', torso: '躯干', body: '全身', male: '男', female: '女', v: 'V', rope: '绳', // 其余修饰词 air: '空气', bike: '单车', fours: '四点', squad: '小队', toucher: '触', touchers: '触', touch: '触', with: '带', throw: '投掷', down: '下', gluteus: '臀肌', piriformis: '梨状肌', motion: '动作', parallel: '平行', rectus: '直肌', femoris: '股直肌', major: '大', towel: '毛巾', astride: '分腿', forth: '往复', backward: '向后', board: '板', basic: '基础', battling: '战斗', ups: '上', drop: '落下', squatting: '深蹲', bottoms: '底', cross: '交叉', body: '全身', butt: '臀', butterfly: '蝴蝶', yoga: '瑜伽', pose: '体式', inverse: '反向', variation: '变式', forward: '前', judo: '柔道', flip: '翻', kickback: '后踢', range: '全程', pro: '专业', stirrups: '马镫', drive: '驱动', rotational: '旋转', inner: '内', external: '外', crossovers: '交叉', kayak: '皮划艇', against: '靠', captains: '队长', extended: '伸展', cage: '架', butt: '臀', butterfly: '蝴蝶', clasped: '交叉', handstand: '倒立', keens: '膝', hyght: '高位', hyperextension: '超伸', impossible: '不可能', inchworm: '尺蠖', depth: '深度', scapula: '肩胛', scapular: '肩胛', intermediate: '中级', from: '从', head: '头', the: '的', of: '的', behind: '头后', bradford: '布拉德福德', rocky: '摇摆', skier: '滑雪', speed: '爆发', rocking: '摇摆', stiff: '直腿', thruster: '推举蹲', in: '内', t: 'T', twisted: '扭转', iron: '铁', across: '横过', face: '面', femoral: '股', pronated: '旋前', supinated: '旋后', pronation: '旋前', supination: '旋后', french: '法式', support: '支撑', peacher: ' preacher', plyo: '增强式', pronate: '旋前', row_shoulder: '划船肩', scott: '斯科特', waiter: '侍者', w: 'W', around: '环绕', bowling: '保龄', stork: '鹳', contralateral: '对侧', cuban: '古巴', can: '罐', finger: '手指', raised: '抬起', breeding: ' breeding', spider: '蜘蛛', world: '环绕', above: '上方', sumo: '相扑', supported: '支撑', tate: 'Tate', elevator: '电梯', butt: '臀', cocoons: '茧', crab: '蟹', curtsey: '屈膝礼', cycle: '单车', trainer: '训练器', diamond: '钻石', donkey: '驴式', basic: '基础', tap: '拍', clap: '击掌', clock: '时钟', cocoons: '茧', crab: '蟹', curtsey: '屈膝礼', flag: '旗', flexion: '屈曲', flutter: '打水', frankenstein: '弗兰肯斯坦', frog: '蛙', planche: '水平支撑', reps: '次', maltese: '马耳他', gironda: '吉龙达', sternum: '胸骨', ham: '腘绳', gorilla: '大猩猩', groin: '腹股沟', bends: '屈', clasped: '交叉', reversed: '反向', handstand: '倒立', keens: '膝', hyght: '高位', hyperextension: '超伸', impossible: '不可能', inchworm: '尺蠖', depth: '深度', scapula: '肩胛', scapular: '肩胛', intermediate: '中级', straps: '带', wipers: '雨刷', jackknife: '折刀', janda: '扬达', advanced: '高级', windmill: '风车', hang: '悬垂', renegade: '叛徒', position: '位', jerk: '上挺', figure: '图形', pass: '穿越', pirate: '海盗', pistol: '手枪', seesaw: '跷跷板', turkish: '土耳其', get: '起', style: '式', out: '出', kipping: '借力', muscle: '双力臂', korean: '韩式', l: 'L', lean: '前倾', left: '左', hook: '勾拳', boxing: '拳击', gripless: '无握', gripper: '握力', overhand: '正握', rotary: '旋转', pad: '垫', unilateral: '单侧', london: '伦敦', catch: '接', point: '点', multiple: '多次', response: '反应', release: '释放', modified: '改良', hindu: '印度', monster: '怪兽', negative: '退让', oblique: '腹斜', olympic: '奥林匹克', otis: '奥蒂斯', outside: '外', pelvic: '骨盆', into: '成', peroneals: '腓骨肌', cobra: '眼镜蛇', posterior: '后侧', tibialis: '胫骨肌', potty: '幼儿', power: '力量', prisoner: '囚徒', inside: '内', plus: '加', quarter: '四分之一', quick: '快速', feet: '脚', reclining: '仰卧', big: '大', thrusts: '推', hyper: '超', ring: '吊环', saw: '锯', depresor: '下压', retractor: '后缩', equipment: '器械', runners: '跑者', self: '自', semi: '半', stride: '跨步', outstretched: '伸展', slide: '滑动', sissy: '少女', skater: '滑冰', ski: '滑雪', ergometer: '测功仪', skin: '皮', cat: '猫', degrees: '度', closer: '更近', sledge: '雪橇', hammer: '锤', raises: '上举', sprint: '冲刺', spell: '法术', caster: '施法', sphinx: '狮身', split: '分腿', stalder: '斯塔尔德', staircase: '楼梯', star: '星形', stationary: '固定', straddle: '分腿', outer: '外', suspended: '悬吊', fallout: '塌陷', swimmer: '游泳', three: '三', twin: '双', upward: '向上', facing: '面向', dog: '犬', elliptical: '椭圆', walking: '行走', treadmill: '跑步机', stepmill: '楼梯机', cossack: '哥萨克', round: '圆', svend: '斯文德', wind: '风', greatest: '最佳', rollerer: '滚轮', }; PHRASES.sort((a, b) => b[0].length - a[0].length); function escapeRe(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // 英文→中文音译(用于兜底未知名词) const PHON = { archer: '射手', slingers: '摆臂', touchers: '触碰', airbike: '空气单车', fours: '四点', squad: '小队', circular: '环绕', piriformis: '梨状肌', gluteus: '臀肌', pallof: '帕洛夫', zercher: '泽彻', guillotine: '断头台', jefferson: '杰弗逊', pendlay: '彭德雷', jm: '杰姆', bradford: '布拉德福德', rocky: '摇摆', thruster: '推举蹲', skier: '滑雪者', blaster: '助力带', snatch: '挺举', judo: '柔道', kayak: '皮划艇', thibaudeau: '蒂博多', cambered: '弯杆', captains: '队长', cocoons: '茧式', curtsey: '屈膝礼', frankenstein: '弗兰肯斯坦', frog: '蛙', planche: '水平支撑', maltese: '马耳他', gironda: '吉龙达', sternum: '胸骨', gorilla: '大猩猩', groin: '腹股沟', inchworm: '尺蠖', jackknife: '折刀', janda: '扬达', windmill: '风车', renegade: '叛徒', pirate: '海盗', pistol: '手枪', seesaw: '跷跷板', turkish: '土耳其', kipping: '借力', london: '伦敦', otis: '奥蒂斯', sphinx: '狮身', stalder: '斯塔尔德', cossack: '哥萨克', svend: '斯文德', spell: '法术', caster: '施法', pelican: '鹈鹕', wipers: '雨刷', butterfly: '蝴蝶', monster: '怪兽', hindu: '印度', skater: '滑冰者', sissy: '少女', farmer: '农夫', flag: '旗帜', handstand: '倒立', keens: '膝', hyght: '高位', gripless: '无握', gripper: '握力', depresor: '下压', retractor: '后缩', peroneals: '腓骨肌', tibialis: '胫骨肌', potty: '幼儿', prisoner: '囚徒', reclining: '仰卧', cobra: '眼镜蛇', elliptical: '椭圆机', treadmill: '跑步机', stepmill: '楼梯机', ski: '滑雪', ergometer: '测功仪', skin: '皮', cat: '猫', rollerer: '滚轮', peacher: '传教士', row_shoulder: '划肩', world: '世界', stork: '鹳', bowling: '保龄', contralateral: '对侧', cuban: '古巴', can: '罐', spider: '蜘蛛', waiter: '侍者', tate: '泰特', elevator: '电梯', butt: '臀', monster: '怪兽', impossible: '不可能', depth: '深度', scapula: '肩胛', intermediate: '中级', straps: '带', jackknife: '折刀', advanced: '高级', hang: '悬垂', position: '位', jerk: '上挺', figure: '图形', pirate: '海盗', get: '起', kipping: '借力', muscle: '肌肉', korean: '韩式', lean: '前倾', boxing: '拳击', hook: '勾', overhand: '正握', rotary: '旋转', pad: '垫', unilateral: '单侧', london: '伦敦', }; function romanize(tok) { if (PHON[tok]) return PHON[tok]; const map = { a: '阿', e: '埃', i: '伊', o: '奥', u: '乌', y: '伊', b: '布', c: '克', d: '德', f: '夫', g: '格', h: '赫', j: '吉', k: '克', l: '尔', m: '姆', n: '恩', p: '普', q: '克', r: '尔', s: '斯', t: '特', v: '夫', w: '乌', x: '克斯', z: '兹' }; return tok.split('').map(c => map[c] || c).join(''); } // 应直接丢弃的干扰词(数据噪声 / OCR 错误),不参与翻译 const DROP = new Set(['supper', 'breeding']); function translate(name) { let s = ' ' + name.toLowerCase().replace(/°/g, '度') + ' '; // 去掉版本号标注,如 " v. 2" / "(v.3)" / " - v.2" s = s.replace(/\s*[(\-]?\s*v\.?\s*\d+\s*[)\]]?/g, ' '); s = ' ' + s.trim() + ' '; const ph = []; for (const [en, zh] of PHRASES) { const re = new RegExp('(^|[^a-z0-9])' + escapeRe(en) + '($|[^a-z0-9])', 'g'); s = s.replace(re, (m, pre, post) => { ph.push(zh); return pre + `__p${ph.length - 1}__` + post; }); } const raw = s.split(/[^a-z0-9一-龥_]+/).filter(Boolean); const out = []; for (const tk of raw) { if (tk.startsWith('__p') && tk.endsWith('__')) { out.push(ph[+tk.slice(3, -2)]); continue; } if (/^[0-9]+$/.test(tk)) { out.push(tk); continue; } if (DROP.has(tk)) continue; const zh = T[tk] || EXTRA[tk]; if (zh) out.push(zh); else if (/^[a-z]+$/.test(tk)) out.push(romanize(tk)); else out.push(tk); } return out.join(''); } const arr = JSON.parse(fs.readFileSync(DATA, 'utf-8')); let fully = 0; const residual = new Map(); for (const rec of arr) { const text = translate(rec.name); rec.nameZh = text; if (/[a-zA-Z]/.test(text)) { fully++; residual.set(rec.name, text); } } const cov = (((arr.length - residual.size) / arr.length) * 100).toFixed(2); console.log(`总条数: ${arr.length}`); console.log(`已完全中文化(无英文字母): ${arr.length - residual.size} (${cov}%)`); console.log(`仍含英文的条数: ${residual.size}`); let n = 0; for (const [en, zh] of residual) { if (n++ < 30) console.log(` ${en} => ${zh}`); } console.log('--- 抽样 ---'); for (let i = 0; i < 25; i++) console.log(` ${arr[i].name} => ${arr[i].nameZh}`); fs.writeFileSync(DATA, JSON.stringify(arr), 'utf-8'); console.log('已写回 exercises.json(nameZh 字段)');