kone
sub_icon

소미소프트

파일 구글 번역기) kr_tr_7.pyw

2026-04-22 20:36:11
유틸
조회 12130 · 좋아요 9
양식
<div>
    <table><tbody><tr><th colspan="2"><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></th></tr><tr><td colspan="2"><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></td></tr><tr><td><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></td><td><p style="margin: 0.5rem 0px;">=</p></td></tr><tr><td><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></td><td><p style="margin: 0.5rem 0px;">=</p></td></tr><tr><td><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></td><td><p style="margin: 0.5rem 0px;">=</p></td></tr><tr><th colspan="2"><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></th></tr><tr><td colspan="2"><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></td></tr><tr><th colspan="2"><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></th></tr><tr><td colspan="2"><p style="margin: 0.5rem 0px; display: flex; justify-content: center; align-items: center;">=</p></td></tr></tbody></table>
</div>

kr_tr_7.pyw

링크

aHR0cHM6Ly90cmFuc2Zlci5pdC90L2REQmhxZjVYa1JBSg==

단일로도 어느정도 쓸 수 있을텐데,
게임 번역하려면 추출한 다음 사용하는게 안정적이고 빠름

파이썬 설치되어 있어야 함
그록이 자꾸 바쁘다고 팅겨서 제미니에게 부탁함

AI 번역 돌릴줄 모르거나
컴 사양이 안되는 경우 쓸만할듯

코드
import os
import re
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext, ttk
import threading
import urllib.parse
import requests
import time

def google_translate(text, src='ja', dest='ko'):
    if not text.strip(): return text
    if not re.search(r'[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]', text):
        return text

    try:
        url = f"https://translate.googleapis.com/translate_a/single?client=gtx&sl={src}&tl={dest}&dt=t&q={urllib.parse.quote(text)}"
        headers = {'User-Agent': 'Mozilla/5.0'}
        res = requests.get(url, headers=headers, timeout=5)
        res.raise_for_status()
        
        parts = res.json()[0]
        result = "".join([p[0] for p in parts if p and p[0]]).strip()
        
        # 마침표 보정 로직
        if not text.strip().endswith('.') and result.endswith('.'):
            result = result[:-1].strip()
            
        return result if result else text
    except Exception:
        return text

class AdvancedTranslator:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("하위 폴더 통합 번역기 v8.0 (큰따옴표 지원)")
        self.root.geometry("800x650")

        config_frame = tk.Frame(self.root)
        config_frame.pack(fill="x", padx=10, pady=5)

        # 구분자를 세미콜론(;)으로 사용하고 기본값에 큰따옴표(") 추가
        tk.Label(config_frame, text="번역 제외 문자 (';'로 구분):").grid(row=0, column=0, sticky="w")
        self.exclude_entry = tk.Entry(config_frame, width=50)
        self.exclude_entry.insert(0, '「; 」; <; >; "; ---; \\n; \\i; ,; [; ]; (; ); :; …; !; \\; :; (; ); ,') 
        self.exclude_entry.grid(row=0, column=1, padx=5, sticky="w")

        self.btn = tk.Button(self.root, text="폴더 선택 (하위 폴더 포함 번역 시작)", command=self.start_thread, 
                             height=2, bg="#4CAF50", fg="white", font=("맑은 고딕", 10, "bold"))
        self.btn.pack(fill="x", padx=10, pady=5)

        self.notebook = ttk.Notebook(self.root)
        self.notebook.pack(fill="both", expand=True, padx=10, pady=10)

        self.log_area = scrolledtext.ScrolledText(self.notebook, bg="#1e1e1e", fg="#ffffff", font=("맑은 고딕", 12))
        self.monitor_area = scrolledtext.ScrolledText(self.notebook, bg="#2d2d2d", fg="#a6e22e", font=("맑은 고딕", 12))
        
        self.notebook.add(self.log_area, text=" 전체 진행 로그 ")
        self.notebook.add(self.monitor_area, text=" 실시간 번역 비교 ")

        self.jp_pattern = re.compile(r'[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]')

    def start_thread(self):
        path = filedialog.askdirectory()
        if not path: return
        self.btn.config(state='disabled')
        threading.Thread(target=self.process, args=(path,), daemon=True).start()

    def split_and_translate(self, text, exclude_chars):
        if not exclude_chars:
            return google_translate(text)

        # 특수 문자 및 큰따옴표를 안전하게 정규식 패턴으로 변환
        pattern = '|'.join(re.escape(char) for char in exclude_chars)
        tokens = re.split(f'({pattern})', text)
        
        translated_tokens = []
        for token in tokens:
            if not token: continue # 빈 문자열 건너뜀
            
            if token in exclude_chars:
                translated_tokens.append(token)
            elif self.jp_pattern.search(token):
                # 실제 번역 수행 (일본어 -> 한국어)
                translated_tokens.append(google_translate(token, src='ja', dest='ko'))
                time.sleep(0.15) 
            else:
                translated_tokens.append(token)
        
        return "".join(translated_tokens)

    def process(self, root_path):
        raw_excludes = self.exclude_entry.get().split(";")
        exclude_chars = [x.strip() for x in raw_excludes if x.strip()]
        
        all_files = []
        for root, dirs, files in os.walk(root_path):
            for file in files:
                if file.lower().endswith(('.txt', '.json', '.ini', '.csv')):
                    all_files.append(os.path.join(root, file))

        parent_dir = os.path.dirname(root_path)
        folder_name = os.path.basename(root_path)
        out_root_dir = os.path.join(parent_dir, f"{folder_name}_Translated")
        
        self.log_insert(f"🚀 총 {len(all_files)}개의 파일을 찾았습니다.\n")
        self.log_insert(f"🏠 저장 위치: {out_root_dir}\n{'-'*50}\n")

        for i, file_path in enumerate(all_files):
            rel_path = os.path.relpath(file_path, root_path)
            save_path = os.path.join(out_root_dir, rel_path)
            os.makedirs(os.path.dirname(save_path), exist_ok=True)
            
            self.log_insert(f"📄 [{i+1}/{len(all_files)}] {rel_path} 번역 중...\n")
            
            content_lines = []
            for enc in ['shift_jis', 'utf-8-sig', 'cp932', 'utf-8', 'euc-kr']:
                try:
                    with open(file_path, 'r', encoding=enc) as f:
                        content_lines = f.readlines()
                    break
                except: continue

            translated_lines = []
            for line in content_lines:
                if self.jp_pattern.search(line):
                    origin = line.rstrip('\n\r')
                    translated = self.split_and_translate(origin, exclude_chars)
                    self.monitor_insert(f"파일: {rel_path}\n원문: {origin}\n번역: {translated}\n{'-'*20}\n")
                    translated_lines.append(translated + '\n')
                else:
                    translated_lines.append(line)

            with open(save_path, 'w', encoding='utf-8-sig') as f:
                f.writelines(translated_lines)

        self.btn.config(state='normal')
        messagebox.showinfo("완료", "큰따옴표를 포함한 모든 파일 번역이 완료되었습니다.")

    def log_insert(self, msg):
        self.log_area.insert(tk.END, msg)
        self.log_area.see(tk.END)

    def monitor_insert(self, msg):
        self.monitor_area.insert(tk.END, msg)
        self.monitor_area.see(tk.END)

