import tkinter as tk from tkinter import filedialog import polib import datetime import os import csv def find_first_source_location(entry): """ POEntry 객체에서 첫 번째 SourceLocation을 찾아 반환합니다. SourceLocation은 '#: FileOrPath' 형식의 주석(occurrence)에서 가져옵니다. """ # entry.occurrences는 (파일경로, 라인번호) 형태의 튜플 리스트입니다. # 이 리스트에 값이 있는지 확인합니다. if entry.occurrences: # 첫 번째 occurrence 튜플의 첫 번째 요소(파일 경로)를 반환합니다. return entry.occurrences[0][0] return "" # occurrence 정보가 없으면 빈 문자열 반환 def extract_untranslated_to_csv(): """ PO 파일을 선택하여 번역되지 않은 항목의 msgctxt, SourceLocation, msgid를 타임스탬프가 포함된 CSV 파일로 저장합니다. 줄바꿈 태그(\r\n)를 그대로 보존합니다. """ # --- 1. 파일 선택 GUI 실행 --- root = tk.Tk() root.withdraw() # tk의 기본 창은 숨깁니다. print("PO 파일을 선택해주세요...") # 파일 탐색기 창을 열어 사용자로부터 PO 파일 경로를 입력받습니다. file_path = filedialog.askopenfilename( title="번역을 추출할 PO 파일을 선택하세요", filetypes=(("PO Files", "*.po"), ("All files", "*.*")) ) if not file_path: print("파일이 선택되지 않았습니다. 작업을 중단합니다.") return print(f"선택된 파일: {file_path}") try: # --- 2. PO 파일 로드 및 처리 --- po = polib.pofile(file_path, encoding='utf-8') # 번역되지 않은 항목 필터링 (msgstr이 비어있는 항목) untranslated_entries = [entry for entry in po if not entry.msgstr.strip()] if not untranslated_entries: print("번역이 누락된 항목을 찾을 수 없습니다.") return # --- 3. 타임스탬프를 포함한 결과 CSV 파일 저장 --- timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") output_dir = os.path.dirname(file_path) # 저장할 파일명을 .csv 확장자로 변경 output_filename = f"untranslated_{timestamp}.csv" output_path = os.path.join(output_dir, output_filename) # CSV 파일 쓰기 시작 (UTF-8 BOM 추가로 Excel 한글 깨짐 방지) with open(output_path, 'w', newline='', encoding='utf-8-sig') as csvfile: # 표준 CSV 라이터 생성 (쉼표 구분자 사용) writer = csv.writer(csvfile, quoting=csv.QUOTE_ALL) # 헤더(컬럼명) 작성 writer.writerow(['msgctxt', 'SourceLocation', 'msgid']) # 번역되지 않은 항목들을 순회하며 데이터 추출 및 저장 for entry in untranslated_entries: # occurrence에서 SourceLocation 정보 추출 source_location = find_first_source_location(entry) # msgid의 줄바꿈을 \r\n 문자열로 보존 # polib은 \r\n을 실제 줄바꿈로 해석하므로 # 다시 \r\n 문자열로 치환해야 함 msgid_escaped = entry.msgid # 실제 줄바꿈을 \r\n 문자열로 치환 msgid_escaped = msgid_escaped.replace('\r\n', '\\r\\n') msgid_escaped = msgid_escaped.replace('\n', '\\n') msgid_escaped = msgid_escaped.replace('\r', '\\r') # msgctxt와 msgstr에도 동일하게 적용 (필요시) msgctxt_escaped = (entry.msgctxt or '').replace('\r\n', '\\r\\n').replace('\n', '\\n').replace('\r', '\\r') # 요청된 3가지 컬럼의 데이터를 행으로 작성 writer.writerow([msgctxt_escaped, source_location, msgid_escaped]) print("-" * 50) print(f"총 {len(untranslated_entries)}개의 번역되지 않은 항목을 추출했습니다.") print(f"결과가 CSV 형식으로 다음 경로에 저장되었습니다: {output_path}") print("-" * 50) except Exception as e: print(f"오류가 발생했습니다: {e}") if __name__ == "__main__": # --- 스크립트 실행 전 라이브러리 설치 확인 --- try: import polib except ImportError: print("스크립트 실행에 필요한 'polib' 라이브러리가 설치되지 않았습니다.") print("터미널(cmd)에서 아래 명령어를 실행하여 설치해주세요.") print("pip install polib") else: extract_untranslated_to_csv()