Files
DS_L10N/archive/ver1.0/po_extract_untranslated.py

107 lines
4.6 KiB
Python
Raw Normal View History

2025-09-11 00:56:02 +09:00
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()