"""
경량 i18n.

`tr('key')` → 현재 언어의 번역 문자열. 키 미존재 시 ko 폴백, ko도 없으면
키 그대로 반환 (미번역도 동작). 점진 도입 가능.

새 언어 추가:
1. _DICT['en'] 옆에 'ja'/'zh' 등 추가
2. 사용자가 설정 → 언어 콤보에서 선택
"""
from __future__ import annotations

_current_lang = 'ko'

_DICT = {
    'ko': {
        # === 메뉴/버튼 ===
        'menu.stats': '통계',
        'menu.calendar': '캘린더',
        'menu.daily_report': '일일보고',
        'menu.help': '도움말',
        'menu.settings': '설정',
        'btn.clock_out': '퇴근하기',
        'btn.clock_out_cancel': '퇴근 취소',
        'btn.lunch_add': '점심시간 추가',
        'btn.lunch_applied': '점심시간 (적용됨)',
        'btn.dinner_add': '저녁시간 추가',
        'btn.dinner_applied': '저녁시간 (적용됨)',
        'btn.break_out': '외출 시작',
        'btn.break_in': '복귀',
        'btn.save': '저장',
        'btn.close': '닫기',
        'btn.apply': '적용',
        'btn.cancel': '취소',
        'btn.add': '추가',
        'btn.delete': '삭제',
        'btn.edit': '편집',
        'btn.confirm': '확인',
        'btn.ok': '확인',

        # === 윈도우/다이얼로그 제목 ===
        'window.main_title': '퇴근시간 계산기',
        'window.settings': '설정',
        'window.help': '사용 설명서',
        'window.stats': '근무 통계',
        'window.calendar': '캘린더',
        'window.mini_widget': '퇴근시간',
        'window.clock_in_dialog': '출근 시간',
        'window.break_view': '외출 관리',
        'window.overtime_view': '연장근무 관리',
        'window.leave_view': '연차 관리',

        # === 라벨 ===
        'label.remaining': '남은 시간',
        'label.overtime_progress': '추가 근무 중',
        'label.expected_clock_out': '예상 퇴근',
        'label.clock_in_time': '출근 시간',
        'label.clock_out_time': '퇴근 시간',
        'label.work_hours_label': '하루 기본 근무:',
        'label.lunch_default': '점심시간 기본:',
        'label.dinner_default': '저녁시간 기본:',
        'label.work_pattern': '근무 패턴:',
        'label.time_format': '시간 형식:',
        'label.theme': '테마:',
        'label.language': '언어 / Language:',
        'label.unit_hour': '시간',
        'label.unit_minute': '분',
        'label.unit_day': '일',
        'label.unit_count': '개',
        'label.weekday_mon': '월',
        'label.weekday_tue': '화',
        'label.weekday_wed': '수',
        'label.weekday_thu': '목',
        'label.weekday_fri': '금',
        'label.weekday_sat': '토',
        'label.weekday_sun': '일',
        'label.am': '오전',
        'label.pm': '오후',

        # === 알림 ===
        'notif.clock_out_soon.title': '⏰ 퇴근 시간 임박',
        'notif.clock_out_soon.body': '퇴근까지 {minutes}분 남았습니다.\n마무리 준비를 시작하세요!',
        'notif.lunch_reminder.title': '🍱 점심시간 등록',
        'notif.lunch_reminder.body': '점심시간을 등록하지 않으셨네요.\n점심시간을 추가하시겠어요?',
        'notif.dinner_reminder.title': '🍽️ 저녁시간 등록',
        'notif.dinner_reminder.body': '저녁시간을 등록하지 않으셨네요.\n저녁시간을 추가하시겠어요?',

        # === 온보딩 근무 패턴 프리셋 ===
        'onboarding.preset.standard_8h': '표준 8시간 (점심 60분)',
        'onboarding.preset.short_7h30m': '단축근무 7시간 30분 (점심 30분)',
        'onboarding.preset.short_7h': '단축근무 7시간 (점심 60분)',
        'onboarding.preset.short_6h': '단축근무 6시간 (점심 30분)',
        'onboarding.preset.half_4h': '반일 4시간 (점심 0분)',
        'onboarding.preset.custom_box': '사용자 정의',
        'onboarding.preset.custom_radio': '직접 입력:',
        'onboarding.preset.suffix_hours': ' 시간',
        'onboarding.preset.suffix_minutes': ' 분',
        'onboarding.preset.lunch_prefix': '점심 ',
        'onboarding.preset.dinner_prefix': '저녁 ',
        'onboarding.preset.dinner_tooltip': '야근으로 저녁 식사가 자주 발생하면 입력 (보통 0~60분)',
        'notif.health_break.title': '🌿 휴식 권고',
        'notif.health_break.body': '{hours}시간 이상 자리에 계셨습니다.\n잠시 일어나서 스트레칭하세요.',
        'notif.overtime_earning.title': '🔥 연장근무 적립 예정',
        'notif.overtime_earning.body': '오늘 {time_str}의 연장근무가 적립될 예정입니다!',
        'notif.overtime_threshold.title': '💰 연장근무 적립 알림',
        'notif.overtime_threshold.body': '적립된 연장근무가 {hours:.1f}시간 입니다.\n사용을 고려해보세요!',
        'notif.health.title': '⚠️ 건강 경고',
        'notif.health.body': '{days}일 연속 연장근무 중입니다.\n건강을 챙기세요!',
        'notif.weekly_52.title': '🚨 주 52시간 초과',
        'notif.weekly_52.body': '이번 주 총 근무시간이 {hours:.1f}시간입니다.\n법정 근로시간을 초과했습니다!',

        # === 메시지박스 ===
        'msg.save_success.title': '저장 완료',
        'msg.save_success.body': '설정이 저장되었습니다.',
        'msg.input_error.title': '입력 오류',
        'msg.work_min_too_small': '하루 기본 근무 시간은 최소 30분 이상이어야 합니다.',
        'msg.no_clock_in.title': '외출 불가',
        'msg.no_clock_in.body': '출근하지 않은 상태입니다.',
        'msg.already_break.body': '이미 외출 중입니다.',
        'msg.no_record.title': '기록 없음',
        'msg.no_record.body': '오늘 출근 기록이 없습니다.',
        'msg.confirm_delete.title': '삭제 확인',
        'msg.no_data.title': '데이터 없음',
        'msg.manual_added': '수동 추가',

        # === 트레이 ===
        'tray.open': '프로그램 열기',
        'tray.mini_widget': '미니 위젯',
        'tray.toggle_lunch': '점심시간 토글',
        'tray.quit': '종료',
        'tray.tooltip_remaining': '퇴근까지: {time}',
        'tray.tooltip_overtime': '추가 근무 중: {time}',
        'tray.background': '프로그램이 트레이에서 실행 중입니다.',

        # === 그룹 박스 ===
        'group.work_time': '근무 시간 설정',
        'group.notification': '알림 및 표시 설정',
        'group.overtime': '연장근무 설정',
        'group.leave': '휴가 설정',
        'group.holiday': '공휴일 설정',
        'group.data': '데이터 관리',

        # === StatsView ===
        'stats.title': '근무 통계',
        'stats.tab_weekly': '주간',
        'stats.tab_monthly': '월간',
        'stats.tab_pattern': '패턴 분석',
        'stats.weekly_summary': '이번 주 요약',
        'stats.monthly_summary': '이번 달 요약',
        'stats.total_hours': '총 근무시간:',
        'stats.work_days': '근무일수:',
        'stats.avg_hours': '평균 근무시간:',
        'stats.total_overtime': '총 연장근무:',
        'stats.pattern_insights': '근무 패턴 인사이트',
        'stats.analyzing': '데이터를 분석 중입니다...',
        'stats.no_data': '아직 충분한 데이터가 없습니다.',

        # === CalendarView ===
        'cal.title': '월간 근무 캘린더',
        'cal.year_label': '년',
        'cal.month_label': '월',
        'cal.prev': '◀ 이전',
        'cal.next': '다음 ▶',
        'cal.today': '오늘',
        'cal.no_record': '기록 없음',
        'cal.edit_record': '기록 편집',

        # === HelpView (각 탭의 큰 HTML은 별도 키) ===
        'help.tab_intro': '시작하기',
        'help.tab_work_hours': '근무시간',
        'help.tab_overtime': '연장근무',
        'help.tab_leave': '연차/휴가',
        'help.tab_break': '외출/저녁',
        'help.tab_faq': '자주 묻는 질문',

        # === clock_in_dialog ===
        'dlg.clock_in.prompt': '오늘의 출근시간을 입력해주세요',
        'dlg.clock_in.label': '출근시간:',
        'dlg.clock_in.quick': '빠른 선택:',
        'dlg.clock_in.btn_now': '현재',

        # === break_view ===
        'dlg.break.edit_title': '외출 기록 수정',
        'dlg.break.out_label': '외출 시간:',
        'dlg.break.in_label': '복귀 시간:',
        'dlg.break.reason_label': '사유:',
        'view.break.today_title': '오늘의 외출 기록',
        'view.break.col_out': '외출 시간',
        'view.break.col_in': '복귀 시간',
        'view.break.col_duration': '소요 시간',
        'view.break.col_reason': '사유',
        'view.break.in_progress': '진행중',
        'view.break.total_zero': '총 외출 시간: 0분',
        'view.break.total_fmt': '총 외출 시간: {h}시간 {m}분',
        'view.break.total_min_only': '총 외출 시간: {m}분',
        'view.break.duration_fmt': '{h}시간 {m}분',
        'view.break.duration_min_only': '{m}분',
        'view.break.delete_confirm': '이 외출 기록을 삭제하시겠습니까?',
        'btn.refresh': '새로고침',
        'btn.edit_short': '수정',
        'btn.delete_short': '삭제',

        # === overtime_view ===
        'view.overtime.title': '연장근무 내역',
        'view.overtime.balance_zero': '잔액: 0분',
        'view.overtime.balance_fmt': '현재 잔액: {h}시간 {m}분 ({total}분)',
        'view.overtime.earned_group': '적립 내역',
        'view.overtime.used_group': '사용 내역',
        'view.overtime.col_date': '날짜',
        'view.overtime.col_earned': '적립',
        'view.overtime.col_used': '사용',
        'view.overtime.col_memo': '메모',
        'view.overtime.col_reason': '사유',
        'view.overtime.btn_add_earned': '수동 적립',
        'view.overtime.btn_add_used': '수동 사용',
        'view.overtime.menu_delete': '삭제',
        'view.overtime.delete_confirm_body': '다음 사용 기록을 삭제하시겠습니까?\n\n날짜: {date}\n시간: {time}\n사유: {reason}',
        'view.overtime.delete_earned_confirm_body': '다음 적립 기록을 삭제하시겠습니까?\n\n날짜: {date}\n적립: {time}\n\n삭제 시 잔액에서 차감됩니다.',
        'view.overtime.manual_earned_title': '추가근무 수동 적립',
        'view.overtime.manual_used_title': '추가근무 수동 사용',
        'view.overtime.field_date': '날짜:',
        'view.overtime.field_time': '시간:',
        'view.overtime.field_memo': '메모:',
        'view.overtime.field_reason': '사유:',
        'view.overtime.unit_hour_suffix': '시간',
        'view.overtime.minute_0': '0분',
        'view.overtime.minute_30': '30분',
        'view.overtime.placeholder_memo': '선택사항',
        'view.overtime.placeholder_reason': '예: 개인 사유',
        'view.overtime.zero_add_error': '0분은 추가할 수 없습니다.',
        'view.overtime.zero_use_error': '0분은 사용할 수 없습니다.',
        'view.overtime.balance_short_title': '잔액 부족',
        'view.overtime.balance_short_body': '사용 가능한 시간이 부족합니다.\n\n요청: {req_h}시간 {req_m}분\n잔액: {bal_h}시간 {bal_m}분',
        'view.overtime.saved_earned': '{h}시간 {m}분이 적립되었습니다.',
        'view.overtime.saved_used': '{h}시간 {m}분이 사용 처리되었습니다.',

        # === leave_view ===
        'view.leave.title': '연차 관리',
        'view.leave.balance_zero': '잔여: 0일',
        'view.leave.balance_fmt': '잔여: {days}일 (총 {hours}시간)',
        'view.leave.btn_set_balance': '잔여 설정',
        'view.leave.used_group': '사용 내역',
        'view.leave.col_date': '날짜',
        'view.leave.col_type': '구분',
        'view.leave.col_used': '사용',
        'view.leave.col_reason': '사유',
        'view.leave.btn_add': '연차 사용 추가',
        'view.leave.btn_calendar': '캘린더 보기',
        'view.leave.delete_confirm_body': '다음 연차 사용 기록을 삭제하시겠습니까?\n\n날짜: {date}\n구분: {type}\n사용: {days}',
        'view.leave.set_title': '연차 시간 설정',
        'view.leave.set_prompt': '연차 잔여 시간을 입력하세요 (0.5시간 단위):\n예) 8시간 = 1일, 4시간 = 0.5일(반차), 2시간 = 0.25일, 0.5시간 = 30분',
        'view.leave.set_done_title': '설정 완료',
        'view.leave.set_done_body': '연차 잔여 개수가 {days}일 ({hours}시간)로 설정되었습니다.',
        'view.leave.add_title': '연차 사용 기록 추가',
        'view.leave.field_date': '날짜:',
        'view.leave.field_type': '구분:',
        'view.leave.field_hours': '시간:',
        'view.leave.field_reason': '사유:',
        'view.leave.type_annual': '연차',
        'view.leave.type_half': '반차',
        'view.leave.type_quarter': '반반차',
        'view.leave.type_hourly': '시간',
        'view.leave.placeholder_reason': '예) 개인 사유, 병원 방문 등',
        'view.leave.note_auto_deduct': '※ 잔여 연차가 자동 차감됩니다.',
        'view.leave.short_title': '잔여 연차 부족',
        'view.leave.short_body': '잔여 연차가 부족합니다.\n현재 잔여: {balance}일\n사용 요청: {req}일',
        'view.leave.confirm_title': '연차 사용 기록 추가',
        'view.leave.confirm_body': '날짜: {date}\n구분: {type}\n사용: {days}일 ({hours}시간)\n사유: {reason}\n\n이 기록을 추가하시겠습니까?',
        'view.leave.added_title': '추가 완료',
        'view.leave.added_body': '{days}일 ({hours}시간)의 연차 사용이 기록되었습니다.',
        'view.leave.error_title': '오류',
        'view.leave.error_body': '연차 기록 추가 중 오류가 발생했습니다:\n{err}',
    },
    'en': {
        # === Menu/Buttons ===
        'menu.stats': 'Stats',
        'menu.calendar': 'Calendar',
        'menu.daily_report': 'Daily Report',
        'menu.help': 'Help',
        'menu.settings': 'Settings',
        'btn.clock_out': 'Clock Out',
        'btn.clock_out_cancel': 'Cancel Clock-out',
        'btn.lunch_add': 'Add Lunch',
        'btn.lunch_applied': 'Lunch (Applied)',
        'btn.dinner_add': 'Add Dinner',
        'btn.dinner_applied': 'Dinner (Applied)',
        'btn.break_out': 'Start Break',
        'btn.break_in': 'Return',
        'btn.save': 'Save',
        'btn.close': 'Close',
        'btn.apply': 'Apply',
        'btn.cancel': 'Cancel',
        'btn.add': 'Add',
        'btn.delete': 'Delete',
        'btn.edit': 'Edit',
        'btn.confirm': 'Confirm',
        'btn.ok': 'OK',

        # === Windows ===
        'window.main_title': 'Clock-out Time Calculator',
        'window.settings': 'Settings',
        'window.help': 'User Guide',
        'window.stats': 'Statistics',
        'window.calendar': 'Calendar',
        'window.mini_widget': 'Clock-out',
        'window.clock_in_dialog': 'Clock-in Time',
        'window.break_view': 'Break Management',
        'window.overtime_view': 'Overtime Management',
        'window.leave_view': 'Leave Management',

        # === Labels ===
        'label.remaining': 'Remaining',
        'label.overtime_progress': 'Overtime',
        'label.expected_clock_out': 'Expected Clock-out',
        'label.clock_in_time': 'Clock-in Time',
        'label.clock_out_time': 'Clock-out Time',
        'label.work_hours_label': 'Daily work:',
        'label.lunch_default': 'Lunch break:',
        'label.dinner_default': 'Dinner break:',
        'label.work_pattern': 'Work pattern:',
        'label.time_format': 'Time format:',
        'label.theme': 'Theme:',
        'label.language': 'Language / 언어:',
        'label.unit_hour': 'h',
        'label.unit_minute': 'min',
        'label.unit_day': 'day(s)',
        'label.unit_count': '',
        'label.weekday_mon': 'Mon',
        'label.weekday_tue': 'Tue',
        'label.weekday_wed': 'Wed',
        'label.weekday_thu': 'Thu',
        'label.weekday_fri': 'Fri',
        'label.weekday_sat': 'Sat',
        'label.weekday_sun': 'Sun',
        'label.am': 'AM',
        'label.pm': 'PM',

        # === Notifications ===
        'notif.clock_out_soon.title': '⏰ Clock-out Soon',
        'notif.clock_out_soon.body': "{minutes} minutes until clock-out.\nWrap things up!",
        'notif.lunch_reminder.title': '🍱 Lunch Reminder',
        'notif.lunch_reminder.body': "You haven't registered lunch yet.\nWant to add it?",
        'notif.dinner_reminder.title': '🍽️ Dinner Reminder',
        'notif.dinner_reminder.body': "You haven't registered dinner yet.\nWant to add it?",

        # === Onboarding work pattern presets ===
        'onboarding.preset.standard_8h': 'Standard 8h (Lunch 60min)',
        'onboarding.preset.short_7h30m': 'Reduced 7h 30m (Lunch 30min)',
        'onboarding.preset.short_7h': 'Reduced 7h (Lunch 60min)',
        'onboarding.preset.short_6h': 'Reduced 6h (Lunch 30min)',
        'onboarding.preset.half_4h': 'Half-day 4h (No Lunch)',
        'onboarding.preset.custom_box': 'Custom',
        'onboarding.preset.custom_radio': 'Manual entry:',
        'onboarding.preset.suffix_hours': ' h',
        'onboarding.preset.suffix_minutes': ' min',
        'onboarding.preset.lunch_prefix': 'Lunch ',
        'onboarding.preset.dinner_prefix': 'Dinner ',
        'onboarding.preset.dinner_tooltip': 'Set if you often have dinner during overtime (typically 0~60 min)',
        'notif.health_break.title': '🌿 Take a Break',
        'notif.health_break.body': "You've been at your desk for over {hours} hours.\nStand up and stretch!",
        'notif.overtime_earning.title': '🔥 Overtime Will Accrue',
        'notif.overtime_earning.body': "{time_str} of overtime will be banked today!",
        'notif.overtime_threshold.title': '💰 Overtime Balance High',
        'notif.overtime_threshold.body': "{hours:.1f} hours of overtime banked.\nConsider using some.",
        'notif.health.title': '⚠️ Health Warning',
        'notif.health.body': "{days} consecutive days of overtime.\nTake care of your health!",
        'notif.weekly_52.title': '🚨 Weekly 52h Exceeded',
        'notif.weekly_52.body': "This week's total work hours: {hours:.1f}\nLegal limit exceeded!",

        # === Message Boxes ===
        'msg.save_success.title': 'Saved',
        'msg.save_success.body': 'Settings saved successfully.',
        'msg.input_error.title': 'Input Error',
        'msg.work_min_too_small': 'Daily work time must be at least 30 minutes.',
        'msg.no_clock_in.title': 'Cannot Take Break',
        'msg.no_clock_in.body': 'Not clocked in.',
        'msg.already_break.body': 'Already on break.',
        'msg.no_record.title': 'No Record',
        'msg.no_record.body': 'No clock-in record for today.',
        'msg.confirm_delete.title': 'Confirm Delete',
        'msg.no_data.title': 'No Data',
        'msg.manual_added': 'Manual',

        # === Tray ===
        'tray.open': 'Open Program',
        'tray.mini_widget': 'Mini Widget',
        'tray.toggle_lunch': 'Toggle Lunch',
        'tray.quit': 'Quit',
        'tray.tooltip_remaining': 'Until clock-out: {time}',
        'tray.tooltip_overtime': 'Overtime: {time}',
        'tray.background': 'Program is running in the tray.',

        # === Groups ===
        'group.work_time': 'Work Time Settings',
        'group.notification': 'Notifications & Display',
        'group.overtime': 'Overtime Settings',
        'group.leave': 'Leave Settings',
        'group.holiday': 'Holidays',
        'group.data': 'Data Management',

        # === StatsView ===
        'stats.title': 'Work Statistics',
        'stats.tab_weekly': 'Weekly',
        'stats.tab_monthly': 'Monthly',
        'stats.tab_pattern': 'Patterns',
        'stats.weekly_summary': 'This Week',
        'stats.monthly_summary': 'This Month',
        'stats.total_hours': 'Total hours:',
        'stats.work_days': 'Work days:',
        'stats.avg_hours': 'Avg hours/day:',
        'stats.total_overtime': 'Total overtime:',
        'stats.pattern_insights': 'Work Pattern Insights',
        'stats.analyzing': 'Analyzing...',
        'stats.no_data': 'Not enough data yet.',

        # === CalendarView ===
        'cal.title': 'Monthly Calendar',
        'cal.year_label': 'Y',
        'cal.month_label': 'M',
        'cal.prev': '◀ Prev',
        'cal.next': 'Next ▶',
        'cal.today': 'Today',
        'cal.no_record': 'No record',
        'cal.edit_record': 'Edit record',

        # === HelpView ===
        'help.tab_intro': 'Getting Started',
        'help.tab_work_hours': 'Work Hours',
        'help.tab_overtime': 'Overtime',
        'help.tab_leave': 'Leave',
        'help.tab_break': 'Break/Dinner',
        'help.tab_faq': 'FAQ',

        # === clock_in_dialog ===
        'dlg.clock_in.prompt': "Enter today's clock-in time",
        'dlg.clock_in.label': 'Clock-in time:',
        'dlg.clock_in.quick': 'Quick pick:',
        'dlg.clock_in.btn_now': 'Now',

        # === break_view ===
        'dlg.break.edit_title': 'Edit Break Record',
        'dlg.break.out_label': 'Break out:',
        'dlg.break.in_label': 'Return:',
        'dlg.break.reason_label': 'Reason:',
        'view.break.today_title': "Today's Break Records",
        'view.break.col_out': 'Break out',
        'view.break.col_in': 'Return',
        'view.break.col_duration': 'Duration',
        'view.break.col_reason': 'Reason',
        'view.break.in_progress': 'In progress',
        'view.break.total_zero': 'Total break: 0 min',
        'view.break.total_fmt': 'Total break: {h}h {m}m',
        'view.break.total_min_only': 'Total break: {m} min',
        'view.break.duration_fmt': '{h}h {m}m',
        'view.break.duration_min_only': '{m} min',
        'view.break.delete_confirm': 'Delete this break record?',
        'btn.refresh': 'Refresh',
        'btn.edit_short': 'Edit',
        'btn.delete_short': 'Delete',

        # === overtime_view ===
        'view.overtime.title': 'Overtime History',
        'view.overtime.balance_zero': 'Balance: 0 min',
        'view.overtime.balance_fmt': 'Current balance: {h}h {m}m ({total} min)',
        'view.overtime.earned_group': 'Earned',
        'view.overtime.used_group': 'Used',
        'view.overtime.col_date': 'Date',
        'view.overtime.col_earned': 'Earned',
        'view.overtime.col_used': 'Used',
        'view.overtime.col_memo': 'Memo',
        'view.overtime.col_reason': 'Reason',
        'view.overtime.btn_add_earned': 'Manual Earn',
        'view.overtime.btn_add_used': 'Manual Use',
        'view.overtime.menu_delete': 'Delete',
        'view.overtime.delete_confirm_body': 'Delete this usage record?\n\nDate: {date}\nTime: {time}\nReason: {reason}',
        'view.overtime.delete_earned_confirm_body': 'Delete this accrual record?\n\nDate: {date}\nEarned: {time}\n\nThe balance will be reduced accordingly.',
        'view.overtime.manual_earned_title': 'Manual Overtime Earn',
        'view.overtime.manual_used_title': 'Manual Overtime Use',
        'view.overtime.field_date': 'Date:',
        'view.overtime.field_time': 'Time:',
        'view.overtime.field_memo': 'Memo:',
        'view.overtime.field_reason': 'Reason:',
        'view.overtime.unit_hour_suffix': 'h',
        'view.overtime.minute_0': '0 min',
        'view.overtime.minute_30': '30 min',
        'view.overtime.placeholder_memo': 'Optional',
        'view.overtime.placeholder_reason': 'e.g., personal',
        'view.overtime.zero_add_error': 'Cannot add 0 minutes.',
        'view.overtime.zero_use_error': 'Cannot use 0 minutes.',
        'view.overtime.balance_short_title': 'Insufficient Balance',
        'view.overtime.balance_short_body': 'Not enough balance.\n\nRequested: {req_h}h {req_m}m\nBalance: {bal_h}h {bal_m}m',
        'view.overtime.saved_earned': '{h}h {m}m banked.',
        'view.overtime.saved_used': '{h}h {m}m used.',

        # === leave_view ===
        'view.leave.title': 'Leave Management',
        'view.leave.balance_zero': 'Balance: 0 days',
        'view.leave.balance_fmt': 'Balance: {days} days ({hours}h total)',
        'view.leave.btn_set_balance': 'Set Balance',
        'view.leave.used_group': 'Used',
        'view.leave.col_date': 'Date',
        'view.leave.col_type': 'Type',
        'view.leave.col_used': 'Used',
        'view.leave.col_reason': 'Reason',
        'view.leave.btn_add': 'Add Leave Usage',
        'view.leave.btn_calendar': 'Calendar',
        'view.leave.delete_confirm_body': 'Delete this leave record?\n\nDate: {date}\nType: {type}\nUsed: {days}',
        'view.leave.set_title': 'Set Leave Hours',
        'view.leave.set_prompt': 'Enter leave hours remaining (0.5h step):\ne.g. 8h = 1d, 4h = 0.5d (half), 2h = 0.25d, 0.5h = 30min',
        'view.leave.set_done_title': 'Saved',
        'view.leave.set_done_body': 'Leave balance set to {days} days ({hours}h).',
        'view.leave.add_title': 'Add Leave Usage',
        'view.leave.field_date': 'Date:',
        'view.leave.field_type': 'Type:',
        'view.leave.field_hours': 'Hours:',
        'view.leave.field_reason': 'Reason:',
        'view.leave.type_annual': 'Annual',
        'view.leave.type_half': 'Half',
        'view.leave.type_quarter': 'Quarter',
        'view.leave.type_hourly': 'Hourly',
        'view.leave.placeholder_reason': 'e.g., personal, medical',
        'view.leave.note_auto_deduct': '※ Leave balance is auto-deducted.',
        'view.leave.short_title': 'Insufficient Leave',
        'view.leave.short_body': 'Not enough leave.\nCurrent: {balance} days\nRequested: {req} days',
        'view.leave.confirm_title': 'Add Leave Usage',
        'view.leave.confirm_body': 'Date: {date}\nType: {type}\nUsed: {days} days ({hours}h)\nReason: {reason}\n\nAdd this record?',
        'view.leave.added_title': 'Added',
        'view.leave.added_body': '{days} days ({hours}h) of leave usage recorded.',
        'view.leave.error_title': 'Error',
        'view.leave.error_body': 'Failed to add leave record:\n{err}',
    },
}


