From ee2089e81d73be3fd18d33f1e7644e8cc2ed2549 Mon Sep 17 00:00:00 2001 From: ppuassi <34529179+ppuassi@users.noreply.github.com> Date: Tue, 26 May 2026 01:22:35 +0900 Subject: [PATCH] feat(i18n): add Korean (ko) translation (#977) Korean translation by @ppuassi, topped up to full en.ts key parity. Language registration follows separately. --- client/src/i18n/translations/ko.ts | 2429 ++++++++++++++++++++++++++++ 1 file changed, 2429 insertions(+) create mode 100644 client/src/i18n/translations/ko.ts diff --git a/client/src/i18n/translations/ko.ts b/client/src/i18n/translations/ko.ts new file mode 100644 index 00000000..82a8dfc0 --- /dev/null +++ b/client/src/i18n/translations/ko.ts @@ -0,0 +1,2429 @@ +const ko: Record = { + // Common + 'common.save': '저장', + 'common.showMore': '더 보기', + 'common.showLess': '접기', + 'common.cancel': '취소', + 'common.clear': '지우기', + 'common.delete': '삭제', + 'common.edit': '편집', + 'common.add': '추가', + 'common.loading': '로딩 중...', + 'common.import': '가져오기', + 'common.select': '선택', + 'common.selectAll': '전체 선택', + 'common.deselectAll': '전체 해제', + 'common.error': '오류', + 'common.unknownError': '알 수 없는 오류', + 'common.tooManyAttempts': '시도 횟수가 너무 많습니다. 잠시 후 다시 시도해 주세요.', + 'common.back': '뒤로', + 'common.all': '전체', + 'common.close': '닫기', + 'common.open': '열기', + 'common.upload': '업로드', + 'common.search': '검색', + 'common.confirm': '확인', + 'common.ok': '확인', + 'common.yes': '예', + 'common.no': '아니오', + 'common.or': '또는', + 'common.none': '없음', + 'common.date': '날짜', + 'common.rename': '이름 변경', + 'common.discardChanges': '변경 사항 취소', + 'common.discard': '취소', + 'common.name': '이름', + 'common.email': '이메일', + 'common.password': '비밀번호', + 'common.saving': '저장 중...', + 'common.justNow': '방금 전', + 'common.hoursAgo': '{count}시간 전', + 'common.daysAgo': '{count}일 전', + 'common.saved': '저장됨', + 'trips.memberRemoved': '{username} 제거됨', + 'trips.memberRemoveError': '제거 실패', + 'trips.memberAdded': '{username} 추가됨', + 'trips.memberAddError': '추가 실패', + 'trips.reminder': '리마인더', + 'trips.reminderNone': '없음', + 'trips.reminderDay': '일', + 'trips.reminderDays': '일', + 'trips.reminderCustom': '직접 설정', + 'trips.reminderDaysBefore': '일 전 출발', + 'trips.reminderDisabledHint': '여행 리마인더가 비활성화되어 있습니다. 관리자 > 설정 > 알림에서 활성화하세요.', + 'common.update': '업데이트', + 'common.change': '변경', + 'common.uploading': '업로드 중…', + 'common.backToPlanning': '계획으로 돌아가기', + 'common.reset': '초기화', + 'common.expand': '펼치기', + 'common.collapse': '접기', + + // Navbar + 'nav.trip': '여행', + 'nav.share': '공유', + 'nav.settings': '설정', + 'nav.admin': '관리자', + 'nav.logout': '로그아웃', + 'nav.lightMode': '라이트 모드', + 'nav.darkMode': '다크 모드', + 'nav.autoMode': '자동 모드', + 'nav.administrator': '관리자', + + // Dashboard + 'dashboard.title': '내 여행', + 'dashboard.subtitle.loading': '여행 불러오는 중...', + 'dashboard.subtitle.trips': '{count}개 여행 ({archived}개 보관됨)', + 'dashboard.subtitle.empty': '첫 번째 여행을 시작하세요', + 'dashboard.subtitle.activeOne': '활성 여행 {count}개', + 'dashboard.subtitle.activeMany': '활성 여행 {count}개', + 'dashboard.subtitle.archivedSuffix': ' · {count}개 보관됨', + 'dashboard.newTrip': '새 여행', + 'dashboard.gridView': '격자 보기', + 'dashboard.listView': '목록 보기', + 'dashboard.currency': '통화', + 'dashboard.timezone': '시간대', + 'dashboard.localTime': '현지', + 'dashboard.timezoneCustomTitle': '사용자 지정 시간대', + 'dashboard.timezoneCustomLabelPlaceholder': '레이블 (선택)', + 'dashboard.timezoneCustomTzPlaceholder': '예: America/New_York', + 'dashboard.timezoneCustomAdd': '추가', + 'dashboard.timezoneCustomErrorEmpty': '시간대 식별자를 입력하세요', + 'dashboard.timezoneCustomErrorInvalid': '잘못된 시간대입니다. Europe/Berlin 같은 형식을 사용하세요', + 'dashboard.timezoneCustomErrorDuplicate': '이미 추가됨', + 'dashboard.emptyTitle': '아직 여행이 없습니다', + 'dashboard.emptyText': '첫 번째 여행을 만들고 계획을 시작하세요!', + 'dashboard.emptyButton': '첫 번째 여행 만들기', + 'dashboard.nextTrip': '다음 여행', + 'dashboard.shared': '공유됨', + 'dashboard.sharedBy': '{name}이(가) 공유', + 'dashboard.days': '일', + 'dashboard.places': '장소', + 'dashboard.members': '동행자', + 'dashboard.archive': '보관', + 'dashboard.copyTrip': '복사', + 'dashboard.copySuffix': '사본', + 'dashboard.restore': '복원', + 'dashboard.archived': '보관됨', + 'dashboard.status.ongoing': '진행 중', + 'dashboard.status.today': '오늘', + 'dashboard.status.tomorrow': '내일', + 'dashboard.status.past': '지난 여행', + 'dashboard.status.daysLeft': '{count}일 남음', + 'dashboard.toast.loadError': '여행 불러오기 실패', + 'dashboard.toast.created': '여행이 생성되었습니다!', + 'dashboard.toast.createError': '여행 생성 실패', + 'dashboard.toast.updated': '여행이 업데이트되었습니다!', + 'dashboard.toast.updateError': '여행 업데이트 실패', + 'dashboard.toast.deleted': '여행이 삭제되었습니다', + 'dashboard.toast.deleteError': '여행 삭제 실패', + 'dashboard.toast.archived': '여행이 보관되었습니다', + 'dashboard.toast.archiveError': '여행 보관 실패', + 'dashboard.toast.restored': '여행이 복원되었습니다', + 'dashboard.toast.restoreError': '여행 복원 실패', + 'dashboard.toast.copied': '여행이 복사되었습니다!', + 'dashboard.toast.copyError': '여행 복사 실패', + 'dashboard.confirm.delete': '여행 "{title}"을(를) 삭제할까요? 모든 장소와 계획이 영구 삭제됩니다.', + 'dashboard.confirm.copy.title': '이 여행을 복사할까요?', + 'dashboard.confirm.copy.willCopy': '복사될 항목', + 'dashboard.confirm.copy.will1': '일정, 장소 및 일별 배정', + 'dashboard.confirm.copy.will2': '숙박 및 예약', + 'dashboard.confirm.copy.will3': '예산 항목 및 카테고리 순서', + 'dashboard.confirm.copy.will4': '짐 목록 (체크 해제 상태)', + 'dashboard.confirm.copy.will5': '할 일 (미배정 및 미완료)', + 'dashboard.confirm.copy.will6': '일별 메모', + 'dashboard.confirm.copy.wontCopy': '복사되지 않는 항목', + 'dashboard.confirm.copy.wont1': '공동 작업자 및 멤버 배정', + 'dashboard.confirm.copy.wont2': '공동 작업 메모, 투표 및 메시지', + 'dashboard.confirm.copy.wont3': '파일 및 사진', + 'dashboard.confirm.copy.wont4': '공유 토큰', + 'dashboard.confirm.copy.confirm': '여행 복사', + 'dashboard.editTrip': '여행 편집', + 'dashboard.createTrip': '새 여행 만들기', + 'dashboard.tripTitle': '제목', + 'dashboard.tripTitlePlaceholder': '예: 일본에서의 여름', + 'dashboard.tripDescription': '설명', + 'dashboard.tripDescriptionPlaceholder': '이 여행에 대해 설명해 주세요', + 'dashboard.startDate': '시작일', + 'dashboard.endDate': '종료일', + 'dashboard.dayCount': '일수', + 'dashboard.dayCountHint': '여행 날짜가 설정되지 않은 경우 계획할 일수입니다.', + 'dashboard.noDateHint': '날짜 미설정 — 기본 7일이 생성됩니다. 언제든지 변경할 수 있습니다.', + 'dashboard.coverImage': '커버 이미지', + 'dashboard.addCoverImage': '커버 이미지 추가 (또는 끌어다 놓기)', + 'dashboard.addMembers': '동행자', + 'dashboard.addMember': '멤버 추가', + 'dashboard.coverSaved': '커버 이미지가 저장되었습니다', + 'dashboard.coverUploadError': '업로드 실패', + 'dashboard.coverRemoveError': '삭제 실패', + 'dashboard.titleRequired': '제목을 입력하세요', + 'dashboard.endDateError': '종료일은 시작일 이후여야 합니다', + + // Settings + 'settings.title': '설정', + 'settings.subtitle': '개인 설정을 구성하세요', + 'settings.tabs.display': '화면', + 'settings.tabs.map': '지도', + 'settings.tabs.notifications': '알림', + 'settings.tabs.integrations': '통합', + 'settings.tabs.account': '계정', + 'settings.tabs.offline': '오프라인', + 'settings.tabs.about': '정보', + 'settings.map': '지도', + 'settings.mapTemplate': '지도 템플릿', + 'settings.mapTemplatePlaceholder.select': '템플릿 선택...', + 'settings.mapDefaultHint': '비워두면 OpenStreetMap (기본값) 사용', + 'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + 'settings.mapHint': '지도 타일 URL 템플릿', + 'settings.mapProvider': '지도 공급자', + 'settings.mapProviderHint': '여행 플래너 및 Journey 지도에 영향을 줍니다. Atlas는 항상 Leaflet을 사용합니다.', + 'settings.mapLeafletSubtitle': '클래식 2D, 모든 래스터 타일', + 'settings.mapMapboxSubtitle': '벡터 타일, 3D 건물 및 지형', + 'settings.mapExperimental': '실험적', + 'settings.mapMapboxToken': 'Mapbox 액세스 토큰', + 'settings.mapMapboxTokenHint': '공개 토큰 (pk.*) 출처', + 'settings.mapMapboxTokenLink': 'mapbox.com → 액세스 토큰', + 'settings.mapStyle': '지도 스타일', + 'settings.mapStylePlaceholder': 'Mapbox 스타일 선택', + 'settings.mapStyleHint': '프리셋 또는 mapbox://styles/USER/ID URL 직접 입력', + 'settings.map3dBuildings': '3D 건물 및 지형', + 'settings.map3dHint': '기울기 + 실제 3D 건물 돌출 — 위성 포함 모든 스타일에서 작동합니다.', + 'settings.mapHighQuality': '고품질 모드', + 'settings.mapHighQualityHint': '안티앨리어싱 + 구형 투영으로 선명한 경계와 현실적인 지구 뷰를 제공합니다.', + 'settings.mapHighQualityWarning': '저사양 기기에서 성능에 영향을 줄 수 있습니다.', + 'settings.mapTipLabel': '팁:', + 'settings.mapTip': '우클릭 후 드래그하여 지도를 회전/기울이세요. 가운데 클릭으로 장소를 추가할 수 있습니다 (우클릭은 회전 전용).', + 'settings.latitude': '위도', + 'settings.longitude': '경도', + 'settings.saveMap': '지도 저장', + 'settings.apiKeys': 'API 키', + 'settings.mapsKey': 'Google Maps API 키', + 'settings.mapsKeyHint': '장소 검색용. Places API (New) 필요. console.cloud.google.com에서 발급', + 'settings.weatherKey': 'OpenWeatherMap API 키', + 'settings.weatherKeyHint': '날씨 데이터용. openweathermap.org/api에서 무료 발급', + 'settings.keyPlaceholder': '키 입력...', + 'settings.configured': '설정됨', + 'settings.saveKeys': '키 저장', + 'settings.display': '화면', + 'settings.colorMode': '색상 모드', + 'settings.light': '라이트', + 'settings.dark': '다크', + 'settings.auto': '자동', + 'settings.language': '언어', + 'settings.temperature': '온도 단위', + 'settings.timeFormat': '시간 형식', + 'settings.routeCalculation': '경로 계산', + 'settings.bookingLabels': '예약 경로 레이블', + 'settings.bookingLabelsHint': '지도에 역 / 공항 이름을 표시합니다. 끄면 아이콘만 표시됩니다.', + 'settings.blurBookingCodes': '예약 코드 흐리게', + 'settings.notifications': '알림', + 'settings.notifyTripInvite': '여행 초대', + 'settings.notifyBookingChange': '예약 변경', + 'settings.notifyTripReminder': '여행 리마인더', + 'settings.notifyTodoDue': '할 일 마감 임박', + 'settings.notifyVacayInvite': 'Vacay 퓨전 초대', + 'settings.notifyPhotosShared': '공유된 사진 (Immich)', + 'settings.notifyCollabMessage': '채팅 메시지 (Collab)', + 'settings.notifyPackingTagged': '짐 목록: 배정', + 'settings.notifyWebhook': '웹훅 알림', + 'settings.notifyVersionAvailable': '새 버전 사용 가능', + 'settings.notificationPreferences.email': '이메일', + 'settings.notificationPreferences.webhook': '웹훅', + 'settings.notificationPreferences.inapp': '앱 내', + 'settings.notificationPreferences.ntfy': 'Ntfy', + 'settings.notificationPreferences.noChannels': '알림 채널이 설정되지 않았습니다. 관리자에게 이메일 또는 웹훅 알림 설정을 요청하세요.', + 'settings.webhookUrl.label': '웹훅 URL', + 'settings.webhookUrl.placeholder': 'https://discord.com/api/webhooks/...', + 'settings.webhookUrl.hint': 'Discord, Slack 또는 사용자 지정 웹훅 URL을 입력하여 알림을 받으세요.', + 'settings.webhookUrl.saved': '웹훅 URL이 저장되었습니다', + 'settings.webhookUrl.test': '테스트', + 'settings.webhookUrl.testSuccess': '테스트 웹훅이 성공적으로 전송되었습니다', + 'settings.webhookUrl.testFailed': '테스트 웹훅 실패', + 'settings.ntfyUrl.topicLabel': 'Ntfy 토픽', + 'settings.ntfyUrl.topicPlaceholder': 'my-trek-alerts', + 'settings.ntfyUrl.serverLabel': 'Ntfy 서버 URL (선택)', + 'settings.ntfyUrl.serverPlaceholder': 'https://ntfy.sh', + 'settings.ntfyUrl.hint': 'ntfy 토픽을 입력하여 푸시 알림을 받으세요. 서버를 비워두면 관리자가 설정한 기본값을 사용합니다.', + 'settings.ntfyUrl.tokenLabel': '액세스 토큰 (선택)', + 'settings.ntfyUrl.tokenHint': '비밀번호로 보호된 토픽에 필요합니다.', + 'settings.ntfyUrl.saved': 'Ntfy 설정이 저장되었습니다', + 'settings.ntfyUrl.test': '테스트', + 'settings.ntfyUrl.testSuccess': '테스트 ntfy 알림이 성공적으로 전송되었습니다', + 'settings.ntfyUrl.testFailed': '테스트 ntfy 알림 실패', + 'settings.ntfyUrl.tokenCleared': '액세스 토큰이 삭제되었습니다', + 'admin.notifications.title': '알림', + 'admin.notifications.hint': '알림 채널을 하나 선택하세요. 한 번에 하나만 활성화할 수 있습니다.', + 'admin.notifications.none': '비활성화', + 'admin.notifications.email': '이메일 (SMTP)', + 'admin.notifications.webhook': '웹훅', + 'admin.notifications.ntfy': 'Ntfy', + 'admin.ntfy.hint': '사용자가 자신의 ntfy 토픽을 설정하여 푸시 알림을 받을 수 있습니다. 아래에 기본 서버를 설정하면 사용자 설정에 미리 채워집니다.', + 'admin.notifications.save': '알림 설정 저장', + 'admin.notifications.saved': '알림 설정이 저장되었습니다', + 'admin.notifications.testWebhook': '테스트 웹훅 전송', + 'admin.notifications.testWebhookSuccess': '테스트 웹훅이 성공적으로 전송되었습니다', + 'admin.notifications.testWebhookFailed': '테스트 웹훅 실패', + 'admin.notifications.testNtfy': '테스트 ntfy 전송', + 'admin.notifications.testNtfySuccess': '테스트 ntfy가 성공적으로 전송되었습니다', + 'admin.notifications.testNtfyFailed': '테스트 ntfy 실패', + 'admin.notifications.emailPanel.title': '이메일 (SMTP)', + 'admin.notifications.webhookPanel.title': '웹훅', + 'admin.notifications.inappPanel.title': '앱 내', + 'admin.notifications.inappPanel.hint': '앱 내 알림은 항상 활성화되어 있으며 전역으로 비활성화할 수 없습니다.', + 'admin.notifications.adminWebhookPanel.title': '관리자 웹훅', + 'admin.notifications.adminWebhookPanel.hint': '이 웹훅은 관리자 알림 전용입니다 (예: 버전 알림). 사용자별 웹훅과 별개이며 설정 시 항상 실행됩니다.', + 'admin.notifications.adminWebhookPanel.saved': '관리자 웹훅 URL이 저장되었습니다', + 'admin.notifications.adminWebhookPanel.testSuccess': '테스트 웹훅이 성공적으로 전송되었습니다', + 'admin.notifications.adminWebhookPanel.testFailed': '테스트 웹훅 실패', + 'admin.notifications.adminWebhookPanel.alwaysOnHint': 'URL이 설정되면 관리자 웹훅은 항상 실행됩니다', + 'admin.notifications.adminNtfyPanel.title': '관리자 Ntfy', + 'admin.notifications.adminNtfyPanel.hint': '이 ntfy 토픽은 관리자 알림 전용입니다 (예: 버전 알림). 사용자별 토픽과 별개이며 설정 시 항상 실행됩니다.', + 'admin.notifications.adminNtfyPanel.serverLabel': 'Ntfy 서버 URL', + 'admin.notifications.adminNtfyPanel.serverHint': '사용자 ntfy 알림의 기본 서버로도 사용됩니다. 비워두면 ntfy.sh가 기본값입니다. 사용자는 자신의 설정에서 변경할 수 있습니다.', + 'admin.notifications.adminNtfyPanel.serverPlaceholder': 'https://ntfy.sh', + 'admin.notifications.adminNtfyPanel.topicLabel': '관리자 토픽', + 'admin.notifications.adminNtfyPanel.topicPlaceholder': 'trek-admin-alerts', + 'admin.notifications.adminNtfyPanel.tokenLabel': '액세스 토큰 (선택)', + 'admin.notifications.adminNtfyPanel.tokenCleared': '관리자 액세스 토큰이 삭제되었습니다', + 'admin.notifications.adminNtfyPanel.saved': '관리자 ntfy 설정이 저장되었습니다', + 'admin.notifications.adminNtfyPanel.test': '테스트 ntfy 전송', + 'admin.notifications.adminNtfyPanel.testSuccess': '테스트 ntfy가 성공적으로 전송되었습니다', + 'admin.notifications.adminNtfyPanel.testFailed': '테스트 ntfy 실패', + 'admin.notifications.adminNtfyPanel.alwaysOnHint': '토픽이 설정되면 관리자 ntfy는 항상 실행됩니다', + 'admin.notifications.adminNotificationsHint': '관리자 전용 알림 (예: 버전 알림)을 전달할 채널을 설정하세요.', + 'admin.notifications.tripReminders.title': '여행 리마인더', + 'admin.notifications.tripReminders.hint': '여행 시작 전에 리마인더 알림을 전송합니다 (여행에 리마인더 일수가 설정되어 있어야 합니다).', + 'admin.notifications.tripReminders.enabled': '여행 리마인더 활성화됨', + 'admin.notifications.tripReminders.disabled': '여행 리마인더 비활성화됨', + 'admin.smtp.title': '이메일 및 알림', + 'admin.smtp.hint': '이메일 알림 전송을 위한 SMTP 설정입니다.', + 'admin.smtp.testButton': '테스트 이메일 전송', + 'admin.webhook.hint': '사용자가 알림용 웹훅 URL을 설정할 수 있습니다 (Discord, Slack 등).', + 'admin.smtp.testSuccess': '테스트 이메일이 성공적으로 전송되었습니다', + 'admin.smtp.testFailed': '테스트 이메일 실패', + 'settings.notificationsDisabled': '알림이 설정되지 않았습니다. 관리자에게 이메일 또는 웹훅 알림 활성화를 요청하세요.', + 'settings.notificationsActive': '활성 채널', + 'settings.notificationsManagedByAdmin': '알림 이벤트는 관리자가 설정합니다.', + 'dayplan.icsTooltip': '캘린더 내보내기 (ICS)', + 'share.linkTitle': '공개 링크', + 'share.linkHint': '로그인 없이 이 여행을 볼 수 있는 링크를 만드세요. 읽기 전용 — 편집 불가.', + 'share.createLink': '링크 만들기', + 'share.deleteLink': '링크 삭제', + 'share.createError': '링크 생성 실패', + 'common.copy': '복사', + 'common.copied': '복사됨', + 'share.permMap': '지도 및 계획', + 'share.permBookings': '예약', + 'share.permPacking': '짐 목록', + 'shared.expired': '링크가 만료되었거나 유효하지 않습니다', + 'shared.expiredHint': '이 공유 여행 링크는 더 이상 유효하지 않습니다.', + 'shared.readOnly': '읽기 전용 공유 보기', + 'shared.tabPlan': '계획', + 'shared.tabBookings': '예약', + 'shared.tabPacking': '짐 목록', + 'shared.tabBudget': '예산', + 'shared.tabChat': '채팅', + 'shared.days': '일', + 'shared.places': '장소', + 'shared.other': '기타', + 'shared.totalBudget': '총 예산', + 'shared.messages': '메시지', + 'shared.sharedVia': '공유 경로', + 'shared.confirmed': '확정됨', + 'shared.pending': '대기 중', + 'share.permBudget': '예산', + 'share.permCollab': '채팅', + 'settings.on': '켜기', + 'settings.off': '끄기', + 'settings.mcp.title': 'MCP 설정', + 'settings.mcp.endpoint': 'MCP 엔드포인트', + 'settings.mcp.clientConfig': '클라이언트 설정', + 'settings.mcp.clientConfigHint': '을 아래 목록의 API 토큰으로 교체하세요. npx 경로는 시스템에 따라 조정해야 할 수 있습니다 (예: Windows의 경우 C:\\PROGRA~1\\nodejs\\npx.cmd).', + 'settings.mcp.clientConfigHintOAuth': '을 위에서 생성한 OAuth 2.1 클라이언트 자격 증명으로 교체하세요. mcp-remote가 처음 연결 시 브라우저를 열어 인증을 완료합니다. npx 경로는 시스템에 따라 조정해야 할 수 있습니다 (예: Windows의 경우 C:\\PROGRA~1\\nodejs\\npx.cmd).', + 'settings.mcp.copy': '복사', + 'settings.mcp.copied': '복사됨!', + 'settings.mcp.apiTokens': 'API 토큰', + 'settings.mcp.createToken': '새 토큰 만들기', + 'settings.mcp.noTokens': '토큰이 없습니다. MCP 클라이언트 연결을 위해 토큰을 만드세요.', + 'settings.mcp.tokenCreatedAt': '생성일', + 'settings.mcp.tokenUsedAt': '사용일', + 'settings.mcp.deleteTokenTitle': '토큰 삭제', + 'settings.mcp.deleteTokenMessage': '이 토큰은 즉시 무효화됩니다. 이 토큰을 사용하는 MCP 클라이언트는 접근 권한을 잃게 됩니다.', + 'settings.mcp.modal.createTitle': 'API 토큰 만들기', + 'settings.mcp.modal.tokenName': '토큰 이름', + 'settings.mcp.modal.tokenNamePlaceholder': '예: Claude Desktop, 업무용 노트북', + 'settings.mcp.modal.creating': '생성 중…', + 'settings.mcp.modal.create': '토큰 만들기', + 'settings.mcp.modal.createdTitle': '토큰이 생성되었습니다', + 'settings.mcp.modal.createdWarning': '이 토큰은 한 번만 표시됩니다. 지금 복사하여 저장하세요 — 다시 복구할 수 없습니다.', + 'settings.mcp.modal.done': '완료', + 'settings.mcp.toast.created': '토큰이 생성되었습니다', + 'settings.mcp.toast.createError': '토큰 생성 실패', + 'settings.mcp.toast.deleted': '토큰이 삭제되었습니다', + 'settings.mcp.toast.deleteError': '토큰 삭제 실패', + 'settings.mcp.apiTokensDeprecated': 'API 토큰은 더 이상 사용되지 않으며 향후 버전에서 제거될 예정입니다. 대신 OAuth 2.1 클라이언트를 사용하세요.', + 'settings.oauth.clients': 'OAuth 2.1 클라이언트', + 'settings.oauth.clientsHint': 'OAuth 2.1 클라이언트를 등록하여 타사 MCP 앱 (Claude Web, Cursor 등)이 정적 토큰 없이 연결할 수 있도록 하세요.', + 'settings.oauth.createClient': '새 클라이언트', + 'settings.oauth.noClients': '등록된 OAuth 클라이언트가 없습니다.', + 'settings.oauth.clientId': '클라이언트 ID', + 'settings.oauth.clientSecret': '클라이언트 시크릿', + 'settings.oauth.deleteClient': '클라이언트 삭제', + 'settings.oauth.deleteClientMessage': '이 클라이언트와 모든 활성 세션이 영구 삭제됩니다. 이 클라이언트를 사용하는 앱은 즉시 접근 권한을 잃게 됩니다.', + 'settings.oauth.rotateSecret': '시크릿 교체', + 'settings.oauth.rotateSecretMessage': '새 클라이언트 시크릿이 생성되고 기존 세션은 즉시 무효화됩니다. 이 대화창을 닫기 전에 앱을 업데이트하세요.', + 'settings.oauth.rotateSecretConfirm': '교체', + 'settings.oauth.rotateSecretConfirming': '교체 중…', + 'settings.oauth.rotateSecretDoneTitle': '새 시크릿이 생성되었습니다', + 'settings.oauth.rotateSecretDoneWarning': '이 시크릿은 한 번만 표시됩니다. 지금 복사하여 앱을 업데이트하세요 — 이전 세션은 모두 무효화되었습니다.', + 'settings.oauth.activeSessions': '활성 OAuth 세션', + 'settings.oauth.sessionScopes': '권한 범위', + 'settings.oauth.sessionExpires': '만료', + 'settings.oauth.revoke': '취소', + 'settings.oauth.revokeSession': '세션 취소', + 'settings.oauth.revokeSessionMessage': '이 OAuth 세션의 접근 권한이 즉시 취소됩니다.', + 'settings.oauth.modal.createTitle': 'OAuth 클라이언트 등록', + 'settings.oauth.modal.presets': '빠른 프리셋', + 'settings.oauth.modal.clientName': '앱 이름', + 'settings.oauth.modal.clientNamePlaceholder': '예: Claude Web, My MCP App', + 'settings.oauth.modal.redirectUris': '리디렉션 URI', + 'settings.oauth.modal.redirectUrisPlaceholder': 'https://your-app.com/callback\nhttps://your-app.com/auth', + 'settings.oauth.modal.redirectUrisHint': '한 줄에 URI 하나. HTTPS 필수 (localhost 예외). 정확히 일치해야 합니다.', + 'settings.oauth.modal.scopes': '허용 권한 범위', + 'settings.oauth.modal.scopesHint': 'list_trips 및 get_trip_summary는 항상 사용 가능합니다 — 권한 범위 불필요. AI가 다른 도구를 사용하는 데 필요한 여행 ID를 찾을 수 있습니다.', + 'settings.oauth.modal.selectAll': '전체 선택', + 'settings.oauth.modal.deselectAll': '전체 해제', + 'settings.oauth.modal.creating': '등록 중…', + 'settings.oauth.modal.create': '클라이언트 등록', + 'settings.oauth.modal.createdTitle': '클라이언트가 등록되었습니다', + 'settings.oauth.modal.createdWarning': '클라이언트 시크릿은 한 번만 표시됩니다. 지금 복사하세요 — 다시 복구할 수 없습니다.', + 'settings.oauth.toast.createError': 'OAuth 클라이언트 등록 실패', + 'settings.oauth.toast.deleted': 'OAuth 클라이언트가 삭제되었습니다', + 'settings.oauth.toast.deleteError': 'OAuth 클라이언트 삭제 실패', + 'settings.oauth.toast.revoked': '세션이 취소되었습니다', + 'settings.oauth.toast.revokeError': '세션 취소 실패', + 'settings.oauth.toast.rotateError': '클라이언트 시크릿 교체 실패', + 'settings.account': '계정', + 'settings.about': '정보', + 'settings.about.reportBug': '버그 신고', + 'settings.about.reportBugHint': '문제를 발견하셨나요? 알려주세요', + 'settings.about.featureRequest': '기능 요청', + 'settings.about.featureRequestHint': '새로운 기능을 제안하세요', + 'settings.about.wikiHint': '문서 및 가이드', + 'settings.about.supporters.badge': '월간 후원자', + 'settings.about.supporters.title': 'TREK의 여행 동반자', + 'settings.about.supporters.subtitle': '다음 여정을 계획하는 동안, 이분들이 TREK의 미래를 함께 만들어가고 있습니다. 월간 후원금은 개발과 실제 작업 시간에 직접 사용되어 TREK이 오픈 소스로 유지될 수 있게 합니다.', + 'settings.about.supporters.since': '{date}부터 후원자', + 'settings.about.supporters.tierEmpty': '첫 번째 후원자가 되어보세요', + 'settings.about.supporter.tier.noReturnTicket': '편도 티켓', + 'settings.about.supporter.tier.lostLuggageVip': '분실 수하물 VIP', + 'settings.about.supporter.tier.businessClassDreamer': '비즈니스 클래스 꿈꾸기', + 'settings.about.supporter.tier.budgetTraveller': '알뜰 여행자', + 'settings.about.supporter.tier.hostelBunkmate': '호스텔 룸메이트', + 'settings.about.description': 'TREK은 첫 아이디어부터 마지막 추억까지 여행을 체계적으로 관리하는 자체 호스팅 여행 플래너입니다. 일별 계획, 예산, 짐 목록, 사진 등 모든 것이 하나의 서버에 담겨 있습니다.', + 'settings.about.madeWith': '으로 만들어졌습니다', + 'settings.about.madeBy': 'Maurice와 성장하는 오픈 소스 커뮤니티가 함께', + 'settings.username': '사용자 이름', + 'settings.email': '이메일', + 'settings.role': '역할', + 'settings.roleAdmin': '관리자', + 'settings.oidcLinked': '연결됨', + 'settings.changePassword': '비밀번호 변경', + 'settings.currentPassword': '현재 비밀번호', + 'settings.currentPasswordRequired': '현재 비밀번호를 입력하세요', + 'settings.newPassword': '새 비밀번호', + 'settings.confirmPassword': '새 비밀번호 확인', + 'settings.updatePassword': '비밀번호 업데이트', + 'settings.passwordRequired': '현재 비밀번호와 새 비밀번호를 입력하세요', + 'settings.passwordTooShort': '비밀번호는 최소 8자 이상이어야 합니다', + 'settings.passwordMismatch': '비밀번호가 일치하지 않습니다', + 'settings.passwordWeak': '비밀번호는 대문자, 소문자, 숫자, 특수문자를 포함해야 합니다', + 'settings.passwordChanged': '비밀번호가 성공적으로 변경되었습니다', + 'settings.mustChangePassword': '계속하기 전에 비밀번호를 변경해야 합니다. 아래에서 새 비밀번호를 설정하세요.', + 'settings.deleteAccount': '계정 삭제', + 'settings.deleteAccountTitle': '계정을 삭제할까요?', + 'settings.deleteAccountWarning': '계정과 모든 여행, 장소, 파일이 영구 삭제됩니다. 이 작업은 취소할 수 없습니다.', + 'settings.deleteAccountConfirm': '영구 삭제', + 'settings.deleteBlockedTitle': '삭제 불가', + 'settings.deleteBlockedMessage': '유일한 관리자입니다. 계정을 삭제하기 전에 다른 사용자를 관리자로 승격하세요.', + 'settings.roleUser': '사용자', + 'settings.saveProfile': '프로필 저장', + 'settings.toast.mapSaved': '지도 설정이 저장되었습니다', + 'settings.toast.keysSaved': 'API 키가 저장되었습니다', + 'settings.toast.displaySaved': '화면 설정이 저장되었습니다', + 'settings.toast.profileSaved': '프로필이 저장되었습니다', + 'settings.uploadAvatar': '프로필 사진 업로드', + 'settings.removeAvatar': '프로필 사진 삭제', + 'settings.avatarUploaded': '프로필 사진이 업데이트되었습니다', + 'settings.avatarRemoved': '프로필 사진이 삭제되었습니다', + 'settings.avatarError': '업로드 실패', + 'settings.mfa.title': '2단계 인증 (2FA)', + 'settings.mfa.description': '이메일 및 비밀번호로 로그인할 때 두 번째 단계를 추가합니다. 인증 앱 (Google Authenticator, Authy 등)을 사용하세요.', + 'settings.mfa.requiredByPolicy': '관리자가 2단계 인증을 요구합니다. 앱을 계속 사용하려면 아래에서 인증 앱을 설정하세요.', + 'settings.mfa.backupTitle': '백업 코드', + 'settings.mfa.backupDescription': '인증 앱에 접근할 수 없을 때 이 일회용 백업 코드를 사용하세요.', + 'settings.mfa.backupWarning': '지금 이 코드를 저장하세요. 각 코드는 한 번만 사용할 수 있습니다.', + 'settings.mfa.backupCopy': '코드 복사', + 'settings.mfa.backupDownload': 'TXT 다운로드', + 'settings.mfa.backupPrint': '인쇄 / PDF', + 'settings.mfa.backupCopied': '백업 코드가 복사되었습니다', + 'settings.mfa.enabled': '계정에 2FA가 활성화되어 있습니다.', + 'settings.mfa.disabled': '2FA가 활성화되지 않았습니다.', + 'settings.mfa.setup': '인증 앱 설정', + 'settings.mfa.scanQr': '앱으로 이 QR 코드를 스캔하거나 시크릿을 수동으로 입력하세요.', + 'settings.mfa.secretLabel': '시크릿 키 (수동 입력)', + 'settings.mfa.codePlaceholder': '6자리 코드', + 'settings.mfa.enable': '2FA 활성화', + 'settings.mfa.cancelSetup': '취소', + 'settings.mfa.disableTitle': '2FA 비활성화', + 'settings.mfa.disableHint': '계정 비밀번호와 인증 앱의 현재 코드를 입력하세요.', + 'settings.mfa.disable': '2FA 비활성화', + 'settings.mfa.toastEnabled': '2단계 인증이 활성화되었습니다', + 'settings.mfa.toastDisabled': '2단계 인증이 비활성화되었습니다', + 'settings.mfa.demoBlocked': '데모 모드에서는 사용할 수 없습니다', + + // Login + 'login.error': '로그인 실패. 자격 증명을 확인하세요.', + 'login.tagline': '나의 여행.\n나의 계획.', + 'login.description': '인터랙티브 지도, 예산, 실시간 동기화로 함께 여행을 계획하세요.', + 'login.features.maps': '인터랙티브 지도', + 'login.features.mapsDesc': 'Google Places, 경로 및 클러스터링', + 'login.features.realtime': '실시간 동기화', + 'login.features.realtimeDesc': 'WebSocket으로 함께 계획', + 'login.features.budget': '예산 추적', + 'login.features.budgetDesc': '카테고리, 차트 및 1인당 비용', + 'login.features.collab': '협업', + 'login.features.collabDesc': '공유 여행으로 다중 사용자 지원', + 'login.features.packing': '짐 목록', + 'login.features.packingDesc': '카테고리, 진행 상황 및 제안', + 'login.features.bookings': '예약', + 'login.features.bookingsDesc': '항공, 호텔, 레스토랑 등', + 'login.features.files': '문서', + 'login.features.filesDesc': '문서 업로드 및 관리', + 'login.features.routes': '스마트 경로', + 'login.features.routesDesc': '자동 최적화 및 Google Maps 내보내기', + 'login.selfHosted': '자체 호스팅 · 오픈 소스 · 내 데이터는 내 것', + 'login.title': '로그인', + 'login.subtitle': '다시 오신 것을 환영합니다', + 'login.signingIn': '로그인 중…', + 'login.signIn': '로그인', + 'login.createAdmin': '관리자 계정 만들기', + 'login.createAdminHint': 'TREK의 첫 번째 관리자 계정을 설정하세요.', + 'login.setNewPassword': '새 비밀번호 설정', + 'login.setNewPasswordHint': '계속하기 전에 비밀번호를 변경해야 합니다.', + 'login.createAccount': '계정 만들기', + 'login.createAccountHint': '새 계정을 등록하세요.', + 'login.creating': '생성 중…', + 'login.noAccount': '계정이 없으신가요?', + 'login.hasAccount': '이미 계정이 있으신가요?', + 'login.register': '회원가입', + 'login.emailPlaceholder': 'your@email.com', + 'login.username': '사용자 이름', + 'login.oidc.registrationDisabled': '회원가입이 비활성화되어 있습니다. 관리자에게 문의하세요.', + 'login.oidc.noEmail': '공급자로부터 이메일을 받지 못했습니다.', + 'login.oidc.tokenFailed': '인증 실패.', + 'login.oidc.invalidState': '유효하지 않은 세션입니다. 다시 시도하세요.', + 'login.demoFailed': '데모 로그인 실패', + 'login.oidcSignIn': '{name}으로 로그인', + 'login.oidcOnly': '비밀번호 인증이 비활성화되었습니다. SSO 공급자로 로그인하세요.', + 'login.oidcLoggedOut': '로그아웃되었습니다. SSO 공급자로 다시 로그인하세요.', + 'login.demoHint': '데모 체험 — 회원가입 불필요', + 'login.mfaTitle': '2단계 인증', + 'login.mfaSubtitle': '인증 앱의 6자리 코드를 입력하세요.', + 'login.mfaCodeLabel': '인증 코드', + 'login.mfaCodeRequired': '인증 앱의 코드를 입력하세요.', + 'login.mfaHint': 'Google Authenticator, Authy 또는 다른 TOTP 앱을 열어주세요.', + 'login.mfaBack': '← 로그인으로 돌아가기', + 'login.mfaVerify': '인증', + 'login.invalidInviteLink': '유효하지 않거나 만료된 초대 링크입니다', + 'login.oidcFailed': 'OIDC 로그인 실패', + 'login.usernameRequired': '사용자 이름을 입력하세요', + 'login.passwordMinLength': '비밀번호는 최소 8자 이상이어야 합니다', + 'login.forgotPassword': '비밀번호를 잊으셨나요?', + 'login.forgotPasswordTitle': '비밀번호 재설정', + 'login.forgotPasswordBody': '가입 시 사용한 이메일 주소를 입력하세요. 계정이 존재하면 재설정 링크를 보내드립니다.', + 'login.forgotPasswordSubmit': '재설정 링크 전송', + 'login.forgotPasswordSentTitle': '이메일을 확인하세요', + 'login.forgotPasswordSentBody': '해당 이메일로 계정이 있다면 재설정 링크가 전송 중입니다. 링크는 60분 후 만료됩니다.', + 'login.forgotPasswordSmtpHintOff': '알림: 관리자가 SMTP를 설정하지 않아 재설정 링크가 이메일 대신 서버 콘솔에 기록됩니다.', + 'login.backToLogin': '로그인으로 돌아가기', + 'login.newPassword': '새 비밀번호', + 'login.confirmPassword': '새 비밀번호 확인', + 'login.passwordsDontMatch': '비밀번호가 일치하지 않습니다', + 'login.mfaCode': '2FA 코드', + 'login.resetPasswordTitle': '새 비밀번호 설정', + 'login.resetPasswordBody': '이전에 사용하지 않은 강력한 비밀번호를 선택하세요. 최소 8자.', + 'login.resetPasswordMfaBody': '재설정을 완료하려면 2FA 코드 또는 백업 코드를 입력하세요.', + 'login.resetPasswordSubmit': '비밀번호 재설정', + 'login.resetPasswordVerify': '인증 및 재설정', + 'login.resetPasswordSuccessTitle': '비밀번호가 업데이트되었습니다', + 'login.resetPasswordSuccessBody': '새 비밀번호로 로그인할 수 있습니다.', + 'login.resetPasswordInvalidLink': '유효하지 않은 재설정 링크', + 'login.resetPasswordInvalidLinkBody': '이 링크가 없거나 손상되었습니다. 새 링크를 요청하세요.', + 'login.resetPasswordFailed': '재설정 실패. 링크가 만료되었을 수 있습니다.', + + // Register + 'register.passwordMismatch': '비밀번호가 일치하지 않습니다', + 'register.passwordTooShort': '비밀번호는 최소 8자 이상이어야 합니다', + 'register.failed': '회원가입 실패', + 'register.getStarted': '시작하기', + 'register.subtitle': '계정을 만들고 꿈의 여행을 계획하세요.', + 'register.feature1': '무제한 여행 계획', + 'register.feature2': '인터랙티브 지도 보기', + 'register.feature3': '장소 및 카테고리 관리', + 'register.feature4': '예약 추적', + 'register.feature5': '짐 목록 만들기', + 'register.feature6': '사진 및 파일 저장', + 'register.createAccount': '계정 만들기', + 'register.startPlanning': '여행 계획 시작', + 'register.minChars': '최소 6자', + 'register.confirmPassword': '비밀번호 확인', + 'register.repeatPassword': '비밀번호 재입력', + 'register.registering': '가입 중...', + 'register.register': '회원가입', + 'register.hasAccount': '이미 계정이 있으신가요?', + 'register.signIn': '로그인', + + // Admin + 'admin.title': '관리자', + 'admin.subtitle': '사용자 관리 및 시스템 설정', + 'admin.tabs.users': '사용자', + 'admin.tabs.categories': '카테고리', + 'admin.tabs.backup': '백업', + 'admin.tabs.notifications': '알림', + 'admin.tabs.audit': '감사', + 'admin.stats.users': '사용자', + 'admin.stats.trips': '여행', + 'admin.stats.places': '장소', + 'admin.stats.photos': '사진', + 'admin.stats.files': '파일', + 'admin.table.user': '사용자', + 'admin.table.email': '이메일', + 'admin.table.role': '역할', + 'admin.table.created': '생성일', + 'admin.table.lastLogin': '마지막 로그인', + 'admin.table.actions': '작업', + 'admin.you': '(나)', + 'admin.editUser': '사용자 편집', + 'admin.newPassword': '새 비밀번호', + 'admin.newPasswordHint': '비워두면 현재 비밀번호 유지', + 'admin.deleteUser': '사용자 "{name}"을(를) 삭제할까요? 모든 여행이 영구 삭제됩니다.', + 'admin.deleteUserTitle': '사용자 삭제', + 'admin.newPasswordPlaceholder': '새 비밀번호 입력…', + 'admin.toast.loadError': '관리자 데이터 불러오기 실패', + 'admin.toast.userUpdated': '사용자가 업데이트되었습니다', + 'admin.toast.updateError': '업데이트 실패', + 'admin.toast.userDeleted': '사용자가 삭제되었습니다', + 'admin.toast.deleteError': '삭제 실패', + 'admin.toast.cannotDeleteSelf': '자신의 계정은 삭제할 수 없습니다', + 'admin.toast.userCreated': '사용자가 생성되었습니다', + 'admin.toast.createError': '사용자 생성 실패', + 'admin.toast.fieldsRequired': '사용자 이름, 이메일, 비밀번호가 필요합니다', + 'admin.createUser': '사용자 만들기', + 'admin.invite.title': '초대 링크', + 'admin.invite.subtitle': '일회용 회원가입 링크 만들기', + 'admin.invite.create': '링크 만들기', + 'admin.invite.createAndCopy': '만들기 및 복사', + 'admin.invite.empty': '아직 초대 링크가 없습니다', + 'admin.invite.maxUses': '최대 사용 횟수', + 'admin.invite.expiry': '만료 기간', + 'admin.invite.uses': '사용됨', + 'admin.invite.expiresAt': '만료', + 'admin.invite.createdBy': '작성자', + 'admin.invite.active': '활성', + 'admin.invite.expired': '만료됨', + 'admin.invite.usedUp': '사용 완료', + 'admin.invite.copied': '초대 링크가 클립보드에 복사되었습니다', + 'admin.invite.copyLink': '링크 복사', + 'admin.invite.deleted': '초대 링크가 삭제되었습니다', + 'admin.invite.createError': '초대 링크 생성 실패', + 'admin.invite.deleteError': '초대 링크 삭제 실패', + 'admin.tabs.settings': '설정', + 'admin.allowRegistration': '회원가입 허용', + 'admin.allowRegistrationHint': '새 사용자가 직접 회원가입할 수 있습니다', + 'admin.authMethods': '인증 방법', + 'admin.passwordLogin': '비밀번호 로그인', + 'admin.passwordLoginHint': '사용자가 이메일과 비밀번호로 로그인할 수 있습니다', + 'admin.passwordRegistration': '비밀번호 회원가입', + 'admin.passwordRegistrationHint': '새 사용자가 이메일과 비밀번호로 가입할 수 있습니다', + 'admin.oidcLogin': 'SSO 로그인', + 'admin.oidcLoginHint': '사용자가 SSO로 로그인할 수 있습니다', + 'admin.oidcRegistration': 'SSO 자동 프로비저닝', + 'admin.oidcRegistrationHint': '새 SSO 사용자의 계정을 자동으로 생성합니다', + 'admin.envOverrideHint': '비밀번호 로그인 설정은 OIDC_ONLY 환경 변수로 제어되며 여기서 변경할 수 없습니다.', + 'admin.lockoutWarning': '최소 하나의 로그인 방법이 활성화되어 있어야 합니다', + 'admin.requireMfa': '2단계 인증 (2FA) 요구', + 'admin.requireMfaHint': '2FA가 없는 사용자는 앱을 사용하기 전에 설정에서 설정을 완료해야 합니다.', + 'admin.apiKeys': 'API 키', + 'admin.apiKeysHint': '선택 사항. 사진 및 날씨 등 확장된 장소 데이터를 활성화합니다.', + 'admin.mapsKey': 'Google Maps API 키', + 'admin.mapsKeyHint': '장소 검색에 필요합니다. console.cloud.google.com에서 발급', + 'admin.mapsKeyHintLong': 'API 키 없이는 장소 검색에 OpenStreetMap이 사용됩니다. Google API 키가 있으면 사진, 평점, 영업 시간도 불러올 수 있습니다. console.cloud.google.com에서 발급하세요.', + 'admin.recommended': '권장', + 'admin.weatherKey': 'OpenWeatherMap API 키', + 'admin.weatherKeyHint': '날씨 데이터용. openweathermap.org에서 무료 발급', + 'admin.validateKey': '테스트', + 'admin.keyValid': '연결됨', + 'admin.keyInvalid': '유효하지 않음', + 'admin.keySaved': 'API 키가 저장되었습니다', + 'admin.oidcTitle': 'Single Sign-On (OIDC)', + 'admin.oidcSubtitle': 'Google, Apple, Authentik 또는 Keycloak 등 외부 공급자를 통한 로그인을 허용합니다.', + 'admin.oidcDisplayName': '표시 이름', + 'admin.oidcIssuer': '발급자 URL', + 'admin.oidcIssuerHint': '공급자의 OpenID Connect 발급자 URL. 예: https://accounts.google.com', + 'admin.oidcSaved': 'OIDC 설정이 저장되었습니다', + 'admin.oidcOnlyMode': '비밀번호 인증 비활성화', + 'admin.oidcOnlyModeHint': '활성화하면 SSO 로그인만 허용됩니다. 비밀번호 기반 로그인 및 회원가입이 차단됩니다.', + + // File Types + 'admin.fileTypes': '허용된 파일 형식', + 'admin.fileTypesHint': '사용자가 업로드할 수 있는 파일 형식을 설정합니다.', + 'admin.fileTypesFormat': '쉼표로 구분된 확장자 (예: jpg,png,pdf,doc). 모든 형식을 허용하려면 *를 사용하세요.', + 'admin.fileTypesSaved': '파일 형식 설정이 저장되었습니다', + + 'admin.placesPhotos.title': '장소 사진', + 'admin.placesPhotos.subtitle': 'Google Places API에서 사진을 가져옵니다. API 할당량 절약을 위해 비활성화할 수 있습니다. Wikimedia 사진은 영향을 받지 않습니다.', + 'admin.placesAutocomplete.title': '장소 자동완성', + 'admin.placesAutocomplete.subtitle': '검색 제안에 Google Places API를 사용합니다. API 할당량 절약을 위해 비활성화할 수 있습니다.', + 'admin.placesDetails.title': '장소 상세 정보', + 'admin.placesDetails.subtitle': 'Google Places API에서 상세 장소 정보 (영업 시간, 평점, 웹사이트)를 가져옵니다. API 할당량 절약을 위해 비활성화할 수 있습니다.', + // Packing Templates & Bag Tracking + 'admin.bagTracking.title': '가방 추적', + 'admin.bagTracking.subtitle': '짐 항목에 무게 및 가방 배정을 활성화합니다', + 'admin.collab.chat.title': '채팅', + 'admin.collab.chat.subtitle': '여행 협업을 위한 실시간 메시지', + 'admin.collab.notes.title': '메모', + 'admin.collab.notes.subtitle': '공유 메모 및 문서', + 'admin.collab.polls.title': '투표', + 'admin.collab.polls.subtitle': '그룹 투표', + 'admin.collab.whatsnext.title': '다음 할 일', + 'admin.collab.whatsnext.subtitle': '활동 제안 및 다음 단계', + 'admin.tabs.config': '개인 설정', + 'admin.tabs.defaults': '기본값', + 'admin.defaultSettings.title': '기본 사용자 설정', + 'admin.defaultSettings.description': '인스턴스 전체 기본값을 설정합니다. 설정을 변경하지 않은 사용자에게 이 값이 표시됩니다. 사용자의 변경 사항이 항상 우선합니다.', + 'admin.defaultSettings.saved': '기본값이 저장되었습니다', + 'admin.defaultSettings.reset': '기본 내장값으로 초기화', + 'admin.defaultSettings.resetToBuiltIn': '초기화', + 'admin.tabs.templates': '짐 목록 템플릿', + 'admin.packingTemplates.title': '짐 목록 템플릿', + 'admin.packingTemplates.subtitle': '여행을 위한 재사용 가능한 짐 목록을 만드세요', + 'admin.packingTemplates.create': '새 템플릿', + 'admin.packingTemplates.namePlaceholder': '템플릿 이름 (예: 해변 휴가)', + 'admin.packingTemplates.empty': '아직 템플릿이 없습니다', + 'admin.packingTemplates.items': '항목', + 'admin.packingTemplates.categories': '카테고리', + 'admin.packingTemplates.itemName': '항목 이름', + 'admin.packingTemplates.itemCategory': '카테고리', + 'admin.packingTemplates.categoryName': '카테고리 이름 (예: 의류)', + 'admin.packingTemplates.addCategory': '카테고리 추가', + 'admin.packingTemplates.created': '템플릿이 생성되었습니다', + 'admin.packingTemplates.deleted': '템플릿이 삭제되었습니다', + 'admin.packingTemplates.loadError': '템플릿 불러오기 실패', + 'admin.packingTemplates.createError': '템플릿 생성 실패', + 'admin.packingTemplates.deleteError': '템플릿 삭제 실패', + 'admin.packingTemplates.saveError': '저장 실패', + + // Addons + 'admin.tabs.addons': '애드온', + 'admin.addons.title': '애드온', + 'admin.addons.subtitle': '기능을 활성화 또는 비활성화하여 TREK 경험을 맞춤 설정하세요.', + 'admin.addons.catalog.packing.name': '목록', + 'admin.addons.catalog.packing.description': '여행을 위한 짐 목록 및 할 일 작업', + 'admin.addons.catalog.budget.name': '예산', + 'admin.addons.catalog.budget.description': '지출 추적 및 여행 예산 계획', + 'admin.addons.catalog.documents.name': '문서', + 'admin.addons.catalog.documents.description': '여행 서류 저장 및 관리', + 'admin.addons.catalog.vacay.name': 'Vacay', + 'admin.addons.catalog.vacay.description': '캘린더 보기가 있는 개인 휴가 플래너', + 'admin.addons.catalog.atlas.name': 'Atlas', + 'admin.addons.catalog.atlas.description': '방문한 나라와 여행 통계가 있는 세계 지도', + 'admin.addons.catalog.collab.name': 'Collab', + 'admin.addons.catalog.collab.description': '여행 계획을 위한 실시간 메모, 투표, 채팅', + 'admin.addons.catalog.memories.name': '사진 (Immich)', + 'admin.addons.catalog.memories.description': 'Immich 인스턴스를 통해 여행 사진 공유', + 'admin.addons.catalog.mcp.name': 'MCP', + 'admin.addons.catalog.mcp.description': 'AI 어시스턴트 통합을 위한 모델 컨텍스트 프로토콜', + 'admin.addons.subtitleBefore': '기능을 활성화 또는 비활성화하여 ', + 'admin.addons.subtitleAfter': ' 경험을 맞춤 설정하세요.', + 'admin.addons.enabled': '활성화됨', + 'admin.addons.disabled': '비활성화됨', + 'admin.addons.type.trip': '여행', + 'admin.addons.type.global': '전역', + 'admin.addons.type.integration': '통합', + 'admin.addons.tripHint': '각 여행 내 탭으로 사용 가능', + 'admin.addons.globalHint': '메인 내비게이션의 독립 섹션으로 사용 가능', + 'admin.addons.integrationHint': '전용 페이지가 없는 백엔드 서비스 및 API 통합', + 'admin.addons.toast.updated': '애드온이 업데이트되었습니다', + 'admin.addons.toast.error': '애드온 업데이트 실패', + 'admin.addons.noAddons': '사용 가능한 애드온이 없습니다', + // Weather info + 'admin.weather.title': '날씨 데이터', + 'admin.weather.badge': '2026년 3월 24일부터', + 'admin.weather.description': 'TREK은 날씨 데이터 소스로 Open-Meteo를 사용합니다. Open-Meteo는 무료 오픈 소스 날씨 서비스로 API 키가 필요 없습니다.', + 'admin.weather.forecast': '16일 예보', + 'admin.weather.forecastDesc': '이전: 5일 (OpenWeatherMap)', + 'admin.weather.climate': '과거 기후 데이터', + 'admin.weather.climateDesc': '16일 예보 이후 날짜의 85년 평균값', + 'admin.weather.requests': '하루 10,000 요청', + 'admin.weather.requestsDesc': '무료, API 키 불필요', + 'admin.weather.locationHint': '날씨는 각 날의 좌표가 있는 첫 번째 장소를 기준으로 합니다. 날에 배정된 장소가 없으면 장소 목록의 임의 장소가 참조로 사용됩니다.', + + // GitHub + 'admin.tabs.mcpTokens': 'MCP 접근', + 'admin.mcpTokens.title': 'MCP 접근', + 'admin.mcpTokens.subtitle': '모든 사용자의 OAuth 세션 및 API 토큰을 관리합니다', + 'admin.mcpTokens.sectionTitle': 'API 토큰', + 'admin.mcpTokens.owner': '소유자', + 'admin.mcpTokens.tokenName': '토큰 이름', + 'admin.mcpTokens.created': '생성일', + 'admin.mcpTokens.lastUsed': '마지막 사용', + 'admin.mcpTokens.never': '없음', + 'admin.mcpTokens.empty': '생성된 MCP 토큰이 없습니다', + 'admin.mcpTokens.deleteTitle': '토큰 삭제', + 'admin.mcpTokens.deleteMessage': '토큰이 즉시 취소됩니다. 사용자는 이 토큰을 통한 MCP 접근 권한을 잃게 됩니다.', + 'admin.mcpTokens.deleteSuccess': '토큰이 삭제되었습니다', + 'admin.mcpTokens.deleteError': '토큰 삭제 실패', + 'admin.mcpTokens.loadError': '토큰 불러오기 실패', + 'admin.oauthSessions.sectionTitle': 'OAuth 세션', + 'admin.oauthSessions.clientName': '클라이언트', + 'admin.oauthSessions.owner': '소유자', + 'admin.oauthSessions.scopes': '권한 범위', + 'admin.oauthSessions.created': '생성일', + 'admin.oauthSessions.empty': '활성 OAuth 세션이 없습니다', + 'admin.oauthSessions.revokeTitle': '세션 취소', + 'admin.oauthSessions.revokeMessage': 'OAuth 세션이 즉시 취소됩니다. 클라이언트는 MCP 접근 권한을 잃게 됩니다.', + 'admin.oauthSessions.revokeSuccess': '세션이 취소되었습니다', + 'admin.oauthSessions.revokeError': '세션 취소 실패', + 'admin.oauthSessions.loadError': 'OAuth 세션 불러오기 실패', + 'admin.tabs.github': 'GitHub', + + 'admin.audit.subtitle': '보안 및 관리 이벤트 (백업, 사용자, MFA, 설정).', + 'admin.audit.empty': '아직 감사 항목이 없습니다.', + 'admin.audit.refresh': '새로 고침', + 'admin.audit.loadMore': '더 불러오기', + 'admin.audit.showing': '{count}개 불러옴 · 총 {total}개', + 'admin.audit.col.time': '시간', + 'admin.audit.col.user': '사용자', + 'admin.audit.col.action': '작업', + 'admin.audit.col.resource': '리소스', + 'admin.audit.col.ip': 'IP', + 'admin.audit.col.details': '상세', + 'admin.github.title': '릴리스 히스토리', + 'admin.github.subtitle': '{repo}의 최신 업데이트', + 'admin.github.latest': '최신', + 'admin.github.prerelease': '사전 릴리스', + 'admin.github.showDetails': '상세 보기', + 'admin.github.hideDetails': '상세 숨기기', + 'admin.github.loadMore': '더 불러오기', + 'admin.github.loading': '불러오는 중...', + 'admin.github.error': '릴리스 불러오기 실패', + 'admin.github.by': '작성자', + 'admin.github.support': 'TREK 개발 지속에 도움이 됩니다', + + 'admin.update.available': '업데이트 사용 가능', + 'admin.update.text': 'TREK {version}이(가) 사용 가능합니다. 현재 {current}을(를) 실행 중입니다.', + 'admin.update.button': 'GitHub에서 보기', + 'admin.update.install': '업데이트 설치', + 'admin.update.confirmTitle': '업데이트를 설치할까요?', + 'admin.update.confirmText': 'TREK이 {current}에서 {version}으로 업데이트됩니다. 서버가 이후 자동으로 재시작됩니다.', + 'admin.update.dataInfo': '모든 데이터 (여행, 사용자, API 키, 업로드, Vacay, Atlas, 예산)가 보존됩니다.', + 'admin.update.warning': '재시작 중에 앱이 잠시 사용할 수 없게 됩니다.', + 'admin.update.confirm': '지금 업데이트', + 'admin.update.installing': '업데이트 중…', + 'admin.update.success': '업데이트 완료! 서버가 재시작 중입니다…', + 'admin.update.failed': '업데이트 실패', + 'admin.update.backupHint': '업데이트 전에 백업을 생성하는 것을 권장합니다.', + 'admin.update.backupLink': '백업으로 이동', + 'admin.update.howTo': '업데이트 방법', + 'admin.update.dockerText': 'TREK 인스턴스가 Docker에서 실행 중입니다. {version}으로 업데이트하려면 서버에서 다음 명령을 실행하세요:', + 'admin.update.reloadHint': '잠시 후 페이지를 새로 고침하세요.', + + // Vacay addon + 'vacay.subtitle': '휴가 일수를 계획하고 관리하세요', + 'vacay.settings': '설정', + 'vacay.year': '연도', + 'vacay.addYear': '다음 연도 추가', + 'vacay.addPrevYear': '이전 연도 추가', + 'vacay.removeYear': '연도 제거', + 'vacay.removeYearConfirm': '{year}을(를) 제거할까요?', + 'vacay.removeYearHint': '이 연도의 모든 휴가 항목 및 회사 공휴일이 영구 삭제됩니다.', + 'vacay.remove': '제거', + 'vacay.persons': '인원', + 'vacay.noPersons': '추가된 인원이 없습니다', + 'vacay.addPerson': '인원 추가', + 'vacay.editPerson': '인원 편집', + 'vacay.removePerson': '인원 제거', + 'vacay.removePersonConfirm': '{name}을(를) 제거할까요?', + 'vacay.removePersonHint': '이 인원의 모든 휴가 항목이 영구 삭제됩니다.', + 'vacay.personName': '이름', + 'vacay.personNamePlaceholder': '이름 입력', + 'vacay.color': '색상', + 'vacay.add': '추가', + 'vacay.legend': '범례', + 'vacay.publicHoliday': '공휴일', + 'vacay.companyHoliday': '회사 휴일', + 'vacay.weekend': '주말', + 'vacay.modeVacation': '휴가', + 'vacay.modeCompany': '회사 휴일', + 'vacay.entitlement': '휴가 일수', + 'vacay.entitlementDays': '일', + 'vacay.used': '사용', + 'vacay.remaining': '남음', + 'vacay.carriedOver': '{year}에서 이월', + 'vacay.blockWeekends': '주말 차단', + 'vacay.blockWeekendsHint': '주말에 휴가 항목 추가를 방지합니다', + 'vacay.weekendDays': '주말 요일', + 'vacay.mon': '월', + 'vacay.tue': '화', + 'vacay.wed': '수', + 'vacay.thu': '목', + 'vacay.fri': '금', + 'vacay.sat': '토', + 'vacay.sun': '일', + 'vacay.publicHolidays': '공휴일', + 'vacay.publicHolidaysHint': '캘린더에 공휴일을 표시합니다', + 'vacay.selectCountry': '국가 선택', + 'vacay.selectRegion': '지역 선택 (선택)', + 'vacay.addCalendar': '캘린더 추가', + 'vacay.calendarLabel': '레이블 (선택)', + 'vacay.calendarColor': '색상', + 'vacay.noCalendars': '아직 공휴일 캘린더가 없습니다', + 'vacay.companyHolidays': '회사 휴일', + 'vacay.companyHolidaysHint': '회사 전체 휴일 표시를 허용합니다', + 'vacay.companyHolidaysNoDeduct': '회사 휴일은 휴가 일수에서 차감되지 않습니다.', + 'vacay.weekStart': '주 시작 요일', + 'vacay.weekStartHint': '캘린더 주가 월요일 또는 일요일에 시작할지 선택하세요', + 'vacay.carryOver': '이월', + 'vacay.carryOverHint': '남은 휴가 일수를 다음 연도로 자동 이월합니다', + 'vacay.sharing': '공유', + 'vacay.sharingHint': '다른 TREK 사용자와 휴가 계획을 공유합니다', + 'vacay.owner': '소유자', + 'vacay.shareEmailPlaceholder': 'TREK 사용자 이메일', + 'vacay.shareSuccess': '계획이 성공적으로 공유되었습니다', + 'vacay.shareError': '계획 공유 실패', + 'vacay.dissolve': '퓨전 해제', + 'vacay.dissolveHint': '캘린더를 다시 분리합니다. 항목은 유지됩니다.', + 'vacay.dissolveAction': '해제', + 'vacay.dissolved': '캘린더가 분리되었습니다', + 'vacay.fusedWith': '퓨전됨', + 'vacay.you': '나', + 'vacay.noData': '데이터 없음', + 'vacay.changeColor': '색상 변경', + 'vacay.inviteUser': '사용자 초대', + 'vacay.inviteHint': '다른 TREK 사용자를 초대하여 통합 휴가 캘린더를 공유하세요.', + 'vacay.selectUser': '사용자 선택', + 'vacay.sendInvite': '초대 전송', + 'vacay.inviteSent': '초대가 전송되었습니다', + 'vacay.inviteError': '초대 전송 실패', + 'vacay.pending': '대기 중', + 'vacay.noUsersAvailable': '사용 가능한 사용자가 없습니다', + 'vacay.accept': '수락', + 'vacay.decline': '거절', + 'vacay.acceptFusion': '수락 및 퓨전', + 'vacay.inviteTitle': '퓨전 요청', + 'vacay.inviteWantsToFuse': '귀하와 휴가 캘린더를 공유하고 싶어 합니다.', + 'vacay.fuseInfo1': '두 사람 모두 하나의 공유 캘린더에서 모든 휴가 항목을 볼 수 있습니다.', + 'vacay.fuseInfo2': '양측 모두 서로의 항목을 만들고 편집할 수 있습니다.', + 'vacay.fuseInfo3': '양측 모두 항목을 삭제하고 휴가 일수를 변경할 수 있습니다.', + 'vacay.fuseInfo4': '공휴일 및 회사 휴일 등의 설정이 공유됩니다.', + 'vacay.fuseInfo5': '어느 쪽이든 언제든지 퓨전을 해제할 수 있습니다. 항목은 보존됩니다.', + 'nav.myTrips': '내 여행', + + // Atlas addon + 'atlas.subtitle': '전 세계의 나의 여행 발자취', + 'atlas.countries': '국가', + 'atlas.trips': '여행', + 'atlas.places': '장소', + 'atlas.unmark': '제거', + 'atlas.confirmMark': '이 나라를 방문한 곳으로 표시할까요?', + 'atlas.confirmUnmark': '방문 목록에서 이 나라를 제거할까요?', + 'atlas.confirmUnmarkRegion': '방문 목록에서 이 지역을 제거할까요?', + 'atlas.markVisited': '방문으로 표시', + 'atlas.markVisitedHint': '방문 목록에 이 나라를 추가합니다', + 'atlas.markRegionVisitedHint': '방문 목록에 이 지역을 추가합니다', + 'atlas.addToBucket': '버킷 리스트에 추가', + 'atlas.addPoi': '장소 추가', + 'atlas.searchCountry': '국가 검색...', + 'atlas.bucketNamePlaceholder': '이름 (국가, 도시, 장소...)', + 'atlas.month': '월', + 'atlas.year': '연도', + 'atlas.addToBucketHint': '방문하고 싶은 장소로 저장', + 'atlas.bucketWhen': '방문 예정 시기는 언제인가요?', + 'atlas.statsTab': '통계', + 'atlas.bucketTab': '버킷 리스트', + 'atlas.addBucket': '버킷 리스트에 추가', + 'atlas.bucketNotesPlaceholder': '메모 (선택)', + 'atlas.bucketEmpty': '버킷 리스트가 비어 있습니다', + 'atlas.bucketEmptyHint': '꿈꾸는 방문지를 추가하세요', + 'atlas.days': '일', + 'atlas.visitedCountries': '방문한 나라', + 'atlas.cities': '도시', + 'atlas.noData': '아직 여행 데이터가 없습니다', + 'atlas.noDataHint': '여행을 만들고 장소를 추가하여 세계 지도를 확인하세요', + 'atlas.lastTrip': '마지막 여행', + 'atlas.nextTrip': '다음 여행', + 'atlas.daysLeft': '일 남음', + 'atlas.streak': '연속', + 'atlas.years': '년', + 'atlas.yearInRow': '연 연속', + 'atlas.yearsInRow': '년 연속', + 'atlas.tripIn': '에서 여행', + 'atlas.tripsIn': '에서 여행', + 'atlas.since': '부터', + 'atlas.europe': '유럽', + 'atlas.asia': '아시아', + 'atlas.northAmerica': '북미', + 'atlas.southAmerica': '남미', + 'atlas.africa': '아프리카', + 'atlas.oceania': '오세아니아', + 'atlas.other': '기타', + 'atlas.firstVisit': '첫 번째 여행', + 'atlas.lastVisitLabel': '마지막 여행', + 'atlas.tripSingular': '여행', + 'atlas.tripPlural': '여행', + 'atlas.placeVisited': '방문한 장소', + 'atlas.placesVisited': '방문한 장소', + + // Trip Planner + 'trip.tabs.plan': '계획', + 'trip.tabs.transports': '교통', + 'trip.tabs.reservations': '예약', + 'trip.tabs.reservationsShort': '예약', + 'trip.tabs.packing': '짐 목록', + 'trip.tabs.packingShort': '짐', + 'trip.tabs.lists': '목록', + 'trip.tabs.listsShort': '목록', + 'trip.tabs.budget': '예산', + 'trip.tabs.files': '파일', + 'trip.loading': '여행 불러오는 중...', + 'trip.loadingPhotos': '장소 사진 불러오는 중...', + 'trip.mobilePlan': '계획', + 'trip.mobilePlaces': '장소', + 'trip.toast.placeUpdated': '장소가 업데이트되었습니다', + 'trip.toast.placeAdded': '장소가 추가되었습니다', + 'trip.toast.placeDeleted': '장소가 삭제되었습니다', + 'trip.toast.selectDay': '먼저 날을 선택하세요', + 'trip.toast.assignedToDay': '장소가 날에 배정되었습니다', + 'trip.toast.reorderError': '순서 변경 실패', + 'trip.toast.reservationUpdated': '예약이 업데이트되었습니다', + 'trip.toast.reservationAdded': '예약이 추가되었습니다', + 'trip.toast.deleted': '삭제됨', + 'trip.confirm.deletePlace': '이 장소를 삭제할까요?', + 'trip.confirm.deletePlaces': '{count}개 장소를 삭제할까요?', + 'trip.toast.placesDeleted': '{count}개 장소가 삭제되었습니다', + + // Day Plan Sidebar + 'dayplan.emptyDay': '이 날에 계획된 장소가 없습니다', + 'dayplan.cannotReorderTransport': '고정된 시간이 있는 예약은 순서를 변경할 수 없습니다', + 'dayplan.confirmRemoveTimeTitle': '시간을 제거할까요?', + 'dayplan.confirmRemoveTimeBody': '이 장소에 고정된 시간 ({time})이 있습니다. 이동하면 시간이 제거되고 자유 정렬이 허용됩니다.', + 'dayplan.confirmRemoveTimeAction': '시간 제거 및 이동', + 'dayplan.cannotDropOnTimed': '시간이 고정된 항목 사이에 배치할 수 없습니다', + 'dayplan.cannotBreakChronology': '이 작업은 시간 고정 항목과 예약의 시간 순서를 깨뜨립니다', + 'dayplan.addNote': '메모 추가', + 'dayplan.expandAll': '모든 날 펼치기', + 'dayplan.collapseAll': '모든 날 접기', + 'dayplan.editNote': '메모 편집', + 'dayplan.noteAdd': '메모 추가', + 'dayplan.noteEdit': '메모 편집', + 'dayplan.noteTitle': '메모', + 'dayplan.noteSubtitle': '일별 메모', + 'dayplan.totalCost': '총 비용', + 'dayplan.days': '일', + 'dayplan.dayN': '{n}일차', + 'dayplan.calculating': '계산 중...', + 'dayplan.route': '경로', + 'dayplan.optimize': '최적화', + 'dayplan.optimized': '경로가 최적화되었습니다', + 'dayplan.routeError': '경로 계산 실패', + 'dayplan.toast.needTwoPlaces': '경로 최적화에는 최소 두 개의 장소가 필요합니다', + 'dayplan.toast.routeOptimized': '경로가 최적화되었습니다', + 'dayplan.toast.noGeoPlaces': '경로 계산을 위한 좌표가 있는 장소가 없습니다', + 'dayplan.confirmed': '확정됨', + 'dayplan.pendingRes': '대기 중', + 'dayplan.pdf': 'PDF', + 'dayplan.pdfTooltip': '일별 계획을 PDF로 내보내기', + 'dayplan.pdfError': 'PDF 내보내기 실패', + + // Places Sidebar + 'places.addPlace': '장소/활동 추가', + 'places.importFile': '파일 가져오기', + 'places.sidebarDrop': '끌어다 가져오기', + 'places.importFileHint': 'Google My Maps, Google Earth 또는 GPS 추적기 등의 .gpx, .kml, .kmz 파일을 가져옵니다.', + 'places.importFileDropHere': '파일을 선택하거나 여기에 끌어다 놓으세요', + 'places.importFileDropActive': '파일을 놓으세요', + 'places.importFileUnsupported': '지원하지 않는 파일 형식입니다. .gpx, .kml 또는 .kmz를 사용하세요.', + 'places.importFileTooLarge': '파일이 너무 큽니다. 최대 업로드 크기는 {maxMb} MB입니다.', + 'places.importFileError': '가져오기 실패', + 'places.importAllSkipped': '모든 장소가 이미 여행에 포함되어 있습니다.', + 'places.gpxImported': 'GPX에서 {count}개 장소를 가져왔습니다', + 'places.gpxImportTypes': '무엇을 가져올까요?', + 'places.gpxImportWaypoints': '웨이포인트', + 'places.gpxImportRoutes': '경로', + 'places.gpxImportTracks': '트랙 (경로 형상 포함)', + 'places.gpxImportNoneSelected': '가져올 유형을 하나 이상 선택하세요.', + 'places.kmlImportTypes': '무엇을 가져올까요?', + 'places.kmlImportPoints': '포인트 (Placemarks)', + 'places.kmlImportPaths': '경로 (LineStrings)', + 'places.kmlImportNoneSelected': '가져올 유형을 하나 이상 선택하세요.', + 'places.selectionCount': '{count}개 선택됨', + 'places.deleteSelected': '선택 항목 삭제', + 'places.kmlKmzImported': 'KMZ/KML에서 {count}개 장소를 가져왔습니다', + 'places.urlResolved': 'URL에서 장소를 가져왔습니다', + 'places.importList': '목록 가져오기', + 'places.kmlKmzSummaryValues': '총 Placemarks: {total} · 가져옴: {created} · 건너뜀: {skipped}', + 'places.importGoogleList': 'Google 목록', + 'places.importNaverList': '네이버 목록', + 'places.googleListHint': '공유된 Google Maps 목록 링크를 붙여넣어 모든 장소를 가져옵니다.', + 'places.googleListImported': '"{list}"에서 {count}개 장소를 가져왔습니다', + 'places.googleListError': 'Google Maps 목록 가져오기 실패', + 'places.naverListHint': '공유된 네이버 지도 목록 링크를 붙여넣어 모든 장소를 가져옵니다.', + 'places.naverListImported': '"{list}"에서 {count}개 장소를 가져왔습니다', + 'places.naverListError': '네이버 지도 목록 가져오기 실패', + 'places.viewDetails': '상세 보기', + 'places.assignToDay': '어느 날에 추가할까요?', + 'places.all': '전체', + 'places.unplanned': '미계획', + 'places.filterTracks': '트랙', + 'places.search': '장소 검색...', + 'places.allCategories': '모든 카테고리', + 'places.categoriesSelected': '카테고리', + 'places.clearFilter': '필터 지우기', + 'places.count': '장소 {count}개', + 'places.countSingular': '장소 1개', + 'places.allPlanned': '모든 장소가 계획되었습니다', + 'places.noneFound': '장소를 찾을 수 없습니다', + 'places.editPlace': '장소 편집', + 'places.formName': '이름', + 'places.formNamePlaceholder': '예: 에펠탑', + 'places.formDescription': '설명', + 'places.formDescriptionPlaceholder': '간단한 설명...', + 'places.formAddress': '주소', + 'places.formAddressPlaceholder': '도로, 도시, 국가', + 'places.formLat': '위도 (예: 48.8566)', + 'places.formLng': '경도 (예: 2.3522)', + 'places.formCategory': '카테고리', + 'places.noCategory': '카테고리 없음', + 'places.categoryNamePlaceholder': '카테고리 이름', + 'places.formTime': '시간', + 'places.startTime': '시작', + 'places.endTime': '종료', + 'places.endTimeBeforeStart': '종료 시간이 시작 시간보다 앞입니다', + 'places.timeCollision': '시간 겹침:', + 'places.formWebsite': '웹사이트', + 'places.formNotes': '메모', + 'places.formNotesPlaceholder': '개인 메모...', + 'places.formReservation': '예약', + 'places.reservationNotesPlaceholder': '예약 메모, 확인 번호...', + 'places.mapsSearchPlaceholder': '장소 검색...', + 'places.mapsSearchError': '장소 검색 실패.', + 'places.loadingDetails': '장소 상세 정보 불러오는 중…', + 'places.osmHint': 'OpenStreetMap 검색 사용 중 (사진, 영업 시간, 평점 없음). 전체 정보를 위해 설정에서 Google API 키를 추가하세요.', + 'places.osmActive': 'OpenStreetMap으로 검색 중 (사진, 평점, 영업 시간 없음). 향상된 데이터를 위해 설정에서 Google API 키를 추가하세요.', + 'places.categoryCreateError': '카테고리 생성 실패', + 'places.nameRequired': '이름을 입력하세요', + 'places.saveError': '저장 실패', + // Place Inspector + 'inspector.opened': '영업 중', + 'inspector.closed': '영업 종료', + 'inspector.openingHours': '영업 시간', + 'inspector.showHours': '영업 시간 보기', + 'inspector.files': '파일', + 'inspector.filesCount': '{count}개 파일', + 'inspector.remove': '제거', + 'inspector.removeFromDay': '날에서 제거', + 'inspector.addToDay': '날에 추가', + 'inspector.confirmedRes': '확정된 예약', + 'inspector.pendingRes': '대기 중인 예약', + 'inspector.google': 'Google Maps에서 열기', + 'inspector.website': '웹사이트 열기', + 'inspector.addRes': '예약', + 'inspector.editRes': '예약 편집', + 'inspector.participants': '참가자', + 'inspector.trackStats': '트랙 통계', + + // Reservations + 'reservations.title': '예약', + 'reservations.empty': '아직 예약이 없습니다', + 'reservations.emptyHint': '항공, 호텔 등의 예약을 추가하세요', + 'reservations.add': '예약 추가', + 'reservations.addManual': '직접 예약', + 'reservations.placeHint': '팁: 예약은 일별 계획과 연결하기 위해 장소에서 직접 만드는 것이 가장 좋습니다.', + 'reservations.confirmed': '확정됨', + 'reservations.pending': '대기 중', + 'reservations.summary': '{confirmed}개 확정, {pending}개 대기 중', + 'reservations.fromPlan': '계획에서', + 'reservations.showFiles': '파일 보기', + 'reservations.editTitle': '예약 편집', + 'reservations.status': '상태', + 'reservations.datetime': '날짜 및 시간', + 'reservations.startTime': '시작 시간', + 'reservations.endTime': '종료 시간', + 'reservations.date': '날짜', + 'reservations.time': '시간', + 'reservations.timeAlt': '시간 (대안, 예: 19:30)', + 'reservations.notes': '메모', + 'reservations.notesPlaceholder': '추가 메모...', + 'reservations.meta.airline': '항공사', + 'reservations.meta.flightNumber': '항공편 번호', + 'reservations.meta.from': '출발', + 'reservations.meta.to': '도착', + 'reservations.needsReview': '검토 필요', + 'reservations.needsReviewHint': '공항이 자동으로 매칭되지 않았습니다 — 위치를 확인해 주세요.', + 'reservations.searchLocation': '역, 항구, 주소 검색…', + 'airport.searchPlaceholder': '공항 코드 또는 도시 (예: ICN)', + 'map.connections': '연결', + 'map.showConnections': '예약 경로 표시', + 'map.hideConnections': '예약 경로 숨기기', + 'reservations.meta.trainNumber': '열차 번호', + 'reservations.meta.platform': '플랫폼', + 'reservations.meta.seat': '좌석', + 'reservations.meta.checkIn': '체크인', + 'reservations.meta.checkInUntil': '체크인 마감', + 'reservations.meta.checkOut': '체크아웃', + 'reservations.meta.linkAccommodation': '숙박', + 'reservations.meta.pickAccommodation': '숙박 연결', + 'reservations.meta.noAccommodation': '없음', + 'reservations.meta.hotelPlace': '숙박', + 'reservations.meta.pickHotel': '숙박 선택', + 'reservations.meta.fromDay': '부터', + 'reservations.meta.toDay': '까지', + 'reservations.meta.selectDay': '날 선택', + 'reservations.type.flight': '항공', + 'reservations.type.hotel': '숙박', + 'reservations.type.restaurant': '레스토랑', + 'reservations.type.train': '기차', + 'reservations.type.car': '차량', + 'reservations.type.cruise': '크루즈', + 'reservations.type.event': '이벤트', + 'reservations.type.tour': '투어', + 'reservations.type.other': '기타', + 'reservations.confirm.delete': '예약 "{name}"을(를) 삭제할까요?', + 'reservations.confirm.deleteTitle': '예약을 삭제할까요?', + 'reservations.confirm.deleteBody': '"{name}"이(가) 영구 삭제됩니다.', + 'reservations.toast.updated': '예약이 업데이트되었습니다', + 'reservations.toast.removed': '예약이 삭제되었습니다', + 'reservations.toast.fileUploaded': '파일이 업로드되었습니다', + 'reservations.toast.uploadError': '업로드 실패', + 'reservations.newTitle': '새 예약', + 'reservations.bookingType': '예약 유형', + 'reservations.titleLabel': '제목', + 'reservations.titlePlaceholder': '예: 대한항공 KE123, 호텔 신라, ...', + 'reservations.locationAddress': '위치 / 주소', + 'reservations.locationPlaceholder': '주소, 공항, 호텔...', + 'reservations.confirmationCode': '예약 코드', + 'reservations.confirmationPlaceholder': '예: ABC12345', + 'reservations.day': '날', + 'reservations.noDay': '날 없음', + 'reservations.place': '장소', + 'reservations.noPlace': '장소 없음', + 'reservations.pendingSave': '저장될 예정…', + 'reservations.uploading': '업로드 중...', + 'reservations.attachFile': '파일 첨부', + 'reservations.linkExisting': '기존 파일 연결', + 'reservations.toast.saveError': '저장 실패', + 'reservations.toast.updateError': '업데이트 실패', + 'reservations.toast.deleteError': '삭제 실패', + 'reservations.confirm.remove': '"{name}"의 예약을 제거할까요?', + 'reservations.linkAssignment': '날 배정에 연결', + 'reservations.pickAssignment': '계획에서 배정을 선택하세요...', + 'reservations.noAssignment': '연결 없음 (독립)', + 'reservations.price': '가격', + 'reservations.budgetCategory': '예산 카테고리', + 'reservations.budgetCategoryPlaceholder': '예: 교통, 숙박', + 'reservations.budgetCategoryAuto': '자동 (예약 유형에서)', + 'reservations.budgetHint': '저장 시 예산 항목이 자동으로 생성됩니다.', + 'reservations.departureDate': '출발', + 'reservations.arrivalDate': '도착', + 'reservations.departureTime': '출발 시간', + 'reservations.arrivalTime': '도착 시간', + 'reservations.pickupDate': '픽업', + 'reservations.returnDate': '반납', + 'reservations.pickupTime': '픽업 시간', + 'reservations.returnTime': '반납 시간', + 'reservations.endDate': '종료 날짜', + 'reservations.meta.departureTimezone': '출발 시간대', + 'reservations.meta.arrivalTimezone': '도착 시간대', + 'reservations.span.departure': '출발', + 'reservations.span.arrival': '도착', + 'reservations.span.inTransit': '이동 중', + 'reservations.span.pickup': '픽업', + 'reservations.span.return': '반납', + 'reservations.span.active': '활성', + 'reservations.span.start': '시작', + 'reservations.span.end': '종료', + 'reservations.span.ongoing': '진행 중', + 'reservations.validation.endBeforeStart': '종료 날짜/시간은 시작 날짜/시간 이후여야 합니다', + 'reservations.addBooking': '예약 추가', + + // Budget + 'budget.title': '예산', + 'budget.exportCsv': 'CSV 내보내기', + 'budget.emptyTitle': '아직 예산이 없습니다', + 'budget.emptyText': '카테고리와 항목을 만들어 여행 예산을 계획하세요', + 'budget.emptyPlaceholder': '카테고리 이름을 입력하세요...', + 'budget.createCategory': '카테고리 만들기', + 'budget.category': '카테고리', + 'budget.categoryName': '카테고리 이름', + 'budget.table.name': '이름', + 'budget.table.total': '합계', + 'budget.table.persons': '인원', + 'budget.table.days': '일수', + 'budget.table.perPerson': '1인당', + 'budget.table.perDay': '일당', + 'budget.table.perPersonDay': '1인/일', + 'budget.table.note': '메모', + 'budget.table.date': '날짜', + 'budget.newEntry': '새 항목', + 'budget.defaultEntry': '새 항목', + 'budget.defaultCategory': '새 카테고리', + 'budget.total': '합계', + 'budget.totalBudget': '총 예산', + 'budget.byCategory': '카테고리별', + 'budget.editTooltip': '클릭하여 편집', + 'budget.linkedToReservation': '예약에 연결됨 — 이름은 예약에서 편집하세요', + 'budget.confirm.deleteCategory': '카테고리 "{name}"을(를) {count}개 항목과 함께 삭제할까요?', + 'budget.deleteCategory': '카테고리 삭제', + 'budget.perPerson': '1인당', + 'budget.paid': '지불됨', + 'budget.open': '미결', + 'budget.noMembers': '배정된 멤버가 없습니다', + 'budget.settlement': '정산', + 'budget.settlementInfo': '예산 항목의 멤버 아바타를 클릭하면 녹색으로 표시됩니다 — 해당 멤버가 지불했음을 의미합니다. 그러면 정산에서 누가 누구에게 얼마를 지불해야 하는지 보여줍니다.', + 'budget.netBalances': '순 잔액', + + // Files + 'files.title': '파일', + 'files.pageTitle': '파일 및 서류', + 'files.subtitle': '{trip}의 파일 {count}개', + 'files.download': '다운로드', + 'files.openError': '파일을 열 수 없습니다', + 'files.downloadPdf': 'PDF 다운로드', + 'files.count': '파일 {count}개', + 'files.countSingular': '파일 1개', + 'files.uploaded': '{count}개 업로드됨', + 'files.uploadError': '업로드 실패', + 'files.dropzone': '여기에 파일을 놓으세요', + 'files.dropzoneHint': '또는 클릭하여 탐색', + 'files.allowedTypes': '이미지, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · 최대 50 MB', + 'files.uploading': '업로드 중...', + 'files.filterAll': '전체', + 'files.filterPdf': 'PDF', + 'files.filterImages': '이미지', + 'files.filterDocs': '문서', + 'files.filterCollab': 'Collab 메모', + 'files.sourceCollab': 'Collab 메모에서', + 'files.empty': '아직 파일이 없습니다', + 'files.emptyHint': '파일을 업로드하여 여행에 첨부하세요', + 'files.openTab': '새 탭에서 열기', + 'files.confirm.delete': '이 파일을 삭제할까요?', + 'files.toast.deleted': '파일이 삭제되었습니다', + 'files.toast.deleteError': '파일 삭제 실패', + 'files.sourcePlan': '일별 계획', + 'files.sourceBooking': '예약', + 'files.sourceTransport': '교통', + 'files.attach': '첨부', + 'files.pasteHint': '클립보드에서 이미지를 붙여넣을 수도 있습니다 (Ctrl+V)', + 'files.trash': '휴지통', + 'files.trashEmpty': '휴지통이 비어 있습니다', + 'files.emptyTrash': '휴지통 비우기', + 'files.restore': '복원', + 'files.star': '즐겨찾기', + 'files.unstar': '즐겨찾기 해제', + 'files.assign': '배정', + 'files.assignTitle': '파일 배정', + 'files.assignPlace': '장소', + 'files.assignBooking': '예약', + 'files.assignTransport': '교통', + 'files.unassigned': '미배정', + 'files.unlink': '연결 해제', + 'files.toast.trashed': '휴지통으로 이동됨', + 'files.toast.restored': '파일이 복원되었습니다', + 'files.toast.trashEmptied': '휴지통이 비워졌습니다', + 'files.toast.assigned': '파일이 배정되었습니다', + 'files.toast.assignError': '배정 실패', + 'files.toast.restoreError': '복원 실패', + 'files.confirm.permanentDelete': '이 파일을 영구 삭제할까요? 이 작업은 취소할 수 없습니다.', + 'files.confirm.emptyTrash': '휴지통의 모든 파일을 영구 삭제할까요? 이 작업은 취소할 수 없습니다.', + 'files.noteLabel': '메모', + 'files.notePlaceholder': '메모 추가...', + + // Packing + 'packing.title': '짐 목록', + 'packing.empty': '짐 목록이 비어 있습니다', + 'packing.import': '가져오기', + 'packing.importTitle': '짐 목록 가져오기', + 'packing.importHint': '한 줄에 하나의 항목. 형식: 카테고리, 이름, 무게(g, 선택), 가방(선택), checked/unchecked(선택)', + 'packing.importPlaceholder': '위생, 칫솔\n의류, 티셔츠, 200\n서류, 여권, , 기내 수하물\n전자기기, 충전기, 50, 캐리어, checked', + 'packing.importCsv': 'CSV/TXT 불러오기', + 'packing.importAction': '{count}개 가져오기', + 'packing.importSuccess': '{count}개 항목을 가져왔습니다', + 'packing.importError': '가져오기 실패', + 'packing.importEmpty': '가져올 항목이 없습니다', + 'packing.progress': '{total}개 중 {packed}개 완료 ({percent}%)', + 'packing.clearChecked': '체크된 {count}개 제거', + 'packing.clearCheckedShort': '{count}개 제거', + 'packing.suggestions': '제안', + 'packing.suggestionsTitle': '제안 추가', + 'packing.allSuggested': '모든 제안이 추가되었습니다', + 'packing.allPacked': '모두 완료!', + 'packing.addPlaceholder': '새 항목 추가...', + 'packing.categoryPlaceholder': '카테고리...', + 'packing.filterAll': '전체', + 'packing.filterOpen': '미완료', + 'packing.filterDone': '완료', + 'packing.emptyTitle': '짐 목록이 비어 있습니다', + 'packing.emptyHint': '항목을 추가하거나 제안을 사용하세요', + 'packing.emptyFiltered': '이 필터와 일치하는 항목이 없습니다', + 'packing.menuRename': '이름 변경', + 'packing.menuCheckAll': '전체 체크', + 'packing.menuUncheckAll': '전체 체크 해제', + 'packing.menuDeleteCat': '카테고리 삭제', + 'packing.noMembers': '여행 멤버가 없습니다', + 'packing.addItem': '항목 추가', + 'packing.addItemPlaceholder': '항목 이름...', + 'packing.addCategory': '카테고리 추가', + 'packing.newCategoryPlaceholder': '카테고리 이름 (예: 의류)', + 'packing.applyTemplate': '템플릿 적용', + 'packing.template': '템플릿', + 'packing.templateApplied': '템플릿에서 {count}개 항목이 추가되었습니다', + 'packing.templateError': '템플릿 적용 실패', + 'packing.saveAsTemplate': '템플릿으로 저장', + 'packing.templateName': '템플릿 이름', + 'packing.templateSaved': '짐 목록이 템플릿으로 저장되었습니다', + 'packing.bags': '가방', + 'packing.noBag': '미배정', + 'packing.totalWeight': '총 무게', + 'packing.bagName': '가방 이름...', + 'packing.addBag': '가방 추가', + 'packing.changeCategory': '카테고리 변경', + 'packing.confirm.clearChecked': '체크된 {count}개 항목을 제거할까요?', + 'packing.confirm.deleteCat': '카테고리 "{name}"을(를) {count}개 항목과 함께 삭제할까요?', + 'packing.defaultCategory': '기타', + 'packing.toast.saveError': '저장 실패', + 'packing.toast.deleteError': '삭제 실패', + 'packing.toast.renameError': '이름 변경 실패', + 'packing.toast.addError': '추가 실패', + + // Packing suggestions + 'packing.suggestions.items': [ + { name: '여권', category: '서류' }, + { name: '신분증', category: '서류' }, + { name: '여행자 보험', category: '서류' }, + { name: '항공권', category: '서류' }, + { name: '신용카드', category: '금융' }, + { name: '현금', category: '금융' }, + { name: '비자', category: '서류' }, + { name: '티셔츠', category: '의류' }, + { name: '바지', category: '의류' }, + { name: '속옷', category: '의류' }, + { name: '양말', category: '의류' }, + { name: '재킷', category: '의류' }, + { name: '잠옷', category: '의류' }, + { name: '수영복', category: '의류' }, + { name: '우비', category: '의류' }, + { name: '편한 신발', category: '의류' }, + { name: '칫솔', category: '세면도구' }, + { name: '치약', category: '세면도구' }, + { name: '샴푸', category: '세면도구' }, + { name: '데오도란트', category: '세면도구' }, + { name: '자외선 차단제', category: '세면도구' }, + { name: '면도기', category: '세면도구' }, + { name: '충전기', category: '전자기기' }, + { name: '보조 배터리', category: '전자기기' }, + { name: '헤드폰', category: '전자기기' }, + { name: '여행용 어댑터', category: '전자기기' }, + { name: '카메라', category: '전자기기' }, + { name: '진통제', category: '건강' }, + { name: '반창고', category: '건강' }, + { name: '소독제', category: '건강' }, + ], + + // Members / Sharing + 'members.shareTrip': '여행 공유', + 'members.inviteUser': '사용자 초대', + 'members.selectUser': '사용자 선택…', + 'members.invite': '초대', + 'members.allHaveAccess': '모든 사용자가 이미 접근 권한을 가지고 있습니다.', + 'members.access': '접근', + 'members.person': '명', + 'members.persons': '명', + 'members.you': '나', + 'members.owner': '소유자', + 'members.leaveTrip': '여행 떠나기', + 'members.removeAccess': '접근 권한 제거', + 'members.confirmLeave': '여행을 떠날까요? 접근 권한을 잃게 됩니다.', + 'members.confirmRemove': '이 사용자의 접근 권한을 제거할까요?', + 'members.loadError': '멤버 불러오기 실패', + 'members.added': '추가됨', + 'members.addError': '추가 실패', + 'members.removed': '멤버가 제거되었습니다', + 'members.removeError': '제거 실패', + + // Categories (Admin) + 'categories.title': '카테고리', + 'categories.subtitle': '장소 카테고리 관리', + 'categories.new': '새 카테고리', + 'categories.empty': '아직 카테고리가 없습니다', + 'categories.namePlaceholder': '카테고리 이름', + 'categories.icon': '아이콘', + 'categories.color': '색상', + 'categories.customColor': '사용자 지정 색상 선택', + 'categories.preview': '미리보기', + 'categories.defaultName': '카테고리', + 'categories.update': '업데이트', + 'categories.create': '생성', + 'categories.confirm.delete': '카테고리를 삭제할까요? 이 카테고리의 장소는 삭제되지 않습니다.', + 'categories.toast.loadError': '카테고리 불러오기 실패', + 'categories.toast.nameRequired': '이름을 입력하세요', + 'categories.toast.updated': '카테고리가 업데이트되었습니다', + 'categories.toast.created': '카테고리가 생성되었습니다', + 'categories.toast.saveError': '저장 실패', + 'categories.toast.deleted': '카테고리가 삭제되었습니다', + 'categories.toast.deleteError': '삭제 실패', + + // Backup (Admin) + 'backup.title': '데이터 백업', + 'backup.subtitle': '데이터베이스 및 모든 업로드된 파일', + 'backup.refresh': '새로 고침', + 'backup.upload': '백업 업로드', + 'backup.uploading': '업로드 중…', + 'backup.create': '백업 만들기', + 'backup.creating': '생성 중…', + 'backup.empty': '아직 백업이 없습니다', + 'backup.createFirst': '첫 번째 백업 만들기', + 'backup.download': '다운로드', + 'backup.restore': '복원', + 'backup.confirm.restore': '백업 "{name}"을(를) 복원할까요?\n\n현재 모든 데이터가 백업으로 교체됩니다.', + 'backup.confirm.uploadRestore': '백업 파일 "{name}"을(를) 업로드하고 복원할까요?\n\n현재 모든 데이터가 덮어쓰여집니다.', + 'backup.confirm.delete': '백업 "{name}"을(를) 삭제할까요?', + 'backup.toast.loadError': '백업 불러오기 실패', + 'backup.toast.created': '백업이 성공적으로 생성되었습니다', + 'backup.toast.createError': '백업 생성 실패', + 'backup.toast.restored': '백업이 복원되었습니다. 페이지가 새로 고침됩니다…', + 'backup.toast.restoreError': '복원 실패', + 'backup.toast.uploadError': '업로드 실패', + 'backup.toast.deleted': '백업이 삭제되었습니다', + 'backup.toast.deleteError': '삭제 실패', + 'backup.toast.downloadError': '다운로드 실패', + 'backup.toast.settingsSaved': '자동 백업 설정이 저장되었습니다', + 'backup.toast.settingsError': '설정 저장 실패', + 'backup.auto.title': '자동 백업', + 'backup.auto.subtitle': '일정에 따른 자동 백업', + 'backup.auto.enable': '자동 백업 활성화', + 'backup.auto.enableHint': '선택한 일정에 따라 자동으로 백업이 생성됩니다', + 'backup.auto.interval': '간격', + 'backup.auto.hour': '실행 시간', + 'backup.auto.hourHint': '서버 현지 시간 ({format} 형식)', + 'backup.auto.dayOfWeek': '요일', + 'backup.auto.dayOfMonth': '매월 몇 일', + 'backup.auto.dayOfMonthHint': '모든 달과의 호환성을 위해 1-28로 제한', + 'backup.auto.scheduleSummary': '일정', + 'backup.auto.summaryDaily': '매일 {hour}:00', + 'backup.auto.summaryWeekly': '매주 {day} {hour}:00', + 'backup.auto.summaryMonthly': '매월 {day}일 {hour}:00', + 'backup.auto.envLocked': 'Docker', + 'backup.auto.envLockedHint': '자동 백업이 Docker 환경 변수로 설정되어 있습니다. 설정을 변경하려면 docker-compose.yml을 업데이트하고 컨테이너를 재시작하세요.', + 'backup.auto.copyEnv': 'Docker 환경 변수 복사', + 'backup.auto.envCopied': 'Docker 환경 변수가 클립보드에 복사되었습니다', + 'backup.auto.keepLabel': '이후 오래된 백업 삭제', + 'backup.dow.sunday': '일', + 'backup.dow.monday': '월', + 'backup.dow.tuesday': '화', + 'backup.dow.wednesday': '수', + 'backup.dow.thursday': '목', + 'backup.dow.friday': '금', + 'backup.dow.saturday': '토', + 'backup.interval.hourly': '매시간', + 'backup.interval.daily': '매일', + 'backup.interval.weekly': '매주', + 'backup.interval.monthly': '매월', + 'backup.keep.1day': '1일', + 'backup.keep.3days': '3일', + 'backup.keep.7days': '7일', + 'backup.keep.14days': '14일', + 'backup.keep.30days': '30일', + 'backup.keep.forever': '영구 보관', + + // Photos + 'photos.title': '사진', + 'photos.subtitle': '{trip}의 사진 {count}장', + 'photos.dropHere': '여기에 사진을 놓으세요...', + 'photos.dropHereActive': '여기에 사진을 놓으세요', + 'photos.captionForAll': '캡션 (전체)', + 'photos.captionPlaceholder': '선택적 캡션...', + 'photos.addCaption': '캡션 추가...', + 'photos.allDays': '모든 날', + 'photos.noPhotos': '아직 사진이 없습니다', + 'photos.uploadHint': '여행 사진을 업로드하세요', + 'photos.clickToSelect': '또는 클릭하여 선택', + 'photos.linkPlace': '장소 연결', + 'photos.noPlace': '장소 없음', + 'photos.uploadN': '{n}장 사진 업로드', + 'photos.linkDay': '날 연결', + 'photos.noDay': '날 없음', + 'photos.dayLabel': '{number}일차', + 'photos.photoSelected': '사진 선택됨', + 'photos.photosSelected': '사진 선택됨', + 'photos.fileTypeHint': 'JPG, PNG, WebP · 최대 10 MB · 최대 30장', + + // Backup restore modal + 'backup.restoreConfirmTitle': '백업을 복원할까요?', + 'backup.restoreWarning': '현재 모든 데이터 (여행, 장소, 사용자, 업로드)가 백업으로 영구 교체됩니다. 이 작업은 취소할 수 없습니다.', + 'backup.restoreTip': '팁: 복원 전에 현재 상태의 백업을 만드세요.', + 'backup.restoreConfirm': '예, 복원', + + // PDF + 'pdf.travelPlan': '여행 계획', + 'pdf.planned': '계획됨', + 'pdf.costLabel': '비용 (원)', + 'pdf.preview': 'PDF 미리보기', + 'pdf.saveAsPdf': 'PDF로 저장', + + // Planner + 'planner.places': '장소', + 'planner.bookings': '예약', + 'planner.packingList': '짐 목록', + 'planner.documents': '문서', + 'planner.dayPlan': '일별 계획', + 'planner.reservations': '예약', + 'planner.minTwoPlaces': '경로 계산에 좌표가 있는 장소가 최소 2개 필요합니다', + 'planner.noGeoPlaces': '좌표가 있는 장소가 없습니다', + 'planner.routeCalculated': '경로가 계산되었습니다', + 'planner.routeCalcFailed': '경로를 계산할 수 없습니다', + 'planner.routeError': '경로 계산 중 오류', + 'planner.icsExportFailed': 'ICS 내보내기 실패', + 'planner.routeOptimized': '경로가 최적화되었습니다', + 'planner.reservationUpdated': '예약이 업데이트되었습니다', + 'planner.reservationAdded': '예약이 추가되었습니다', + 'planner.confirmDeleteReservation': '예약을 삭제할까요?', + 'planner.reservationDeleted': '예약이 삭제되었습니다', + 'planner.days': '일', + 'planner.allPlaces': '모든 장소', + 'planner.totalPlaces': '총 {n}개 장소', + 'planner.noDaysPlanned': '아직 계획된 날이 없습니다', + 'planner.editTrip': '여행 편집 →', + 'planner.placeOne': '장소 1개', + 'planner.placeN': '장소 {n}개', + 'planner.addNote': '메모 추가', + 'planner.noEntries': '이 날에 항목이 없습니다', + 'planner.addPlace': '장소/활동 추가', + 'planner.addPlaceShort': '+ 장소/활동 추가', + 'planner.resPending': '예약 대기 중 · ', + 'planner.resConfirmed': '예약 확정 · ', + 'planner.notePlaceholder': '메모…', + 'planner.noteTimePlaceholder': '시간 (선택)', + 'planner.noteExamplePlaceholder': '예: 14:30 중앙역에서 S3, 7번 부두에서 페리, 점심 휴식…', + 'planner.totalCost': '총 비용', + 'planner.searchPlaces': '장소 검색…', + 'planner.allCategories': '모든 카테고리', + 'planner.noPlacesFound': '장소를 찾을 수 없습니다', + 'planner.addFirstPlace': '첫 번째 장소 추가', + 'planner.noReservations': '예약 없음', + 'planner.addFirstReservation': '첫 번째 예약 추가', + 'planner.new': '새로 만들기', + 'planner.addToDay': '+ 날에 추가', + 'planner.calculating': '계산 중…', + 'planner.route': '경로', + 'planner.optimize': '최적화', + 'planner.openGoogleMaps': 'Google Maps에서 열기', + 'planner.selectDayHint': '왼쪽 목록에서 날을 선택하여 일별 계획을 보세요', + 'planner.noPlacesForDay': '이 날에 아직 장소가 없습니다', + 'planner.addPlacesLink': '장소 추가 →', + 'planner.minTotal': '분 합계', + 'planner.noReservation': '예약 없음', + 'planner.removeFromDay': '날에서 제거', + 'planner.addToThisDay': '날에 추가', + 'planner.overview': '개요', + 'planner.noDays': '아직 날이 없습니다', + 'planner.editTripToAddDays': '여행을 편집하여 날을 추가하세요', + 'planner.dayCount': '{n}일', + 'planner.clickToUnlock': '클릭하여 잠금 해제', + 'planner.keepPosition': '경로 최적화 중 위치 유지', + 'planner.dayDetails': '일별 상세', + 'planner.dayN': '{n}일차', + + // Dashboard Stats + 'stats.countries': '국가', + 'stats.cities': '도시', + 'stats.trips': '여행', + 'stats.places': '장소', + 'stats.worldProgress': '세계 진행도', + 'stats.visited': '방문함', + 'stats.remaining': '남음', + 'stats.visitedCountries': '방문한 나라', + + // Day Detail Panel + 'day.precipProb': '강수 확률', + 'day.precipitation': '강수량', + 'day.wind': '바람', + 'day.sunrise': '일출', + 'day.sunset': '일몰', + 'day.hourlyForecast': '시간별 예보', + 'day.climateHint': '역사적 평균값 — 이 날짜로부터 16일 이내의 실제 예보를 사용할 수 있습니다.', + 'day.noWeather': '날씨 데이터가 없습니다. 좌표가 있는 장소를 추가하세요.', + 'day.overview': '일별 개요', + 'day.accommodation': '숙박', + 'day.addAccommodation': '숙박 추가', + 'day.hotelDayRange': '적용할 날', + 'day.noPlacesForHotel': '먼저 여행에 장소를 추가하세요', + 'day.allDays': '전체', + 'day.checkIn': '체크인', + 'day.checkInUntil': '까지', + 'day.checkOut': '체크아웃', + 'day.confirmation': '확인', + 'day.editAccommodation': '숙박 편집', + 'day.reservations': '예약', + + // Photos / Immich + 'memories.title': '사진', + 'memories.notConnected': '{provider_name}이(가) 연결되지 않았습니다', + 'memories.notConnectedHint': '이 여행에 사진을 추가하려면 설정에서 {provider_name} 인스턴스를 연결하세요.', + 'memories.notConnectedMultipleHint': '이 여행에 사진을 추가하려면 설정에서 다음 사진 공급자 중 하나를 연결하세요: {provider_names}', + 'memories.noDates': '사진을 불러오려면 여행에 날짜를 추가하세요.', + 'memories.noPhotos': '사진을 찾을 수 없습니다', + 'memories.noPhotosHint': '{provider_name}에서 이 여행의 날짜 범위에 해당하는 사진을 찾을 수 없습니다.', + 'memories.photosFound': '장', + 'memories.fromOthers': '다른 사람으로부터', + 'memories.sharePhotos': '사진 공유', + 'memories.sharing': '공유', + 'memories.reviewTitle': '사진 검토', + 'memories.reviewHint': '사진을 클릭하여 공유에서 제외하세요.', + 'memories.shareCount': '사진 {count}장 공유', + 'memories.providerUrl': '서버 URL', + 'memories.providerApiKey': 'API 키', + 'memories.providerUsername': '사용자 이름', + 'memories.providerPassword': '비밀번호', + 'memories.providerOTP': 'MFA 코드 (활성화된 경우)', + 'memories.skipSSLVerification': 'SSL 인증서 확인 건너뛰기', + 'memories.immichAutoUpload': '업로드 시 Journey 사진을 Immich에 미러링', + 'memories.providerUrlHintSynology': 'URL에 Photos 앱 경로를 포함하세요. 예: https://nas:5001/photo', + 'memories.testConnection': '연결 테스트', + 'memories.testShort': '테스트', + 'memories.testFirst': '먼저 연결을 테스트하세요', + 'memories.connected': '연결됨', + 'memories.disconnected': '연결되지 않음', + 'memories.connectionSuccess': '{provider_name}에 연결되었습니다', + 'memories.connectionError': '{provider_name}에 연결할 수 없습니다', + 'memories.saved': '{provider_name} 설정이 저장되었습니다', + 'memories.providerDisconnectedBanner': '{provider_name} 연결이 끊어졌습니다. 사진을 보려면 설정에서 다시 연결하세요.', + 'memories.saveError': '{provider_name} 설정을 저장할 수 없습니다', + 'memories.addPhotos': '사진 추가', + 'memories.linkAlbum': '앨범 연결', + 'memories.selectAlbum': '{provider_name} 앨범 선택', + 'memories.selectAlbumMultiple': '앨범 선택', + 'memories.noAlbums': '앨범을 찾을 수 없습니다', + 'memories.syncAlbum': '앨범 동기화', + 'memories.unlinkAlbum': '앨범 연결 해제', + 'memories.photos': '장', + 'memories.selectPhotos': '{provider_name}에서 사진 선택', + 'memories.selectPhotosMultiple': '사진 선택', + 'memories.selectHint': '사진을 탭하여 선택하세요.', + 'memories.selected': '선택됨', + 'memories.addSelected': '{count}장 추가', + 'memories.alreadyAdded': '추가됨', + 'memories.private': '비공개', + 'memories.stopSharing': '공유 중지', + 'memories.oldest': '오래된 것 먼저', + 'memories.newest': '최신 것 먼저', + 'memories.allLocations': '모든 위치', + 'memories.tripDates': '여행 날짜', + 'memories.allPhotos': '모든 사진', + 'memories.confirmShareTitle': '여행 멤버와 공유할까요?', + 'memories.confirmShareHint': '{count}장의 사진이 이 여행의 모든 멤버에게 표시됩니다. 나중에 개별 사진을 비공개로 만들 수 있습니다.', + 'memories.confirmShareButton': '사진 공유', + 'memories.error.loadAlbums': '앨범 불러오기 실패', + 'memories.error.linkAlbum': '앨범 연결 실패', + 'memories.error.unlinkAlbum': '앨범 연결 해제 실패', + 'memories.error.syncAlbum': '앨범 동기화 실패', + 'memories.error.loadPhotos': '사진 불러오기 실패', + 'memories.error.addPhotos': '사진 추가 실패', + 'memories.error.removePhoto': '사진 제거 실패', + 'memories.error.toggleSharing': '공유 업데이트 실패', + 'memories.saveRouteNotConfigured': '이 공급자에 대해 저장 경로가 설정되지 않았습니다', + 'memories.testRouteNotConfigured': '이 공급자에 대해 테스트 경로가 설정되지 않았습니다', + 'memories.fillRequiredFields': '모든 필수 항목을 입력하세요', + + // Collab Addon + 'collab.tabs.chat': '채팅', + 'collab.tabs.notes': '메모', + 'collab.tabs.polls': '투표', + 'collab.whatsNext.title': '다음 할 일', + 'collab.whatsNext.today': '오늘', + 'collab.whatsNext.tomorrow': '내일', + 'collab.whatsNext.empty': '예정된 활동이 없습니다', + 'collab.whatsNext.until': '까지', + 'collab.whatsNext.emptyHint': '시간이 있는 활동이 여기에 표시됩니다', + 'collab.chat.send': '전송', + 'collab.chat.placeholder': '메시지 입력...', + 'collab.chat.empty': '대화를 시작하세요', + 'collab.chat.emptyHint': '메시지는 모든 여행 멤버와 공유됩니다', + 'collab.chat.emptyDesc': '여행 그룹과 아이디어, 계획, 업데이트를 공유하세요', + 'collab.chat.today': '오늘', + 'collab.chat.yesterday': '어제', + 'collab.chat.deletedMessage': '메시지를 삭제했습니다', + 'collab.chat.reply': '답장', + 'collab.chat.loadMore': '이전 메시지 불러오기', + 'collab.chat.justNow': '방금 전', + 'collab.chat.minutesAgo': '{n}분 전', + 'collab.chat.hoursAgo': '{n}시간 전', + 'collab.notes.title': '메모', + 'collab.notes.new': '새 메모', + 'collab.notes.empty': '아직 메모가 없습니다', + 'collab.notes.emptyHint': '아이디어와 계획을 기록하세요', + 'collab.notes.all': '전체', + 'collab.notes.titlePlaceholder': '메모 제목', + 'collab.notes.contentPlaceholder': '내용을 입력하세요...', + 'collab.notes.categoryPlaceholder': '카테고리', + 'collab.notes.newCategory': '새 카테고리...', + 'collab.notes.category': '카테고리', + 'collab.notes.noCategory': '카테고리 없음', + 'collab.notes.color': '색상', + 'collab.notes.save': '저장', + 'collab.notes.cancel': '취소', + 'collab.notes.edit': '편집', + 'collab.notes.delete': '삭제', + 'collab.notes.pin': '고정', + 'collab.notes.unpin': '고정 해제', + 'collab.notes.daysAgo': '{n}일 전', + 'collab.notes.categorySettings': '카테고리 관리', + 'collab.notes.create': '생성', + 'collab.notes.website': '웹사이트', + 'collab.notes.websitePlaceholder': 'https://...', + 'collab.notes.attachFiles': '파일 첨부', + 'collab.notes.noCategoriesYet': '아직 카테고리가 없습니다', + 'collab.notes.emptyDesc': '메모를 만들어 시작하세요', + 'collab.polls.title': '투표', + 'collab.polls.new': '새 투표', + 'collab.polls.empty': '아직 투표가 없습니다', + 'collab.polls.emptyHint': '그룹에 질문하고 함께 투표하세요', + 'collab.polls.question': '질문', + 'collab.polls.questionPlaceholder': '무엇을 할까요?', + 'collab.polls.addOption': '+ 옵션 추가', + 'collab.polls.optionPlaceholder': '옵션 {n}', + 'collab.polls.create': '투표 만들기', + 'collab.polls.close': '닫기', + 'collab.polls.closed': '종료됨', + 'collab.polls.votes': '{n}표', + 'collab.polls.vote': '{n}표', + 'collab.polls.multipleChoice': '복수 선택', + 'collab.polls.multiChoice': '복수 선택', + 'collab.polls.deadline': '마감일', + 'collab.polls.option': '옵션', + 'collab.polls.options': '옵션', + 'collab.polls.delete': '삭제', + 'collab.polls.closedSection': '종료됨', + + // Permissions + 'admin.tabs.permissions': '권한', + 'perm.title': '권한 설정', + 'perm.subtitle': '앱 전체에서 누가 작업을 수행할 수 있는지 제어합니다', + 'perm.saved': '권한 설정이 저장되었습니다', + 'perm.resetDefaults': '기본값으로 초기화', + 'perm.customized': '맞춤 설정됨', + 'perm.level.admin': '관리자만', + 'perm.level.tripOwner': '여행 소유자', + 'perm.level.tripMember': '여행 멤버', + 'perm.level.everybody': '모든 사람', + 'perm.cat.trip': '여행 관리', + 'perm.cat.members': '멤버 관리', + 'perm.cat.files': '파일', + 'perm.cat.content': '콘텐츠 및 일정', + 'perm.cat.extras': '예산, 짐 목록 및 협업', + 'perm.action.trip_create': '여행 만들기', + 'perm.action.trip_edit': '여행 상세 편집', + 'perm.action.trip_delete': '여행 삭제', + 'perm.action.trip_archive': '여행 보관/복원', + 'perm.action.trip_cover_upload': '커버 이미지 업로드', + 'perm.action.member_manage': '멤버 추가/제거', + 'perm.action.file_upload': '파일 업로드', + 'perm.action.file_edit': '파일 메타데이터 편집', + 'perm.action.file_delete': '파일 삭제', + 'perm.action.place_edit': '장소 추가/편집/삭제', + 'perm.action.day_edit': '날, 메모 및 배정 편집', + 'perm.action.reservation_edit': '예약 관리', + 'perm.action.budget_edit': '예산 관리', + 'perm.action.packing_edit': '짐 목록 관리', + 'perm.action.collab_edit': '협업 (메모, 투표, 채팅)', + 'perm.action.share_manage': '공유 링크 관리', + 'perm.actionHint.trip_create': '누가 새 여행을 만들 수 있는지', + 'perm.actionHint.trip_edit': '누가 여행 이름, 날짜, 설명, 통화를 변경할 수 있는지', + 'perm.actionHint.trip_delete': '누가 여행을 영구 삭제할 수 있는지', + 'perm.actionHint.trip_archive': '누가 여행을 보관하거나 복원할 수 있는지', + 'perm.actionHint.trip_cover_upload': '누가 커버 이미지를 업로드하거나 변경할 수 있는지', + 'perm.actionHint.member_manage': '누가 여행 멤버를 초대하거나 제거할 수 있는지', + 'perm.actionHint.file_upload': '누가 여행에 파일을 업로드할 수 있는지', + 'perm.actionHint.file_edit': '누가 파일 설명 및 링크를 편집할 수 있는지', + 'perm.actionHint.file_delete': '누가 파일을 휴지통으로 이동하거나 영구 삭제할 수 있는지', + 'perm.actionHint.place_edit': '누가 장소를 추가, 편집, 삭제할 수 있는지', + 'perm.actionHint.day_edit': '누가 날, 일별 메모, 장소 배정을 편집할 수 있는지', + 'perm.actionHint.reservation_edit': '누가 예약을 만들고, 편집하고, 삭제할 수 있는지', + 'perm.actionHint.budget_edit': '누가 예산 항목을 만들고, 편집하고, 삭제할 수 있는지', + 'perm.actionHint.packing_edit': '누가 짐 항목과 가방을 관리할 수 있는지', + 'perm.actionHint.collab_edit': '누가 메모, 투표를 만들고 메시지를 보낼 수 있는지', + 'perm.actionHint.share_manage': '누가 공개 공유 링크를 만들거나 삭제할 수 있는지', + + // Undo + 'undo.button': '실행 취소', + 'undo.tooltip': '실행 취소: {action}', + 'undo.assignPlace': '장소가 날에 배정되었습니다', + 'undo.removeAssignment': '장소가 날에서 제거되었습니다', + 'undo.reorder': '장소 순서가 변경되었습니다', + 'undo.optimize': '경로가 최적화되었습니다', + 'undo.deletePlace': '장소가 삭제되었습니다', + 'undo.deletePlaces': '장소들이 삭제되었습니다', + 'undo.moveDay': '장소가 다른 날로 이동되었습니다', + 'undo.lock': '장소 잠금이 변경되었습니다', + 'undo.importGpx': 'GPX 가져오기', + 'undo.importKeyholeMarkup': 'KMZ/KML 가져오기', + 'undo.importGoogleList': 'Google Maps 가져오기', + 'undo.importNaverList': '네이버 지도 가져오기', + 'undo.addPlace': '장소가 추가되었습니다', + 'undo.done': '실행 취소됨: {action}', + + // Notifications + 'notifications.title': '알림', + 'notifications.markAllRead': '모두 읽음으로 표시', + 'notifications.deleteAll': '모두 삭제', + 'notifications.showAll': '모든 알림 보기', + 'notifications.empty': '알림 없음', + 'notifications.emptyDescription': '모두 확인했습니다!', + 'notifications.all': '전체', + 'notifications.unreadOnly': '읽지 않음', + 'notifications.markRead': '읽음으로 표시', + 'notifications.markUnread': '읽지 않음으로 표시', + 'notifications.delete': '삭제', + 'notifications.system': '시스템', + 'notifications.synologySessionCleared.title': 'Synology Photos 연결 해제됨', + 'notifications.synologySessionCleared.text': '서버 또는 계정이 변경되었습니다 — 설정에서 연결을 다시 테스트하세요.', + + // Notification test keys (dev only) + 'notifications.versionAvailable.title': '업데이트 사용 가능', + 'notifications.versionAvailable.text': 'TREK {version}이(가) 사용 가능합니다.', + 'notifications.versionAvailable.button': '상세 보기', + 'notifications.test.title': '{actor}의 테스트 알림', + 'notifications.test.text': '간단한 테스트 알림입니다.', + 'notifications.test.booleanTitle': '{actor}이(가) 승인을 요청합니다', + 'notifications.test.booleanText': '테스트 boolean 알림입니다. 아래에서 작업을 선택하세요.', + 'notifications.test.accept': '승인', + 'notifications.test.decline': '거절', + 'notifications.test.navigateTitle': '확인할 항목이 있습니다', + 'notifications.test.navigateText': '테스트 navigate 알림입니다.', + 'notifications.test.goThere': '이동', + 'notifications.test.adminTitle': '관리자 방송', + 'notifications.test.adminText': '{actor}이(가) 모든 관리자에게 테스트 알림을 보냈습니다.', + 'notifications.test.tripTitle': '{actor}이(가) 여행에 게시했습니다', + 'notifications.test.tripText': '여행 "{trip}"의 테스트 알림입니다.', + + // Todo + 'todo.subtab.packing': '짐 목록', + 'todo.subtab.todo': '할 일', + 'todo.completed': '완료됨', + 'todo.filter.all': '전체', + 'todo.filter.open': '미완료', + 'todo.filter.done': '완료', + 'todo.uncategorized': '미분류', + 'todo.namePlaceholder': '작업 이름', + 'todo.descriptionPlaceholder': '설명 (선택)', + 'todo.unassigned': '미배정', + 'todo.noCategory': '카테고리 없음', + 'todo.hasDescription': '설명 있음', + 'todo.addItem': '새 작업 추가', + 'todo.sidebar.sortBy': '정렬 기준', + 'todo.priority': '우선순위', + 'todo.newCategoryLabel': '새로 만들기', + 'budget.categoriesLabel': '카테고리', + 'todo.newCategory': '카테고리 이름', + 'todo.addCategory': '카테고리 추가', + 'todo.newItem': '새 작업', + 'todo.empty': '아직 작업이 없습니다. 작업을 추가하여 시작하세요!', + 'todo.filter.my': '내 작업', + 'todo.filter.overdue': '기한 초과', + 'todo.sidebar.tasks': '작업', + 'todo.sidebar.categories': '카테고리', + 'todo.detail.title': '작업', + 'todo.detail.description': '설명', + 'todo.detail.category': '카테고리', + 'todo.detail.dueDate': '마감일', + 'todo.detail.assignedTo': '배정 대상', + 'todo.detail.delete': '삭제', + 'todo.detail.save': '변경 사항 저장', + 'todo.sortByPrio': '우선순위', + 'todo.detail.priority': '우선순위', + 'todo.detail.noPriority': '없음', + 'todo.detail.create': '작업 만들기', + + // Notifications — dev test events + 'notif.test.title': '[테스트] 알림', + 'notif.test.simple.text': '간단한 테스트 알림입니다.', + 'notif.test.boolean.text': '이 테스트 알림을 수락하시겠습니까?', + 'notif.test.navigate.text': '아래를 클릭하여 대시보드로 이동하세요.', + + // Notifications + 'notif.trip_invite.title': '여행 초대', + 'notif.trip_invite.text': '{actor}이(가) {trip}에 초대했습니다', + 'notif.booking_change.title': '예약 업데이트됨', + 'notif.booking_change.text': '{actor}이(가) {trip}의 예약을 업데이트했습니다', + 'notif.trip_reminder.title': '여행 리마인더', + 'notif.trip_reminder.text': '여행 {trip}이(가) 곧 시작됩니다!', + 'notif.todo_due.title': '할 일 마감', + 'notif.todo_due.text': '{trip}의 {todo}이(가) {due}에 마감됩니다', + 'notif.vacay_invite.title': 'Vacay 퓨전 초대', + 'notif.vacay_invite.text': '{actor}이(가) 휴가 계획 공유에 초대했습니다', + 'notif.photos_shared.title': '사진 공유됨', + 'notif.photos_shared.text': '{actor}이(가) {trip}에서 {count}장의 사진을 공유했습니다', + 'notif.collab_message.title': '새 메시지', + 'notif.collab_message.text': '{actor}이(가) {trip}에서 메시지를 보냈습니다', + 'notif.packing_tagged.title': '짐 목록 배정', + 'notif.packing_tagged.text': '{actor}이(가) {trip}의 {category}에 배정했습니다', + 'notif.version_available.title': '새 버전 사용 가능', + 'notif.version_available.text': 'TREK {version}이(가) 사용 가능합니다', + 'notif.action.view_trip': '여행 보기', + 'notif.action.view_collab': '메시지 보기', + 'notif.action.view_packing': '짐 목록 보기', + 'notif.action.view_photos': '사진 보기', + 'notif.action.view_vacay': 'Vacay 보기', + 'notif.action.view_admin': '관리자로 이동', + 'notif.action.view': '보기', + 'notif.action.accept': '수락', + 'notif.action.decline': '거절', + 'notif.generic.title': '알림', + 'notif.generic.text': '새 알림이 있습니다', + 'notif.dev.unknown_event.title': '[DEV] 알 수 없는 이벤트', + 'notif.dev.unknown_event.text': '이벤트 유형 "{event}"이(가) EVENT_NOTIFICATION_CONFIG에 등록되지 않았습니다', + + // Journey addon + 'journey.search.placeholder': 'Journey 검색…', + 'journey.search.noResults': '"{query}"와(과) 일치하는 Journey가 없습니다', + 'journey.title': 'Journey', + 'journey.subtitle': '여행을 실시간으로 기록하세요', + 'journey.new': '새 Journey', + 'journey.create': '만들기', + 'journey.titlePlaceholder': '어디로 가시나요?', + 'journey.empty': '아직 Journey가 없습니다', + 'journey.emptyHint': '다음 여행을 기록하기 시작하세요', + 'journey.deleted': 'Journey가 삭제되었습니다', + 'journey.createError': 'Journey를 만들 수 없습니다', + 'journey.deleteError': 'Journey를 삭제할 수 없습니다', + 'journey.deleteConfirmTitle': '삭제', + 'journey.deleteConfirmMessage': '"{title}"을(를) 삭제할까요? 이 작업은 취소할 수 없습니다.', + 'journey.deleteConfirmGeneric': '정말로 삭제할까요?', + 'journey.notFound': 'Journey를 찾을 수 없습니다', + 'journey.photos': '사진', + 'journey.timelineEmpty': '아직 정류장이 없습니다', + 'journey.timelineEmptyHint': '체크인을 추가하거나 일기를 작성하여 시작하세요', + 'journey.status.draft': '초안', + 'journey.status.active': '활성', + 'journey.status.completed': '완료됨', + 'journey.status.upcoming': '예정됨', + 'journey.status.archived': '보관됨', + 'journey.checkin.add': '체크인', + 'journey.checkin.namePlaceholder': '위치 이름', + 'journey.checkin.notesPlaceholder': '메모 (선택)', + 'journey.checkin.save': '저장', + 'journey.checkin.error': '체크인을 저장할 수 없습니다', + 'journey.entry.add': '일기', + 'journey.entry.edit': '항목 편집', + 'journey.entry.titlePlaceholder': '제목 (선택)', + 'journey.entry.bodyPlaceholder': '오늘 무슨 일이 있었나요?', + 'journey.entry.save': '저장', + 'journey.entry.error': '항목을 저장할 수 없습니다', + 'journey.photo.add': '사진', + 'journey.photo.uploadError': '업로드 실패', + 'journey.share.share': '공유', + 'journey.share.public': '공개', + 'journey.share.linkCopied': '공개 링크가 복사되었습니다', + 'journey.share.disabled': '공개 공유 비활성화됨', + 'journey.editor.titlePlaceholder': '이 순간에 이름을 붙여주세요...', + 'journey.editor.bodyPlaceholder': '오늘의 이야기를 들려주세요...', + 'journey.editor.placePlaceholder': '위치 (선택)', + 'journey.editor.tagsPlaceholder': '태그: 숨겨진 명소, 최고의 식사, 다시 방문...', + 'journey.visibility.private': '비공개', + 'journey.visibility.shared': '공유됨', + 'journey.visibility.public': '공개', + 'journey.emptyState.title': '여기서 이야기가 시작됩니다', + 'journey.emptyState.subtitle': '장소에 체크인하거나 첫 번째 일기 항목을 작성하세요', + + // Journey Frontpage + 'journey.frontpage.subtitle': '여행을 영원히 잊지 못할 이야기로 만드세요', + 'journey.frontpage.createJourney': 'Journey 만들기', + 'journey.frontpage.activeJourney': '활성 Journey', + 'journey.frontpage.allJourneys': '모든 Journey', + 'journey.frontpage.journeys': '개 Journey', + 'journey.frontpage.createNew': '새 Journey 만들기', + 'journey.frontpage.createNewSub': '여행을 선택하고, 이야기를 쓰고, 모험을 공유하세요', + 'journey.frontpage.live': '라이브', + 'journey.frontpage.synced': '동기화됨', + 'journey.frontpage.continueWriting': '계속 쓰기', + 'journey.frontpage.updated': '{time}에 업데이트됨', + 'journey.frontpage.suggestionLabel': '여행이 방금 종료됨', + 'journey.frontpage.suggestionText': '{title}을(를) Journey로 만들어보세요', + 'journey.frontpage.dismiss': '닫기', + 'journey.frontpage.journeyName': 'Journey 이름', + 'journey.frontpage.namePlaceholder': '예: 동남아시아 2026', + 'journey.frontpage.selectTrips': '여행 선택', + 'journey.frontpage.tripsSelected': '개 여행 선택됨', + 'journey.frontpage.trips': '개 여행', + 'journey.frontpage.placesImported': '개 장소가 가져와집니다', + 'journey.frontpage.places': '개 장소', + + // Journey Detail + 'journey.detail.backToJourney': 'Journey로 돌아가기', + 'journey.detail.syncedWithTrips': '여행과 동기화됨', + 'journey.detail.addEntry': '항목 추가', + 'journey.detail.newEntry': '새 항목', + 'journey.detail.editEntry': '항목 편집', + 'journey.detail.noEntries': '아직 항목이 없습니다', + 'journey.detail.noEntriesHint': '여행을 추가하여 스켈레톤 항목으로 시작하세요', + 'journey.detail.noPhotos': '아직 사진이 없습니다', + 'journey.detail.noPhotosHint': '항목에 사진을 업로드하거나 Immich/Synology 라이브러리를 탐색하세요', + 'journey.detail.journeyTab': 'Journey', + 'journey.detail.journeyStats': 'Journey 통계', + 'journey.detail.syncedTrips': '동기화된 여행', + 'journey.detail.noTripsLinked': '아직 연결된 여행이 없습니다', + 'journey.detail.contributors': '기여자', + 'journey.detail.readMore': '더 읽기', + 'journey.detail.prosCons': '장단점', + 'journey.detail.photos': '장', + 'journey.detail.day': '{number}일차', + 'journey.detail.places': '개 장소', + + // Journey Detail — Stats + 'journey.stats.days': '일', + 'journey.stats.cities': '도시', + 'journey.stats.entries': '항목', + 'journey.stats.photos': '사진', + 'journey.stats.places': '장소', + 'journey.skeletons.show': '제안 보기', + 'journey.skeletons.hide': '제안 숨기기', + + // Journey Detail — Verdict + 'journey.verdict.lovedIt': '정말 좋았어요', + 'journey.verdict.couldBeBetter': '더 좋을 수 있었어요', + + // Journey Detail — Synced badge + 'journey.synced.places': '개 장소', + 'journey.synced.synced': '동기화됨', + + // Journey Entry Editor + 'journey.editor.discardChangesConfirm': '저장되지 않은 변경 사항이 있습니다. 취소할까요?', + 'journey.editor.uploadPhotos': '사진 업로드', + 'journey.editor.uploading': '업로드 중...', + 'journey.editor.fromGallery': '갤러리에서', + 'journey.editor.allPhotosAdded': '모든 사진이 이미 추가되었습니다', + 'journey.editor.writeStory': '이야기를 써주세요...', + 'journey.editor.prosCons': '장단점', + 'journey.editor.pros': '장점', + 'journey.editor.cons': '단점', + 'journey.editor.proPlaceholder': '좋은 점...', + 'journey.editor.conPlaceholder': '아쉬운 점...', + 'journey.editor.addAnother': '하나 더 추가', + 'journey.editor.date': '날짜', + 'journey.editor.location': '위치', + 'journey.editor.searchLocation': '위치 검색...', + 'journey.editor.mood': '기분', + 'journey.editor.weather': '날씨', + 'journey.editor.photoFirst': '1번째', + 'journey.editor.makeFirst': '1번째로 설정', + 'journey.editor.searching': '검색 중...', + + // Journey Entry — Moods + 'journey.mood.amazing': '최고!', + 'journey.mood.good': '좋음', + 'journey.mood.neutral': '보통', + 'journey.mood.rough': '힘들었음', + + // Journey Entry — Weather + 'journey.weather.sunny': '맑음', + 'journey.weather.partly': '구름 조금', + 'journey.weather.cloudy': '흐림', + 'journey.weather.rainy': '비', + 'journey.weather.stormy': '폭풍', + 'journey.weather.cold': '눈', + + // Journey — Trip Linking + 'journey.trips.linkTrip': '여행 연결', + 'journey.trips.searchTrip': '여행 검색', + 'journey.trips.searchPlaceholder': '여행 이름 또는 목적지...', + 'journey.trips.noTripsAvailable': '사용 가능한 여행이 없습니다', + 'journey.trips.link': '연결', + 'journey.trips.tripLinked': '여행이 연결되었습니다', + 'journey.trips.linkFailed': '여행 연결 실패', + 'journey.trips.addTrip': '여행 추가', + 'journey.trips.unlinkTrip': '여행 연결 해제', + 'journey.trips.unlinkMessage': '"{title}"을(를) 연결 해제할까요? 이 여행의 동기화된 모든 항목과 사진이 영구 삭제됩니다. 이 작업은 취소할 수 없습니다.', + 'journey.trips.unlink': '연결 해제', + 'journey.trips.tripUnlinked': '여행 연결이 해제되었습니다', + 'journey.trips.unlinkFailed': '여행 연결 해제 실패', + 'journey.trips.noTripsLinkedSettings': '연결된 여행이 없습니다', + + // Journey — Contributors + 'journey.contributors.invite': '기여자 초대', + 'journey.contributors.searchUser': '사용자 검색', + 'journey.contributors.searchPlaceholder': '사용자 이름 또는 이메일...', + 'journey.contributors.noUsers': '사용자를 찾을 수 없습니다', + 'journey.contributors.role': '역할', + 'journey.contributors.added': '기여자가 추가되었습니다', + 'journey.contributors.addFailed': '기여자 추가 실패', + 'journey.contributors.remove': '기여자 제거', + 'journey.contributors.removeConfirm': '{username}을(를) 이 Journey에서 제거할까요?', + 'journey.contributors.removed': '기여자가 제거되었습니다', + 'journey.contributors.removeFailed': '기여자 제거 실패', + + // Journey — Share + 'journey.share.publicShare': '공개 공유', + 'journey.share.createLink': '공유 링크 만들기', + 'journey.share.linkCreated': '공유 링크가 생성되었습니다', + 'journey.share.createFailed': '링크 생성 실패', + 'journey.share.copy': '복사', + 'journey.share.copied': '복사됨!', + 'journey.share.timeline': '타임라인', + 'journey.share.gallery': '갤러리', + 'journey.share.map': '지도', + 'journey.share.removeLink': '공유 링크 제거', + 'journey.share.linkDeleted': '공유 링크가 삭제되었습니다', + 'journey.share.deleteFailed': '삭제 실패', + 'journey.share.updateFailed': '업데이트 실패', + + // Journey — Invite + 'journey.invite.role': '역할', + 'journey.invite.viewer': '뷰어', + 'journey.invite.editor': '편집자', + 'journey.invite.invite': '초대', + 'journey.invite.inviting': '초대 중...', + + // Journey — Settings Dialog + 'journey.settings.title': 'Journey 설정', + 'journey.settings.coverImage': '커버 이미지', + 'journey.settings.changeCover': '커버 변경', + 'journey.settings.addCover': '커버 이미지 추가', + 'journey.settings.name': '이름', + 'journey.settings.subtitle': '부제목', + 'journey.settings.subtitlePlaceholder': '예: 태국, 베트남 & 캄보디아', + 'journey.settings.endJourney': 'Journey 보관', + 'journey.settings.reopenJourney': 'Journey 복원', + 'journey.settings.archived': 'Journey가 보관되었습니다', + 'journey.settings.reopened': 'Journey가 복원되었습니다', + 'journey.settings.endDescription': '라이브 배지를 숨깁니다. 언제든지 다시 열 수 있습니다.', + 'journey.settings.delete': '삭제', + 'journey.settings.deleteJourney': 'Journey 삭제', + 'journey.settings.deleteMessage': '"{title}"을(를) 삭제할까요? 모든 항목과 사진이 삭제됩니다.', + 'journey.settings.saved': '설정이 저장되었습니다', + 'journey.settings.saveFailed': '저장 실패', + 'journey.settings.coverUpdated': '커버가 업데이트되었습니다', + 'journey.settings.coverFailed': '업로드 실패', + 'journey.settings.failedToDelete': '삭제 실패', + 'journey.entries.deleteTitle': '항목 삭제', + 'journey.photosUploaded': '{count}장 사진이 업로드되었습니다', + 'journey.photosAdded': '{count}장 사진이 추가되었습니다', + + // Journey — Public Page + 'journey.public.notFound': '찾을 수 없습니다', + 'journey.public.notFoundMessage': '이 Journey가 존재하지 않거나 링크가 만료되었습니다.', + 'journey.public.readOnly': '읽기 전용 · 공개 Journey', + 'journey.public.tagline': '여행 기록 및 탐험 키트', + 'journey.public.sharedVia': '공유 경로', + 'journey.public.madeWith': '으로 만들어짐', + + // Journey — PDF Export + 'journey.pdf.journeyBook': 'Journey 책', + 'journey.pdf.madeWith': 'TREK으로 만들어짐', + 'journey.pdf.day': '일차', + 'journey.pdf.theEnd': '끝', + 'journey.pdf.saveAsPdf': 'PDF로 저장', + 'journey.pdf.pages': '페이지', + 'journey.picker.tripPeriod': '여행 기간', + 'journey.picker.dateRange': '날짜 범위', + 'journey.picker.allPhotos': '모든 사진', + 'journey.picker.albums': '앨범', + 'journey.picker.selected': '선택됨', + 'journey.picker.addTo': '추가', + 'journey.picker.newGallery': '새 갤러리', + 'journey.picker.selectAll': '전체 선택', + 'journey.picker.deselectAll': '전체 해제', + 'journey.picker.noAlbums': '앨범을 찾을 수 없습니다', + 'journey.picker.selectDate': '날짜 선택', + 'journey.picker.search': '검색', + + // Dashboard Mobile + 'dashboard.greeting.morning': '좋은 아침이에요,', + 'dashboard.greeting.afternoon': '안녕하세요,', + 'dashboard.greeting.evening': '좋은 저녁이에요,', + 'dashboard.mobile.liveNow': '지금 라이브', + 'dashboard.mobile.tripProgress': '여행 진행도', + 'dashboard.mobile.daysLeft': '{count}일 남음', + 'dashboard.mobile.places': '장소', + 'dashboard.mobile.buddies': '동행자', + 'dashboard.mobile.newTrip': '새 여행', + 'dashboard.mobile.currency': '통화', + 'dashboard.mobile.timezone': '시간대', + 'dashboard.mobile.upcomingTrips': '예정된 여행', + 'dashboard.mobile.yourTrips': '내 여행', + 'dashboard.mobile.trips': '개 여행', + 'dashboard.mobile.starts': '시작', + 'dashboard.mobile.duration': '기간', + 'dashboard.mobile.day': '일', + 'dashboard.mobile.days': '일', + 'dashboard.mobile.ongoing': '진행 중', + 'dashboard.mobile.startsToday': '오늘 시작', + 'dashboard.mobile.tomorrow': '내일', + 'dashboard.mobile.inDays': '{count}일 후', + 'dashboard.mobile.inMonths': '{count}개월 후', + 'dashboard.mobile.completed': '완료됨', + 'dashboard.mobile.currencyConverter': '환율 계산기', + + // BottomNav & Profile + 'nav.profile': '프로필', + 'nav.bottomSettings': '설정', + 'nav.bottomAdmin': '관리자 설정', + 'nav.bottomLogout': '로그아웃', + 'nav.bottomAdminBadge': '관리자', + + // DayPlan Mobile + 'dayplan.mobile.addPlace': '장소 추가', + 'dayplan.mobile.searchPlaces': '장소 검색...', + 'dayplan.mobile.allAssigned': '모든 장소가 배정되었습니다', + 'dayplan.mobile.noMatch': '일치 없음', + 'dayplan.mobile.createNew': '새 장소 만들기', + + 'admin.addons.catalog.journey.name': 'Journey', + 'admin.addons.catalog.journey.description': '체크인, 사진, 일별 이야기가 있는 여행 기록 및 여행 일지', + + // OAuth scope groups + 'oauth.scope.group.trips': '여행', + 'oauth.scope.group.places': '장소', + 'oauth.scope.group.atlas': 'Atlas', + 'oauth.scope.group.packing': '짐 목록', + 'oauth.scope.group.todos': '할 일', + 'oauth.scope.group.budget': '예산', + 'oauth.scope.group.reservations': '예약', + 'oauth.scope.group.collab': '협업', + 'oauth.scope.group.notifications': '알림', + 'oauth.scope.group.vacay': '휴가', + 'oauth.scope.group.geo': '지리', + 'oauth.scope.group.weather': '날씨', + 'oauth.scope.group.journey': 'Journey', + + // OAuth scope labels & descriptions + 'oauth.scope.trips:read.label': '여행 및 일정 보기', + 'oauth.scope.trips:read.description': '여행, 날, 일별 메모, 멤버 읽기', + 'oauth.scope.trips:write.label': '여행 및 일정 편집', + 'oauth.scope.trips:write.description': '여행, 날, 메모 만들기 및 업데이트, 멤버 관리', + 'oauth.scope.trips:delete.label': '여행 삭제', + 'oauth.scope.trips:delete.description': '전체 여행 영구 삭제 — 이 작업은 되돌릴 수 없습니다', + 'oauth.scope.trips:share.label': '공유 링크 관리', + 'oauth.scope.trips:share.description': '여행의 공개 공유 링크 만들기, 업데이트, 취소', + 'oauth.scope.places:read.label': '장소 및 지도 데이터 보기', + 'oauth.scope.places:read.description': '장소, 날 배정, 태그, 카테고리 읽기', + 'oauth.scope.places:write.label': '장소 관리', + 'oauth.scope.places:write.description': '장소, 배정, 태그 만들기, 업데이트, 삭제', + 'oauth.scope.atlas:read.label': 'Atlas 보기', + 'oauth.scope.atlas:read.description': '방문한 나라, 지역, 버킷 리스트 읽기', + 'oauth.scope.atlas:write.label': 'Atlas 관리', + 'oauth.scope.atlas:write.description': '방문한 나라 및 지역 표시, 버킷 리스트 관리', + 'oauth.scope.packing:read.label': '짐 목록 보기', + 'oauth.scope.packing:read.description': '짐 항목, 가방, 카테고리 배정 읽기', + 'oauth.scope.packing:write.label': '짐 목록 관리', + 'oauth.scope.packing:write.description': '짐 항목 및 가방 추가, 업데이트, 삭제, 체크, 순서 변경', + 'oauth.scope.todos:read.label': '할 일 목록 보기', + 'oauth.scope.todos:read.description': '여행 할 일 항목 및 카테고리 배정 읽기', + 'oauth.scope.todos:write.label': '할 일 목록 관리', + 'oauth.scope.todos:write.description': '할 일 항목 만들기, 업데이트, 체크, 삭제, 순서 변경', + 'oauth.scope.budget:read.label': '예산 보기', + 'oauth.scope.budget:read.description': '예산 항목 및 지출 내역 읽기', + 'oauth.scope.budget:write.label': '예산 관리', + 'oauth.scope.budget:write.description': '예산 항목 만들기, 업데이트, 삭제', + 'oauth.scope.reservations:read.label': '예약 보기', + 'oauth.scope.reservations:read.description': '예약 및 숙박 상세 정보 읽기', + 'oauth.scope.reservations:write.label': '예약 관리', + 'oauth.scope.reservations:write.description': '예약 만들기, 업데이트, 삭제, 순서 변경', + 'oauth.scope.collab:read.label': '협업 보기', + 'oauth.scope.collab:read.description': '협업 메모, 투표, 메시지 읽기', + 'oauth.scope.collab:write.label': '협업 관리', + 'oauth.scope.collab:write.description': '협업 메모, 투표, 메시지 만들기, 업데이트, 삭제', + 'oauth.scope.notifications:read.label': '알림 보기', + 'oauth.scope.notifications:read.description': '앱 내 알림 및 읽지 않은 수 읽기', + 'oauth.scope.notifications:write.label': '알림 관리', + 'oauth.scope.notifications:write.description': '알림 읽음 표시 및 응답', + 'oauth.scope.vacay:read.label': '휴가 계획 보기', + 'oauth.scope.vacay:read.description': '휴가 계획 데이터, 항목, 통계 읽기', + 'oauth.scope.vacay:write.label': '휴가 계획 관리', + 'oauth.scope.vacay:write.description': '휴가 항목, 공휴일, 팀 계획 만들기 및 관리', + 'oauth.scope.geo:read.label': '지도 및 지오코딩', + 'oauth.scope.geo:read.description': '위치 검색, 지도 URL 확인, 좌표 역지오코딩', + 'oauth.scope.weather:read.label': '날씨 예보', + 'oauth.scope.weather:read.description': '여행 위치 및 날짜의 날씨 예보 가져오기', + 'oauth.scope.journey:read.label': 'Journey 보기', + 'oauth.scope.journey:read.description': 'Journey, 항목, 기여자 목록 읽기', + 'oauth.scope.journey:write.label': 'Journey 관리', + 'oauth.scope.journey:write.description': 'Journey 및 항목 만들기, 업데이트, 삭제', + 'oauth.scope.journey:share.label': 'Journey 링크 관리', + 'oauth.scope.journey:share.description': 'Journey의 공개 공유 링크 만들기, 업데이트, 취소', + + // System notices — 3.0.0 upgrade + 'system_notice.v3_photos.title': '3.0에서 사진이 이동했습니다', + 'system_notice.v3_photos.body': '여행 플래너의 **사진** 기능이 제거되었습니다. 사진은 안전합니다 — TREK은 Immich 또는 Synology 라이브러리를 수정하지 않았습니다.\n\n사진은 이제 **Journey** 애드온에 있습니다. Journey는 선택 사항입니다 — 아직 사용할 수 없다면 관리자에게 관리자 → 애드온에서 활성화를 요청하세요.', + 'system_notice.v3_journey.title': 'Journey를 만나보세요 — 여행 일지', + 'system_notice.v3_journey.body': '타임라인, 사진 갤러리, 인터랙티브 지도가 있는 풍부한 여행 이야기로 여행을 기록하세요.', + 'system_notice.v3_journey.cta_label': 'Journey 열기', + 'system_notice.v3_journey.highlight_timeline': '일별 타임라인 및 갤러리', + 'system_notice.v3_journey.highlight_photos': 'Immich 또는 Synology에서 가져오기', + 'system_notice.v3_journey.highlight_share': '공개 공유 — 로그인 불필요', + 'system_notice.v3_journey.highlight_export': 'PDF 사진 책으로 내보내기', + 'system_notice.v3_features.title': '3.0의 더 많은 하이라이트', + 'system_notice.v3_features.body': '이번 릴리스에서 알아두면 좋은 몇 가지 더.', + 'system_notice.v3_features.highlight_dashboard': '모바일 우선 대시보드 재설계', + 'system_notice.v3_features.highlight_offline': 'PWA로 완전한 오프라인 모드', + 'system_notice.v3_features.highlight_search': '실시간 장소 검색 자동완성', + 'system_notice.v3_features.highlight_import': 'KMZ/KML 파일에서 장소 가져오기', + + // System notices — MCP OAuth 2.1 upgrade + 'system_notice.v3_mcp.title': 'MCP: OAuth 2.1 업그레이드', + 'system_notice.v3_mcp.body': 'MCP 통합이 완전히 개선되었습니다. OAuth 2.1이 이제 권장 인증 방법입니다. 기존 정적 토큰 (trek_…)은 더 이상 사용되지 않으며 향후 릴리스에서 제거될 예정입니다.', + 'system_notice.v3_mcp.highlight_oauth': 'OAuth 2.1 권장 (mcp-remote)', + 'system_notice.v3_mcp.highlight_scopes': '24개 세분화된 권한 범위', + 'system_notice.v3_mcp.highlight_deprecated': '정적 trek_ 토큰 더 이상 사용 안 됨', + 'system_notice.v3_mcp.highlight_tools': '확장된 도구 모음 및 프롬프트', + + // System notices — personal thank you + 'system_notice.v3_thankyou.title': '개인적인 감사 인사', + 'system_notice.v3_thankyou.body': '떠나시기 전에 잠깐 시간을 내주세요.\n\nTREK은 제 자신의 여행을 위해 만든 사이드 프로젝트로 시작했습니다. 4,000명이 넘는 분들이 모험을 계획하는 데 신뢰해 주실 줄은 상상도 못 했습니다. 모든 별, 모든 이슈, 모든 기능 요청 — 저는 다 읽고, 그것들이 풀타임 직장과 대학 사이의 늦은 밤을 버티게 해줍니다.\n\n알아주셨으면 합니다: TREK은 항상 오픈 소스이고, 항상 자체 호스팅이며, 항상 여러분의 것입니다. 추적 없음, 구독 없음, 조건 없음. 그저 여러분만큼 여행을 사랑하는 누군가가 만든 도구입니다.\n\n[jubnl](https://github.com/jubnl)에게 특별한 감사를. 당신은 훌륭한 협력자가 되었습니다. 3.0을 훌륭하게 만든 많은 부분에 당신의 손길이 담겨 있습니다. 거칠던 초기에 이 프로젝트를 믿어줘서 고맙습니다.\n\n그리고 버그를 제출하고, 문자열을 번역하고, TREK을 친구에게 공유하거나, 단순히 여행 계획에 사용해 주신 모든 분들께 — **감사합니다**. 여러분이 바로 이것이 존재하는 이유입니다.\n\n함께하는 더 많은 모험을 위해.\n\n— Maurice\n\n---\n\n[Discord 커뮤니티에 참여하세요](https://discord.gg/7Q6M6jDwzf)\n\nTREK이 여행을 더 즐겁게 만들어 준다면, [커피 한 잔](https://ko-fi.com/mauriceboe)으로 불을 켜두는 데 도움이 됩니다.', + + // System notices — 3.0.14 + 'system_notice.v3014_whitespace_collision.title': '조치 필요: 사용자 계정 충돌', + 'system_notice.v3014_whitespace_collision.body': '3.0.14 업그레이드 중 저장된 계정의 앞뒤 공백으로 인한 사용자 이름 또는 이메일 충돌이 감지되었습니다. 영향받은 계정은 자동으로 이름이 변경되었습니다. 검토가 필요한 계정을 확인하려면 **[migration] WHITESPACE COLLISION**으로 시작하는 줄의 서버 로그를 확인하세요.', + + // System notices — onboarding + 'system_notice.welcome_v1.title': 'TREK에 오신 것을 환영합니다', + 'system_notice.welcome_v1.body': '올인원 여행 플래너. 일정을 만들고, 친구들과 여행을 공유하고, 온라인 또는 오프라인으로 체계적으로 유지하세요.', + 'system_notice.welcome_v1.cta_label': '여행 계획', + 'system_notice.welcome_v1.hero_alt': 'TREK 계획 UI 오버레이가 있는 아름다운 여행지', + 'system_notice.welcome_v1.highlight_plan': '모든 여행을 위한 일별 일정', + 'system_notice.welcome_v1.highlight_share': '여행 파트너와 협업', + 'system_notice.welcome_v1.highlight_offline': '모바일에서 오프라인으로 작동', + 'system_notice.dev_test_modal.title': '[Dev] 테스트 공지', + 'system_notice.dev_test_modal.body': '개발 전용 테스트 공지입니다.', + 'system_notice.pager.prev': '이전 공지', + 'system_notice.pager.next': '다음 공지', + 'system_notice.pager.counter': '{current} / {total}', + 'system_notice.pager.goto': '{n}번 공지로 이동', + 'system_notice.pager.position': '공지 {current}/{total}', + 'transport.addTransport': '교통 추가', + 'transport.modalTitle.create': '교통 추가', + 'transport.modalTitle.edit': '교통 편집', + 'transport.title': '교통', + 'transport.addManual': '직접 교통 입력', + + // Added to match EN keys + 'journey.editor.uploadingProgress': '업로드 중 {done}/{total}…', + 'journey.editor.uploadFailed': '사진 업로드 실패', + 'journey.editor.uploadPartialFailed': '{total}개 중 {failed}개의 사진을 업로드하지 못했습니다 — 다시 저장하여 재시도하세요', + 'journey.photosUploadFailed': '일부 사진을 업로드하지 못했습니다', + 'settings.oauth.modal.machineClient': '머신 클라이언트(브라우저 로그인 없음)', + 'settings.oauth.modal.machineClientHint': 'client_credentials 권한 부여를 사용합니다 — 리디렉션 URI가 필요하지 않습니다. 토큰은 client_id + client_secret을 통해 직접 발급되며 선택한 범위 내에서 사용자로 작동합니다.', + 'settings.oauth.modal.machineClientUsage': '토큰 받기: grant_type=client_credentials, client_id, client_secret으로 POST /oauth/token을 호출하세요. 브라우저도 새로 고침 토큰도 필요 없습니다.', + 'settings.oauth.badge.machine': '머신', +} + +export default ko