kone
sub_icon

소미소프트

파일 구글 번역기) kr_tr_7.pyw

2026-04-22 20:36:11
유틸
조회 12178 · 좋아요 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
ai,청아,버튜버)코코로쨩 마이크로비키니
야짤
gpsel157
05.12 19135 26
이전에 가지고 있던 것 복구(10개)
복구
ziririri123
05.12 51257 169
[LYCO]리오&토키 처벌쇼
영상
ㅇㅇ
05.12 35202 83
古い(furui) 모음
영상
쀏꿱이
05.12 35217 159
ガナイショウ(가나이쇼우) 26.3. 눈나
야짤
kuuki
05.12 10502 41
회복술사의 재시작 서비스씬 모음
영상
고죠/센세
05.12 41714 206
[90일복구] 요청자료 5종
복구
Ghost
05.12 41857 110
[AI번역/초반검수] 쾌락의 저주(The Curse of Pleasure) v1.0
번역
weller703
05.12 72411 245
대리업로드 번역게임 6개
번역
미스터장
05.12 76439 246
[한글자막] [NightHawk(ナイトホーク)] incest village インセストヴィレッジ
영상
lximiad
05.12 29560 73
Ai번역) 여동생의 친구가 동경하던 G컵 갸루 코스플레이어였던 이야기 2
동인
customer121
05.12 29395 180
[구매보급] [버전업] RJ01452526 이상적인 히키코모리 생활 ~부녀의 꽁냥꽁냥 동거~ 1.1.6 26.05.12 "26.05.22(수정)"
번역
gkqisq
05.12 34637 174
[GIF] (후타, 보추, 수?간 포함) QW1wbGVjdGVk gif 모음집
야짤
hannanas
05.12 14179 47
AI, 셀레스포니아) 아마네 데이트편
야짤
miso5
05.12 11497 112
[버전업] [구매보급] RJ01588884 이노센트 도터 v1.1.1
미번
gkqisq
05.12 11267 45
QW1wbGVjdGVk 모음집 없데이트 알림
영상
hannanas
05.12 22879 81
[구매보급] RJ432000 성처리가 있는 학교 2023.04.26
미번
gkqisq
05.12 16667 35
(요청복구, 미검수) Cursed Armor 2
복구
zeri1590
05.12 17772 49
[미번] 오네쇼타 마을의 엣치한 여름방학 스팀 노모 일어판
미번
미스터장
05.12 9608 44
[atahuta] 발정기 한창 오나홀 씨.
동인
ㅇㅇ
05.12 42188 276
[Croriin/노모] 마녀가 아끼는 것
동인
ㅇㅇ
05.12 25137 160
감각 차단 암컷화 트랩! 손번역 및 노모작업 현황
작업현황
미스터장
05.12 12244 36
[ai번역=오오토리 마히로] 나의 이세계 하렘 1
동인
mybest
05.12 16892 42
[유부녀/레이프/밀프쇼타/서양](보루토) 히나타의 숨겨진 욕망
영상
Ghost
05.12 29064 117
[한글자막] 미시 여교사, 쇼타 사정 도와주기 (上편)
영상
실루엣21
05.12 18149 97
QW1wbGVjdGVk 블렌더 파일 공유 첫번째 9.74GB
유틸
hannanas
05.12 15550 21
[bWlyYWNhbg== / RJ01602232] 전생 용사가 즉시 함락 마법으로 이세계 무쌍!! [전편]
영상
yozuna
05.12 26317 178
요몽원 이미지 번역하면 수요 있나?
일반
losress
05.12 5683 55
미번) [airu] 폭유에 엉덩이가 커다란 흑장발 무녀씨에게 사랑이 무거운 개변태봉사로 쥐어짜인다
동인
hun99
05.12 13794 26
[AI/이미지번역] Esurience 일본풍 미인 소꿉친구와 숨겨진 갈망
번역
미식이네
05.12 38181 168