v2.0.1 업데이트

This commit is contained in:
Gnill82
2025-10-29 15:35:54 +09:00
parent e189a64631
commit 0482c8299b
44 changed files with 89080 additions and 718 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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)

View File

@ -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:

View File

@ -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(