feat: 존댓말/반말 모드, 포터블 exe 빌드, AI 로고/배너
말투 (존댓말 기본, 반말 선택) - 원문이 실제로 존댓말이면 반말 모드여도 존댓말을 지킨다. 상대가 정중하게 말했는데 자막이 반말이면 뉘앙스가 뒤집히기 때문. - 영어·중국어는 문법적 높임이 없으므로 항상 고른 모드를 따른다. "please" 를 존댓말 근거로 삼으면 오탐이 많아 쓰지 않았다. - 낮춤 변환은 한글 자모를 분해해 실제 활용 규칙(모음조화 + 축약)을 구현했다. 오+아->와, 지+어->져, 하+어->해, 았/었 뒤는 항상 어, 치겠습니다->칠게. 어미를 나열하는 방식보다 훨씬 넓게 맞는다. - 변환 방향은 존댓말->반말 한쪽만 한다. 번역 모델의 한국어 출력이 이미 격식체라 존댓말 모드는 손댈 필요가 없고, 반대 방향은 훨씬 자주 틀린다. - 지시문을 이해하는 Qwen3 에는 프롬프트로도 전달한다. Seed-X 는 지시문을 못 알아듣는 모델이라 후처리로만 맞춘다. 포터블 exe - PyInstaller 명세 + 빌드 스크립트. torch 를 의도적으로 제외했다. torch+CUDA 만 2.5GB 라 onefile 로 묶으면 실행할 때마다 그걸 임시폴더에 푸느라 1분 넘게 걸려 쓸 수 없다. - 음성인식(faster-whisper)도 번역(NLLB)도 CTranslate2 위에서 돌아 torch 가 필요 없다. 덕분에 1~3티어는 그대로 다 되고 exe 는 3GB -> 500MB 가 된다. - 4~5티어는 못 쓰므로 tier_availability() 로 판정해 모델 화면에 '사용 불가'와 이유를 표시한다. torch 없는 환경에서 앱 전체가 뜨는 것을 확인했다. AI 이미지 - SDXL-turbo 로 아이콘/배경 생성 (로컬 GPU, 피크 VRAM 1.9GB). - 글자는 AI 가 제대로 못 쓰므로 아트만 AI 로 만들고 타이포그래피는 정확히 렌더링해 합성했다. icon.ico 는 16~256px 멀티해상도. 검증: pytest 163개 통과 (말투 53개 신규), ruff clean Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -102,6 +102,22 @@ class HomePage(QWidget):
|
||||
layout.addWidget(arrow)
|
||||
layout.addWidget(QLabel("번역"))
|
||||
layout.addWidget(self.target_lang)
|
||||
|
||||
self.speech_combo = QComboBox()
|
||||
self.speech_combo.addItem("존댓말", "polite")
|
||||
self.speech_combo.addItem("반말", "casual")
|
||||
self.speech_combo.setCurrentIndex(
|
||||
max(0, self.speech_combo.findData(self.config.models.speech_level))
|
||||
)
|
||||
self.speech_combo.setToolTip(
|
||||
"한국어 자막의 말투입니다.\n"
|
||||
"반말을 골라도 원문이 실제로 존댓말이면 존댓말로 나옵니다.\n"
|
||||
"영어·중국어처럼 높임이 없는 언어는 이 설정을 그대로 따릅니다."
|
||||
)
|
||||
self.speech_combo.currentIndexChanged.connect(self._on_lang_changed)
|
||||
layout.addWidget(QLabel("말투"))
|
||||
layout.addWidget(self.speech_combo)
|
||||
|
||||
layout.addStretch(1)
|
||||
|
||||
self.status_pill = StatusPill()
|
||||
@@ -182,6 +198,9 @@ class HomePage(QWidget):
|
||||
def _on_lang_changed(self, *_) -> None:
|
||||
self.config.models.source_lang = self.source_lang.currentData()
|
||||
self.config.models.target_lang = self.target_lang.currentData()
|
||||
self.config.models.speech_level = self.speech_combo.currentData()
|
||||
# 한국어가 아니면 말투 규칙을 적용할 데가 없다.
|
||||
self.speech_combo.setEnabled(self.config.models.target_lang == "ko")
|
||||
self.config_changed.emit()
|
||||
|
||||
def _on_toggle(self) -> None:
|
||||
@@ -209,6 +228,9 @@ class HomePage(QWidget):
|
||||
|
||||
for widget in (self.source_combo, self.source_lang, self.target_lang):
|
||||
widget.setEnabled(not running)
|
||||
self.speech_combo.setEnabled(
|
||||
not running and self.config.models.target_lang == "ko"
|
||||
)
|
||||
|
||||
def on_line(self, line: TranslationLine) -> None:
|
||||
if not line.is_final:
|
||||
|
||||
Reference in New Issue
Block a user