# === HelpView 큰 HTML 콘텐츠 (별도 사전) ===
_HELP_HTML = {
    'ko': {
        'help.html.intro': """
        <h2>👋 환영합니다!</h2>
        <p><b>퇴근시간 계산기</b>는 출근 시간 자동 감지부터 연장근무 적립·사용까지
        하루 근무를 정리해 주는 데스크톱 앱입니다.</p>

        <h3>한눈에 보는 기본 흐름</h3>
        <ol>
          <li><b>출근</b> — 컴퓨터 켜진 시각이 자동으로 출근 시간으로 기록돼요.</li>
          <li><b>근무 중</b> — 메인 화면에 퇴근까지 남은 시간이 1초마다 갱신됩니다.</li>
          <li><b>점심/저녁</b> — 식사 시간 버튼을 누르면 그만큼 근무시간이 늘어납니다.</li>
          <li><b>외출</b> — "외출 시작/복귀" 버튼으로 잠깐 자리 비운 시간을 추적합니다.</li>
          <li><b>퇴근</b> — 퇴근 버튼을 누르면 연장근무가 30분 단위로 자동 적립됩니다.</li>
        </ol>

        <h3>처음 켰다면 꼭 확인하세요</h3>
        <ul>
          <li><b>설정 → 근무 시간</b>: 본인 근무 패턴(8시간 / 단축 7h30m / 6시간 등)을
              프리셋에서 선택하거나 직접 입력하세요.</li>
          <li><b>설정 → 휴가 → 연간 연차</b>: 본인 연차 일수를 맞춰 두면 잔여 연차가
              자동 계산됩니다.</li>
          <li><b>관리자 권한</b>이 필요할 수 있어요. 부팅 시간이 자동 감지되지 않으면
              관리자 권한으로 실행해 보세요.</li>
        </ul>
        """,
        'help.html.work_hours': """
        <h2>🕘 근무시간 설정</h2>

        <h3>표준 근무 / 단축근무 / 시간제 모두 지원</h3>
        <ul>
          <li><b>표준 8시간</b> — 점심 60분 (기본값)</li>
          <li><b>단축근무 7시간 30분</b> — 점심 30분</li>
          <li><b>단축근무 7시간</b> — 점심 60분</li>
          <li><b>단축근무 6시간</b> — 점심 30분</li>
          <li><b>반일 4시간</b> — 점심 없음</li>
          <li><b>사용자 정의</b> — 시간/분 직접 입력 (5분 단위)</li>
        </ul>

        <h3>💡 단축근무 사용자 안내</h3>
        <p>예) 하루 7시간 30분 근무 + 점심 30분</p>
        <ol>
          <li>설정 → 근무 시간 → <b>근무 패턴</b>에서
              <i>"단축근무 7시간 30분 (점심 30분)"</i> 선택</li>
          <li>또는 직접 입력: <b>하루 기본 근무</b>에 <code>7 시간 30 분</code>,
              <b>점심시간 기본</b>에 <code>30 분</code></li>
          <li><b>저장</b> 클릭하면 즉시 메인 화면 계산이 갱신됩니다.</li>
        </ol>

        <h3>점심시간 자동 적용</h3>
        <p>설정에서 <b>"자동 적용"</b>을 체크하면 출근 후 <b>4시간 경과</b> 시
        점심시간이 자동으로 켜집니다.</p>
        """,
        'help.html.overtime': """
        <h2>🏦 연장근무 30분 단위 적립 시스템</h2>

        <h3>적립 규칙</h3>
        <p>정규 퇴근시간 이후 일한 시간은 <b>30분 단위로 절삭</b>되어 적립됩니다.</p>
        <ul>
          <li>1시간 35분 일했다면 → <b>1시간 30분</b> 적립</li>
          <li>55분 일했다면 → <b>30분</b> 적립</li>
          <li>29분 일했다면 → <b>0분</b> 적립</li>
        </ul>

        <h3>사용 방법</h3>
        <p>적립된 연장근무는 메인 화면 <b>"30분 사용" / "1시간 사용"</b> 버튼으로
        쓸 수 있어요. 사용한 만큼 그날 퇴근시간이 앞당겨집니다.</p>

        <h3>주말·공휴일 근무</h3>
        <p>주말 또는 등록된 공휴일에 일한 시간은
        <b>모든 시간이 연장근무로 적립</b>됩니다.</p>
        """,
        'help.html.leave': """
        <h2>🌴 연차·반차 관리</h2>

        <h3>연차 잔액 자동 계산</h3>
        <p>잔액 = <b>연간 연차</b> − (프로그램 외 사용분 + 프로그램에서 기록된 사용분)</p>

        <h3>반차·반반차 지원</h3>
        <ul>
          <li><b>1.0일</b> — 종일 연차</li>
          <li><b>0.5일</b> — 반차 (4시간)</li>
          <li><b>0.25일</b> — 반반차 (2시간)</li>
        </ul>

        <h3>단축근무자의 연차 환산</h3>
        <p>1일 연차의 시간 길이는 설정의 <b>하루 기본 근무</b>를 따릅니다.
        예: 7시간 30분 근무자는 1일 연차가 7시간 30분(=450분)으로 환산됩니다.</p>
        """,
        'help.html.break': """
        <h2>🚪 외출 / 저녁시간</h2>

        <h3>외출 (잠깐 자리 비움)</h3>
        <p>병원, 잠깐 외근 등으로 자리를 비울 때 <b>외출 시작 → 복귀</b> 버튼으로
        시간을 추적하세요.</p>

        <h3>화면 잠금 자동 외출</h3>
        <p>설정에서 <b>"화면 잠금 시 자동 외출/복귀"</b>를 켜면 PC 잠금 시 자동으로
        외출이 시작되고, 풀리면 복귀로 처리됩니다.</p>

        <h3>저녁시간</h3>
        <p>야근하면서 저녁을 먹는다면 <b>저녁시간 추가</b> 버튼을 눌러주세요.</p>
        """,
        'help.html.faq': """
        <h2>❓ 자주 묻는 질문</h2>

        <h3>Q. 출근 시간이 잘못 잡혔어요</h3>
        <p>메인 화면 출근 시각 옆 <b>편집(연필)</b> 아이콘으로 수정할 수 있어요.</p>

        <h3>Q. 단축근무 7시간 30분으로 설정하고 싶어요</h3>
        <p>설정 → 근무 시간 → 근무 패턴에서 프리셋을 선택하거나 시·분을 직접 입력하세요.</p>

        <h3>Q. 데이터는 어디에 저장되나요?</h3>
        <p>실행 폴더의 <code>database.db</code> (SQLite). 자동 백업은
        <code>~/.clockout_backups/</code>에 1일 1회 회전됩니다.</p>

        """,
    },
    'en': {
        'help.html.intro': """
        <h2>👋 Welcome!</h2>
        <p><b>Clock-out Time Calculator</b> is a desktop app that organizes your daily work
        — from auto-detecting clock-in time to banking and using overtime.</p>

        <h3>Basic Flow</h3>
        <ol>
          <li><b>Clock in</b> — System boot time is auto-recorded as your clock-in.</li>
          <li><b>Working</b> — Remaining time updates every second on the main screen.</li>
          <li><b>Lunch/Dinner</b> — Press the meal buttons to extend work time.</li>
          <li><b>Break</b> — Track time away with "Start Break / Return" buttons.</li>
          <li><b>Clock out</b> — Press the button; overtime is banked in 30-min units.</li>
        </ol>

        <h3>First-Time Setup</h3>
        <ul>
          <li><b>Settings → Work Time</b>: pick your pattern from presets
              (8h / 7h30m / 6h / 4h half-day) or enter custom values.</li>
          <li><b>Settings → Leave</b>: set your annual leave days.</li>
          <li><b>Admin rights</b> may be required for boot-time auto-detection.</li>
        </ul>
        """,
        'help.html.work_hours': """
        <h2>🕘 Work Time Settings</h2>

        <h3>Supports Standard / Reduced / Part-time</h3>
        <ul>
          <li><b>Standard 8h</b> — 60-min lunch (default)</li>
          <li><b>Reduced 7h30m</b> — 30-min lunch</li>
          <li><b>Reduced 7h</b> — 60-min lunch</li>
          <li><b>Reduced 6h</b> — 30-min lunch</li>
          <li><b>Half-day 4h</b> — no lunch</li>
          <li><b>Custom</b> — direct input (5-min granularity)</li>
        </ul>

        <h3>💡 For Reduced-Hours Users</h3>
        <p>Example: 7h30m daily + 30-min lunch</p>
        <ol>
          <li>Settings → Work Time → pick <i>"Reduced 7h30m (30-min lunch)"</i> preset</li>
          <li>Or enter directly: 7h 30min daily, 30min lunch</li>
          <li>Click <b>Save</b> — main screen recalculates immediately.</li>
        </ol>

        <h3>Auto Lunch</h3>
        <p>Enable "Auto Apply" in settings to automatically turn on lunch
        after 4 hours from clock-in.</p>
        """,
        'help.html.overtime': """
        <h2>🏦 30-Minute Overtime Banking</h2>

        <h3>Banking Rule</h3>
        <p>Time worked past your scheduled clock-out is <b>truncated to 30-min units</b>.</p>
        <ul>
          <li>1h35m worked → <b>1h30m</b> banked</li>
          <li>55min worked → <b>30min</b> banked</li>
          <li>29min worked → <b>0min</b> banked</li>
        </ul>

        <h3>Using Banked Overtime</h3>
        <p>Use buttons on the main screen to consume banked overtime.
        Each unit lets you clock out earlier on a chosen day.</p>

        <h3>Weekend/Holiday Work</h3>
        <p>All hours worked on weekends or registered holidays are
        <b>banked entirely as overtime</b>.</p>
        """,
        'help.html.leave': """
        <h2>🌴 Annual Leave Management</h2>

        <h3>Auto Balance Calculation</h3>
        <p>Balance = annual leave − (pre-program usage + recorded usage)</p>

        <h3>Half / Quarter Day</h3>
        <ul>
          <li><b>1.0 day</b> — full leave</li>
          <li><b>0.5 day</b> — half (4h)</li>
          <li><b>0.25 day</b> — quarter (2h)</li>
        </ul>

        <h3>Reduced-Hours Conversion</h3>
        <p>1 leave day equals your configured daily work time.
        Example: 7h30m worker → 1 day = 7h30m (450 min).</p>
        """,
        'help.html.break': """
        <h2>🚪 Break / Dinner</h2>

        <h3>Break (Briefly Away)</h3>
        <p>For short absences (medical, errands), use <b>Start Break / Return</b>.</p>

        <h3>Auto Break on Screen Lock</h3>
        <p>Enable "Auto break on screen lock" in settings — when the PC locks,
        a break starts automatically; on unlock, you return.</p>

        <h3>Dinner</h3>
        <p>For overtime with dinner, press <b>Add Dinner</b>.</p>
        """,
        'help.html.faq': """
        <h2>❓ FAQ</h2>

        <h3>Q. Clock-in time is wrong</h3>
        <p>Click the pencil icon next to clock-in time on the main screen to edit.</p>

        <h3>Q. How to set 7h30m work day?</h3>
        <p>Settings → Work Time → pick the preset or enter hours/minutes directly.</p>

        <h3>Q. Where is data stored?</h3>
        <p><code>database.db</code> in the program folder (SQLite). Daily auto-backups
        rotate in <code>~/.clockout_backups/</code>.</p>

        """,
    },
}


def set_language(lang: str) -> None:
    global _current_lang
    if lang in _DICT:
        _current_lang = lang


def get_language() -> str:
    return _current_lang


def tr(key: str, **kwargs) -> str:
    """번역 조회. 키 미존재 시 ko 폴백 → 키 그대로."""
    table = _DICT.get(_current_lang, _DICT['ko'])
    text = table.get(key) or _DICT['ko'].get(key) or key
    if kwargs:
        try:
            return text.format(**kwargs)
        except (KeyError, IndexError):
            return text
    return text


def tr_html(key: str) -> str:
    """HTML 콘텐츠 조회 (HelpView용)."""
    table = _HELP_HTML.get(_current_lang, _HELP_HTML['ko'])
    return table.get(key) or _HELP_HTML['ko'].get(key) or f"<p>missing: {key}</p>"


def available_languages() -> list:
    return list(_DICT.keys())


def language_label(code: str) -> str:
    return {'ko': '한국어', 'en': 'English'}.get(code, code)
