#!/usr/bin/env python # -*- coding: utf-8 -*- """Merge Multilingual-ai (post-edit) into term_*.xlsx + apply term-review.md fixes.""" import sys, io, os sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') from openpyxl import load_workbook TOOLS = r'C:\TH1\TH1\Tools' AI_BACKUP = os.path.join(TOOLS, 'Multilingual-ai.backup-2026-04-28.xlsx') TERM_DIR = os.path.join(TOOLS, '术语表') # ============================================================ # STEP 1: Multilingual-ai-review.md fixes (rebuild post-edit) # Format: ID -> {EN/JP/KR: new_value} # ============================================================ AI_FIXES = { '17831': {'EN': 'Dharma', 'KR': '정법'}, '17857': {'EN': 'Wago-Araga Bond', 'KR': '화혼과 황혼의 연리'}, '17858': {'EN': 'Cursed Bunrei'}, '17863': {'KR': '바람타기'}, '17865': {'EN': 'Omikuji'}, '17890': {'EN': '[Ability: Leave it to Lord Mishaguji!]', 'JP': '[能力:ミシャグチ様に任せて!]', 'KR': '[능력: 미샤구지님께 맡겨!]'}, '17896': {'EN': 'Chaotic Omikuji Barrage'}, '17897': {'EN': '[Ability: Omikuji]'}, '17908': {'EN': '[Ability: Crimson Leaf Herald]'}, '17916': {'EN': '[Bishop] Class Hero'}, '17939': {'KR': '오니족 호걸'}, '18062': {'EN': 'Gross Body'}, '18127': {'EN': 'Statue of the Queen', 'JP': '后の彫像'}, '18130': {'EN': 'Statue of the Bishop'}, '18133': {'EN': 'Statue of the Rook'}, '18138': {'EN': 'Statue of the Knight'}, '18154': {'EN': 'Karana-sharira', 'JP': '原因身', 'KR': '원인신'}, '18168': {'EN': 'Maha-Vetala', 'JP': 'マハー・ヴェターラ', 'KR': '마하베탈라'}, '18179': {'EN': 'Awe-Strike'}, '18213': {'KR': '바루나함'}, '18217': {'EN': 'Rudra Fire Chariot'}, '18311': {'EN': '[Bishop] Class', 'KR': '[상] 클래스'}, '18314': {'EN': '[Rook] Class'}, '18447': {'KR': '월토끼 환영'}, '18520': {'EN': 'Scarlet Sleepless Castle'}, '18523': {'EN': "The Empire's Blood Sovereign", 'KR': '제국의 피의 군왕'}, '18525': {'EN': 'Perfect & Elegant Maid'}, '18534': {'EN': '[Ability: Yellow Quake Stomp]', 'KR': '[능력: 황진각]'}, '18549': {'EN': 'Sea of Trees of Hourai'}, '18567': {'EN': 'Peerless Elixir of the Realm'}, '18613': {'KR': '마법석{화}'}, '18614': {'KR': '마법석{목}'}, '18615': {'KR': '마법석{금}'}, '18626': {'JP': '----[バグと最適化]----'}, '18717': {'EN': 'Statue of the King'}, '18840': {'EN': 'Statue of the King'}, '19450': {'KR': '중국어'}, } # ============================================================ # STEP 2: Build {ZH: (EN, JP, KR)} from AI backup + AI_FIXES # ============================================================ def build_ai_data(): wb = load_workbook(AI_BACKUP, read_only=True) ws = wb.active data = {} # ZH -> [EN, JP, KR] for row in ws.iter_rows(min_row=2, values_only=True): rid = str(row[0] or '').lstrip('') zh, en, jp, kr = row[2], row[4], row[5], row[6] if not zh: continue # Apply fixes if any f = AI_FIXES.get(rid, {}) en2 = f.get('EN', en) jp2 = f.get('JP', jp) kr2 = f.get('KR', kr) data[zh] = [en2, jp2, kr2] wb.close() return data # ============================================================ # STEP 3: term-review.md row-specific fixes by ZH # Applied after AI merge (so they override anything from AI merge) # ============================================================ TERM_FIXES = { # E1 '绝不再把你留在阿斯佩恩': { 'EN': 'Never leave you in Aspern again', 'JP': '二度とアスペルンに置いていかない', 'KR': '다시는 널 아스페른에 두고 가지 않을게'}, # E2 (ZH not changed; per user instruction) '御住古战场': { 'EN': 'Onbashira Ancient Battlefield', 'KR': '온바시라 고대 전장'}, # E3 拼音 → 英文棋子 '英雄神像[后]': {'EN': 'Hero Statue [Queen]', 'JP': '英雄神像[后]', 'KR': '영웅 신상 [후]'}, '英雄神像[相]': {'EN': 'Hero Statue [Bishop]'}, '英雄神像[王]': {'EN': 'Hero Statue [King]'}, '英雄神像[马]': {'EN': 'Hero Statue [Knight]'}, '英雄神像[车]': {'EN': 'Hero Statue [Rook]'}, # E4 赤口 → Mishaguji '赤口大人的作祟': {'EN': "Lord Mishaguji's Curse", 'JP': 'ミシャグチ様の祟り', 'KR': '미샤구지님의 저주'}, '交给赤口大人吧!': {'EN': 'Leave it to Lord Mishaguji!', 'JP': 'ミシャグチ様に任せて!', 'KR': '미샤구지님께 맡겨!'}, # E5 '召唤御射宫司大人': {'EN': 'Summon Lord Mishaguji', 'KR': '미샤구지님 소환'}, # E7 挖掘 verb '挖掘': {'JP': '発掘', 'KR': '발굴'}, # §二 sync (overwrite if AI merge didn't already cover) '国士无双之药': {'EN': 'Peerless Elixir of the Realm'}, '完美女仆': {'EN': 'Perfect & Elegant Maid'}, '红色不夜城': {'EN': 'Scarlet Sleepless Castle'}, '红叶传令': {'EN': 'Crimson Leaf Herald'}, # §三 C1 (建造英雄神像系列) '建造英雄神像[马]': {'EN': 'Build Hero Statue [Knight]', 'KR': '영웅 신상 [마] 건설'}, '建造英雄神像[后]': {'EN': 'Build Hero Statue [Queen]', 'KR': '영웅 신상 [후] 건설'}, '建造英雄神像[车]': {'EN': 'Build Hero Statue [Rook]', 'KR': '영웅 신상 [차] 건설'}, '建造英雄神像[相]': {'EN': 'Build Hero Statue [Bishop]', 'JP': '英雄神像[相]', 'KR': '영웅 신상 [상] 건설'}, '建造英雄神像[王]': {'EN': 'Build Hero Statue [King]', 'KR': '영웅 신상 [왕] 건설'}, # §C2 红雾 KR unify (주홍 안개) '清除红雾': {'KR': '주홍 안개 제거'}, '回收红雾': {'KR': '주홍 안개 회수'}, '红雾攻击': {'KR': '주홍 안개 공격'}, '红雾弥漫': {'KR': '주홍 안개 자욱'}, '红雾领地': {'KR': '주홍 안개 영지'}, '红雾防御': {'KR': '주홍 안개 방어'}, # §C3 风祝 KR (바람 무녀) '铁血风祝': {'KR': '철혈의 바람 무녀'}, '风祝': {'KR': '바람 무녀'}, # §C4 大团长 → Grand Master '大团长的将棋时间': {'EN': "Grand Master's Shogi Time"}, # §D3 核能 → 核エネルギー / 핵 에너지 '土豆大王与核能尊神': {'JP': '芋大王と核エネルギーの尊神', 'KR': '감자 대왕과 핵 에너지 존신'}, # §D5 punctuation '地毯、咖啡与香料': {'JP': '絨毯・コーヒー・香辛料'}, # §D7 미조우 '未遇见': {'KR': '만난 적 없음'}, '未相遇的玩家': {'KR': '만난 적 없는 플레이어'}, # §D10 竹林狼 KR space '召唤竹林狼': {'KR': '대나무 숲 늑대 소환'}, '竹林狼上校': {'KR': '대나무 숲 늑대 대령'}, # §D11 简体中文 KR '简体中文': {'KR': '간체 중국어'}, # §D12 血流成河 EN '我要看到血流成河!': {'EN': 'I want to see rivers of blood!'}, '无聊!我要看到血流成河!': {'EN': 'Boring! I want to see rivers of blood!'}, } # ============================================================ # STEP 4: Merge into a single term file # ============================================================ LANG_IDX = {'EN': 0, 'JP': 1, 'KR': 2} def merge_term(term_path, lang): """lang in EN/JP/KR. Loads term_*.xlsx, merges AI data + term fixes, saves.""" ai_data = build_ai_data() # ZH -> [EN, JP, KR] li = LANG_IDX[lang] wb = load_workbook(term_path) ws = wb.active # Build existing ZH -> row index map existing = {} for r in range(2, ws.max_row + 1): zh = ws.cell(row=r, column=1).value if zh: existing[zh] = r # Counters overwrote = 0 appended = 0 term_fixed = 0 # Pass 1: Merge AI data for zh, vals in ai_data.items(): new_val = vals[li] if new_val is None: continue if zh in existing: row = existing[zh] old = ws.cell(row=row, column=2).value if old != new_val: ws.cell(row=row, column=2).value = new_val overwrote += 1 else: new_row = ws.max_row + 1 ws.cell(row=new_row, column=1).value = zh ws.cell(row=new_row, column=2).value = new_val existing[zh] = new_row appended += 1 # Pass 2: Apply term-review fixes (override) for zh, fix_map in TERM_FIXES.items(): if lang not in fix_map: continue new_val = fix_map[lang] if zh in existing: row = existing[zh] old = ws.cell(row=row, column=2).value if old != new_val: ws.cell(row=row, column=2).value = new_val term_fixed += 1 else: print(f' [WARN] term-fix ZH not found in {lang}: {zh!r}') wb.save(term_path) print(f' {os.path.basename(term_path)} ({lang}): overwrote={overwrote} appended={appended} term_fixed={term_fixed} new_total_rows={ws.max_row}') # ============================================================ # RUN # ============================================================ if __name__ == '__main__': print('=== Merging Multilingual-ai post-edit data into term_*.xlsx ===') merge_term(os.path.join(TERM_DIR, 'term_en.xlsx'), 'EN') merge_term(os.path.join(TERM_DIR, 'term_jp.xlsx'), 'JP') merge_term(os.path.join(TERM_DIR, 'term_kr.xlsx'), 'KR') print('Done.')