kone
sub_icon

소미소프트

파일 구글 번역기) kr_tr_7.pyw

2026-04-22 20:36:11
유틸
조회 12069 · 좋아요 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
펌) 산제물인 엄마5
동인
kjalar
04.22 33137 64
[Ai 후원] 방도리 시로카네 린코 [348p]
야짤
Ghost
04.22 9440 23
[貧乳愛好会] 야한 노출 방송 ~체육관 관장이 사실은 변태 노출 스트리머?~
영상
실루엣21
04.22 23363 99
[Ai 후원] 블렌드s 히나타 카호 [353p]
야짤
Ghost
04.22 14644 17
[업데이트 안내] 존재감 없는 여동생과의 소박한 일상 1.07rev.1
번역
kkkkkk0909
04.22 50349 166
현1자전1도사 모음
동인
Ghost
04.22 24897 99
[Ai 후원] 따끈 베이커리 아즈사가와 츠키노 [364p]
야짤
Ghost
04.22 14420 20
[ai번역] RJ404030 야한 학교 괴담 1 (패치파일만) 수정1
번역
ㅇㅇ
04.22 31755 74
[Ai 후원] 친구가 없어 카시와자키 세나 [354p]
야짤
Ghost
04.22 14283 22
[미번/보?급/번역요청/고어] Astrid's Adventure
미번
로지쨤리
04.22 14216 22
[한글자막] 아이큐 VS 카베이라, 흑자지 임신 승부!!
영상
실루엣21
04.22 21307 109
≪★ 사정 가챠 포함★≫【좋은 마조 손님 찬스 있음...? 다우너 누나의 특별 뒷 옵션~질퍽 미끈미끈 오망코 기승위♡ 고속 말뚝 박기 시술 (받을 수 있을지도 모른다)~
소리
키리안
04.22 16688 84
[Ai 후원] 팬텀 카와카미 마이 [314p]
야짤
Ghost
04.22 18808 19
[Ai 후원] 오등분 신부 요츠바 [359p]
야짤
Ghost
04.22 5554 20
[요청복구] 후타나리 검사와 마계의 소녀 / フタナリ剣士と魔界の少女
복구
crimson-hammer
04.22 23720 39
BBQ서클 DLC 내일출시
정보
sorbe123
04.22 6730 17
[구매보급/번역요청] RJ01586313 LOVING DEAD GIRL ラビング・デッド・ガール
미번
cookieasy
04.22 16653 58
[Miyahara Ayumu] 즉시 섹스! 최면 치트로 내 맘대로
동인
1uF
04.22 39283 148
[Jagayamatarawo] BEHIND THE MASK
동인
1uF
04.22 28424 99
[Kurumaya Koudou] 섹스가 목적인 거유 아싸 소녀에게 홀딱 반해도 되나요?
동인
1uF
04.22 33486 178
[Ai 후원] 금서 빵빵한 사텐 루이코 [57p]
야짤
Ghost
04.22 9192 20
[구매보급]도스케베 거유간호사가 더러운 자지에 봉사 해주는 이야기 ♪
소리
이름뭐하지
04.22 11779 54
(코이카츠) - "큰거"
유틸
pst0025
04.22 15866 66
[미번, 번역요청, TS, 구매보급][Uten ameka] 내 친구는 TS체질 6 전편
동인
dokidoki1411
04.22 11339 27
[요청복구] 기홍사 스칼렛~전설의 약초를 찾아~ver.1.05
복구
rubberduck
04.22 40484 96
(코이카츠) 큰거 올리기 전에 작은거
유틸
pst0025
04.22 18754 62
쿠로네의 곁에서 체험판 떳다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
정보
여동생킬러
04.22 21482 34
카프카 : 비밀의 스크립트 (스타레일)
영상
브레머튼
04.22 27068 101
버전업) RJ384983 NTRaholic (치호 NTR 계획) (V5.1.18) (26.03.02)
번역
딸ㄱ기맛
04.22 50393 291
AI번역 검수) NTR 방송 ─HAPPY BIRTHDAY─
번역
제로콜라라이트
04.22 105727 542