v2.0.1 업데이트
This commit is contained in:
BIN
lib/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
lib/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/config_loader.cpython-313.pyc
Normal file
BIN
lib/__pycache__/config_loader.cpython-313.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/file_manager.cpython-313.pyc
Normal file
BIN
lib/__pycache__/file_manager.cpython-313.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/logger.cpython-313.pyc
Normal file
BIN
lib/__pycache__/logger.cpython-313.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/po_handler.cpython-313.pyc
Normal file
BIN
lib/__pycache__/po_handler.cpython-313.pyc
Normal file
Binary file not shown.
BIN
lib/__pycache__/validator.cpython-313.pyc
Normal file
BIN
lib/__pycache__/validator.cpython-313.pyc
Normal file
Binary file not shown.
@ -13,6 +13,15 @@ if sys.platform == 'win32':
|
||||
import os
|
||||
os.system('') # ANSI escape sequences 활성화
|
||||
|
||||
# UTF-8 콘솔 출력 설정
|
||||
try:
|
||||
import ctypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
kernel32.SetConsoleCP(65001) # UTF-8 input
|
||||
kernel32.SetConsoleOutputCP(65001) # UTF-8 output
|
||||
except:
|
||||
pass
|
||||
|
||||
# ANSI 컬러 코드
|
||||
class Colors:
|
||||
RESET = '\033[0m'
|
||||
@ -113,8 +122,15 @@ class DSLogger:
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
self.logger.handlers.clear() # 기존 핸들러 제거
|
||||
|
||||
# 콘솔 핸들러
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
# 콘솔 핸들러 (UTF-8 강제)
|
||||
if sys.platform == 'win32':
|
||||
# Windows에서 UTF-8 출력 스트림 사용
|
||||
import io
|
||||
console_stream = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True)
|
||||
else:
|
||||
console_stream = sys.stdout
|
||||
|
||||
console_handler = logging.StreamHandler(console_stream)
|
||||
console_handler.setLevel(getattr(logging, console_level.upper()))
|
||||
console_handler.setFormatter(ColoredFormatter(colored=colored))
|
||||
self.logger.addHandler(console_handler)
|
||||
|
||||
@ -55,14 +55,16 @@ class POHandler:
|
||||
if po is None:
|
||||
return 0
|
||||
|
||||
# 미번역 항목 필터링
|
||||
# 전체 항목 및 미번역 항목 필터링
|
||||
total_entries = len([entry for entry in po if entry.msgid]) # msgid가 있는 항목만 카운트
|
||||
untranslated = [entry for entry in po if not entry.msgstr.strip()]
|
||||
|
||||
if not untranslated:
|
||||
self.logger.info('미번역 항목이 없습니다.')
|
||||
translated_count = total_entries
|
||||
self.logger.info(f'전체 {total_entries}개 항목 중 {translated_count}개 번역 완료 (100%)')
|
||||
return 0
|
||||
|
||||
self.logger.info(f'미번역 항목 {len(untranslated)}건 발견')
|
||||
self.logger.info(f'전체 {total_entries}개 항목 중 미번역 {len(untranslated)}건 발견')
|
||||
|
||||
# TSV 파일로 저장
|
||||
self._save_to_tsv(untranslated, output_path)
|
||||
@ -121,14 +123,7 @@ class POHandler:
|
||||
key = (msgctxt_escaped, source_location_escaped)
|
||||
|
||||
if key not in merged_data:
|
||||
merged_data[key] = {
|
||||
'msgid': msgid_escaped,
|
||||
'msgid_ko': None, # ko의 msgid를 별도로 저장
|
||||
}
|
||||
|
||||
# ko 언어의 msgid는 별도로 저장
|
||||
if lang_code == 'ko':
|
||||
merged_data[key]['msgid_ko'] = msgid_escaped
|
||||
merged_data[key] = {}
|
||||
|
||||
# 언어별 번역문 저장
|
||||
merged_data[key][lang_code] = msgstr_escaped
|
||||
@ -136,19 +131,14 @@ class POHandler:
|
||||
# CSV 레코드 생성
|
||||
records = []
|
||||
for (msgctxt, source_location), data in merged_data.items():
|
||||
# ko의 msgid가 있으면 우선 사용
|
||||
msgid = data.get('msgid_ko') if data.get('msgid_ko') else data.get('msgid')
|
||||
|
||||
record = {
|
||||
'msgctxt': msgctxt,
|
||||
'SourceLocation': source_location,
|
||||
'msgid': msgid,
|
||||
}
|
||||
|
||||
# 언어별 번역 추가
|
||||
for key, value in data.items():
|
||||
if key not in ['msgid', 'msgid_ko']:
|
||||
record[key] = value
|
||||
record[key] = value
|
||||
|
||||
records.append(record)
|
||||
|
||||
@ -160,10 +150,12 @@ class POHandler:
|
||||
all_langs = set()
|
||||
for record in records:
|
||||
all_langs.update(record.keys())
|
||||
all_langs -= {'msgctxt', 'SourceLocation', 'msgid'}
|
||||
all_langs -= {'msgctxt', 'SourceLocation'}
|
||||
|
||||
# 선호 순서: ko를 맨 앞에, en을 두 번째로
|
||||
source_lang = self.config.get('languages', {}).get('source', 'ko')
|
||||
preferred_order = [source_lang] + self.config.get('languages', {}).get('targets', [])
|
||||
|
||||
# 선호 순서
|
||||
preferred_order = self.config.get('languages', {}).get('targets', [])
|
||||
ordered_langs = [lang for lang in preferred_order if lang in all_langs]
|
||||
other_langs = sorted([lang for lang in all_langs if lang not in preferred_order])
|
||||
final_langs = ordered_langs + other_langs
|
||||
@ -172,7 +164,7 @@ class POHandler:
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(output_path, 'w', newline='', encoding='utf-8-sig') as f:
|
||||
fieldnames = ['msgctxt', 'SourceLocation', 'msgid'] + final_langs
|
||||
fieldnames = ['msgctxt', 'SourceLocation'] + final_langs
|
||||
writer = csv.DictWriter(f, fieldnames=fieldnames, quoting=csv.QUOTE_ALL)
|
||||
writer.writeheader()
|
||||
writer.writerows(records)
|
||||
@ -323,6 +315,8 @@ class POHandler:
|
||||
for lang in lang_codes:
|
||||
msgstr = row.get(lang, '')
|
||||
if msgstr: # 빈 문자열이 아니면 저장
|
||||
# TSV의 이스케이프된 줄바꿈을 실제 escape sequence로 변환
|
||||
msgstr = self._unescape_newlines(msgstr)
|
||||
translations_by_lang[lang][msgctxt] = msgstr
|
||||
|
||||
except Exception as e:
|
||||
|
||||
@ -180,15 +180,16 @@ class TranslationValidator:
|
||||
"""줄바꿈 문자 확인"""
|
||||
issues = []
|
||||
|
||||
# \r\n, \n, \r 개수 확인
|
||||
orig_crlf = original.count('\\r\\n')
|
||||
trans_crlf = translation.count('\\r\\n')
|
||||
# 실제 escape sequence (\r\n, \n, \r) 개수 확인
|
||||
# 주의: '\r\n'은 실제 CR+LF 문자 (2바이트), '\\r\\n'은 리터럴 문자열 (4바이트)
|
||||
orig_crlf = original.count('\r\n')
|
||||
trans_crlf = translation.count('\r\n')
|
||||
|
||||
orig_lf = original.count('\\n') - orig_crlf # \\r\\n에 포함된 \\n 제외
|
||||
trans_lf = translation.count('\\n') - trans_crlf
|
||||
orig_lf = original.count('\n') - orig_crlf # \r\n에 포함된 \n 제외
|
||||
trans_lf = translation.count('\n') - trans_crlf
|
||||
|
||||
orig_cr = original.count('\\r') - orig_crlf # \\r\\n에 포함된 \\r 제외
|
||||
trans_cr = translation.count('\\r') - trans_crlf
|
||||
orig_cr = original.count('\r') - orig_crlf # \r\n에 포함된 \r 제외
|
||||
trans_cr = translation.count('\r') - trans_crlf
|
||||
|
||||
if orig_crlf != trans_crlf or orig_lf != trans_lf or orig_cr != trans_cr:
|
||||
issues.append(ValidationIssue(
|
||||
|
||||
Reference in New Issue
Block a user