feat: 小程序连接服务器IP + 同步未提交开发

- miniprogram/config.js: BASE_URL 指向 http://192.227.237.8:3001
- 动作标题中文化(nameZh),搜索匹配 name/nameZh/nameEn
- 新增计划/收藏/我的 等页面与组件
- 后端 Docker 化(Dockerfile/.dockerignore)与翻译脚本
- .gitignore 补充 .DS_Store
This commit is contained in:
2026-07-22 14:05:30 +08:00
parent b3b58e66fb
commit 70ff806042
79 changed files with 2397 additions and 146070 deletions

View File

@@ -0,0 +1,338 @@
// 动作标题中文化引擎 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.jsonnameZh 字段)');