kone
sub_icon

소미소프트

파일 구글 번역기) kr_tr_7.pyw

2026-04-22 20:36:11
유틸
조회 12078 · 좋아요 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번역) [r-one] 「엄마 몸을 탈취한 알콩달콩♥ 육아일기」
동인
GGmen
05.23 18349 69
a290YXJvdTM5OTA= 작가 공유 74.5GB
영상
cmodmd
05.23 20869 118
(청아)[번역][모자이크감소] RJ127023 음란한 짐승의 우리 - 여고생 폐공장 감금 강간 (1.1A)
번역
ilillilllilil
05.23 43342 274
미번) [RJ01518150] M男いじめスクールライフ (번역링크)
미번
wave7535
05.23 6934 30
[구매보급/번역요청] 카네다는 나쁘지 않아 vol.4 金田は何も悪くない Vol.04
동인
eggslut
05.23 17848 58
VmVjdG9yQ2VsbA== 작가 공유 43GB
영상
cmodmd
05.23 22015 123
(코이카츠) 엔드필드 프리셋 공유
유틸
pst0025
05.23 8617 65
(청아) 꾸준실패 연필 32주차
창작
지나가던사람
05.23 4617 21
[AI,빵] ぬるぬるアニメ,なめらか動画部 시리즈 모음
영상
도가다
05.23 16544 95
EnigmaVBUnpacker (MV MZ 언팩) 웹버전 오픈
유틸
mrpls
05.23 4042 15
Kakuchou No Okina-Gaping JK
동인
k8625
05.23 20666 56
키타키타
정보
F1_code
05.23 7712 22
Kakuchou No Okina-익스트림 애널 헌터
동인
k8625
05.23 17608 63
Yutsuki Tsuzuri-화장실 괴담 하나코 따먹는 만화
동인
k8625
05.23 16569 64
마마야 유부녀 알바 2.5편 썸네일 식질
작업현황
1Q2W3E4R
05.23 4754 18
컴도 못끄고 VPN도 못켜고...
작업현황
ㅇㅇ
05.23 5228 30
엽빛나 & 와이즈 (ZZZ)
영상
브레머튼
05.23 14538 101
[Ginger Lily] 마사지숍에서 후타나리 미녀에게 포르치오 절정으로 길들여지는 여자아이
동인
1uF
05.23 21150 176
[Hirari] 남장 플레이어 코스 ROM 촬영
동인
1uF
05.23 11597 34
[Hirari] 내가 모르는 너의
동인
1uF
05.23 15542 62
[전개방세이브] 히로인을 붙잡아 놓고 아무것도 하지 않을 리가 없다
세이브
미스터장
05.23 5675 22
[직번] [Carrot Caramel Batake] 회장과 교실
동인
maha1004
05.23 15263 27
[구매보급]【저음 오호 목소리·밀착 귀 핥기】왕자님 카페~소녀 같은 루이와 러브러브 밀회
소리
이름뭐하지
05.23 8598 68
직번) [Yamamoto Zenzen] 학원원교일기 Comix 3화
동인
qlalfsla
05.23 16406 86
[요청복구][3D/여주/노출][버전업/한글지원/노모] 비밀 노출 -배덕의 달콤함에 물든 마나카- v1.13
복구
zeri1590
05.23 25078 66
ai) chui 요르 움짤
야짤
Ghost
05.23 7888 42
[요청복구] [RJ01604961] PACHIMON 8bit 노모,일반버전
복구
tenXX
05.23 25815 87
[보이스코믹][구매보급][한] 거대한 가슴에 통통한 무녀에게 아헤 얼굴과 오호 소리로 착취당하다
소리
책먹는망아지
05.23 14719 115
RJ01394659 가짜 세계수의 무녀 ~거리 한복판에서 마음껏 더듬기 & 에로 트랩으로 갸루 겟츄~(세이브파일 빼먹어서 링크 하나 더 추가)
복구
ruel-x
05.23 18981 36
[구매보급,복구요청 2개 + 요청X 1개]RJ01303046, RJ127023, RJ112298
미번
ruel-x
05.23 10063 105