if __name__ == "__main__":
    app = AdvancedTranslator()
    app.root.mainloop()
9
댓글 8개
댓글 쓰기
04.22
번역 라이브러리는 googletrans==3.1.0a0 이거 인가…?
04.23
제미니에게 뭐라고 했더니 라이브러리 안 쓰는거 같음
ja 대신 en 하면 영어도 될라나
04.23
그건 대부분 영어로 이루어져있기 때문에 제외 단어 엄청 등록하는거 아니면 불가능할걸 게임 터짐
04.23
추출 상태로 돌리면 가능은 할거임 통으로 돌리면 터진다는 뜻
0 / 500
[구매보급][번역요청] RJ366405, RJ274147, RJ125993 격전요이담+패러렐판타지 if
미번
jung3291
04.29 13603 31
노출류 신작 드디어 출시일뜸
정보
afds34wewq
04.29 12740 27
내 근육 돌려줘! 공략 (초스압주의,스포주의)
후기 및 공략
asdf
04.29 16699 46
짧번)보지 붕괴 피스톤
야짤
qew123
04.29 10479 33
AI번역,손식질) 사키코 간통사정 3
동인
1Q2W3E4R
04.29 25960 113
아리아 (ZZZ)
영상
브레머튼
04.29 20840 105
bbc ep21+22 자막 완성함
영상
jaennab
04.29 16661 71
U2FpZ28gRWJpem9yaQ== 기타 영상 모음
영상
karatro
04.29 23724 105
AI, 나히아) 하가쿠레 교내 노출
야짤
miso5
04.29 14563 60
[후기] RJ01293869 [7センチ] 종말 쉘터 성활 v1.4 후기
후기 및 공략
루나랩
04.29 16594 24
[구매보급][번역 요청] RJ01569413 征服_催眠紅魔館 Ver1.00b
미번
rkrkrkrk777777
04.29 13199 46
[구매보급]【오호쿠노이치】건방진 쿠노이치를 약물굴복교미시키는 이야기
소리
이름뭐하지
04.29 18314 57
Poriuretan 갸루와 안경(남), 그리고 여름
동인
uzaki
04.29 19557 56
Poriuretan 한여름 낮 시간의 아파트 단지 주부
동인
uzaki
04.29 18802 43
Poriuretan 심령 스팟에서 의기투합
동인
uzaki
04.29 12239 29
Poriuretan 컴플렉스
동인
uzaki
04.29 17787 47
Poriuretan 노츨중 환자와 이슬
동인
uzaki
04.29 15029 46
Poriuretan 언제나 옷차림이 가벼운
동인
uzaki
04.29 16888 53
Poriuretan 메이드
동인
uzaki
04.29 13285 37
Poriuretan 수학여행
동인
uzaki
04.29 14197 45
Poriuretan 이웃집 여자아이
동인
uzaki
04.29 21832 65
Poriuretan 모기장 밖
동인
uzaki
04.29 8792 28
[베로츄 특화] 나를 너무너무너무 좋아하는 건방진 JK 여동생과 잔뜩 키스하는 동거 생활
소리
츄하이
04.29 18853 94
AI, 셀레스포니아) 감각차단함정 (촉수, 산란 있음 시청 주의)
야짤
miso5
04.29 16168 144
[버전업] 요몽원: The Nightmaretaker ~악마에 씌인 남자~ v1.7.2
미번
kkkkkk0909
04.29 32427 178
[한글자막] 왕가슴 대기업 임원, 애널&풋잡
영상
실루엣21
04.29 33519 122
[이미지 번역]코스플레이어 우타네를 빼앗겨 버립니다
번역
솔라셀
04.29 56579 215
비비안 [ZZZ] ( 기본 + 보너스 영상)
영상
브레머튼
04.29 18347 85
【아헤오호 밀착 엣찌로 의사소통♪】 ~맹인 폭유 시스터의 두근두근 보지 커뮤니케이션♪~ 초미인 성녀님이 나의 오라에 한눈에 반해... 엣!
소리
shiroi
04.29 18841 95
타락신관 공략글 링크 + 궁금한거 질문 받음
후기 및 공략
asdf788
04.29 14464 31