diff --git a/apps/desktop/src/main/__tests__/settings-preferences-copy.test.ts b/apps/desktop/src/main/__tests__/settings-preferences-copy.test.ts index c0c5a05203..62011cdfed 100644 --- a/apps/desktop/src/main/__tests__/settings-preferences-copy.test.ts +++ b/apps/desktop/src/main/__tests__/settings-preferences-copy.test.ts @@ -29,18 +29,28 @@ test('language selector offers every preference with locale-appropriate labels', ['auto', '跟随系统'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], + ['ko', '한국어'], ['en', 'English'], ]); assert.deepEqual(getSettingsPreferencesCopy('zh-TW').personalization.localeOptions, [ ['auto', '自動(跟隨系統)'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], + ['ko', '한국어'], + ['en', 'English'], + ]); + assert.deepEqual(getSettingsPreferencesCopy('ko').personalization.localeOptions, [ + ['auto', '시스템 설정 따름'], + ['zh-CN', '简体中文'], + ['zh-TW', '繁體中文'], + ['ko', '한국어'], ['en', 'English'], ]); assert.deepEqual(getSettingsPreferencesCopy('en').personalization.localeOptions, [ ['auto', 'Follow system'], ['zh-CN', 'Simplified Chinese'], ['zh-TW', 'Traditional Chinese'], + ['ko', 'Korean'], ['en', 'English'], ]); }); diff --git a/apps/desktop/src/renderer/locales/onboarding-copy.ts b/apps/desktop/src/renderer/locales/onboarding-copy.ts index f408b0ab3b..2fd5f52d47 100644 --- a/apps/desktop/src/renderer/locales/onboarding-copy.ts +++ b/apps/desktop/src/renderer/locales/onboarding-copy.ts @@ -198,6 +198,55 @@ const ONBOARDING_COPY_BY_LOCALE: UiCatalog = { skip: 'Skip onboarding', snapshotErrorFallback: 'First-run status is temporarily unavailable. Try again later.', }, + ko: { + hero: { + needs_connection: { + eyebrow: 'Maka에 오신 것을 환영합니다', + title: 'AI를 연결하고 첫 작업을 시작하세요.', + body: 'Maka는 본인의 모델 계정이나 API 키로 로컬에서 실행됩니다. 계속하려면 주요 모델 제공자를 선택하세요.', + cta: { label: '전체 모델 제공자 보기' }, + }, + needs_connection_credentials: { + eyebrow: '연결 설정 계속하기', + title: '이 연결에 사용할 인증 정보를 추가하세요.', + body: 'API 키를 추가하거나 계정 로그인을 완료하면 Maka가 모델을 호출할 수 있습니다.', + cta: { label: '인증 정보 설정' }, + }, + needs_model: { + eyebrow: '연결 설정 계속하기', + title: '이 연결에서 사용 가능한 모델을 켜세요.', + body: '대화가 가능한 모델을 켜면 첫 작업을 시작할 수 있습니다.', + cta: { label: '사용 가능한 모델 선택' }, + }, + 'blocked:all_connections_unhealthy': { + eyebrow: '연결 확인 필요', + title: '모델 연결을 일시적으로 사용할 수 없습니다.', + body: '기존 연결 중 검증을 통과한 것이 없습니다. 인증 정보, 로그인 상태, 네트워크 접근을 확인한 뒤 다시 테스트해 주세요.', + cta: { label: '모델 연결 문제 해결' }, + tone: 'destructive', + }, + 'blocked:all_connections_retired': { + eyebrow: '연결 확인 필요', + title: '연결에서 사용하는 로그인 방식의 지원이 종료되었습니다.', + body: '이 연결들이 사용하는 로그인 방식이 Maka에서 제거되었습니다. 더 이상 로그인하거나 대화에 사용할 수 없습니다. 계속하려면 새 모델 연결을 추가해 주세요.', + cta: { label: '모델 연결 추가' }, + tone: 'destructive', + }, + }, + needsConnection: { + pickLabel: '주요 모델 제공자 선택', + browseProviders: '전체 모델 제공자 보기', + }, + refresh: { + connection: '연결 다시 확인', + credentials: '인증 정보 다시 확인', + model: '모델 다시 확인', + blocked: '연결 다시 확인', + }, + connectionLabel: '연결', + skip: '온보딩 건너뛰기', + snapshotErrorFallback: '첫 실행 상태를 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.', + }, }; export function getOnboardingCopy(locale: UiLocale): OnboardingCatalog { diff --git a/apps/desktop/src/renderer/locales/permission-center-copy.ts b/apps/desktop/src/renderer/locales/permission-center-copy.ts index e2398a71eb..e868b9bf0d 100644 --- a/apps/desktop/src/renderer/locales/permission-center-copy.ts +++ b/apps/desktop/src/renderer/locales/permission-center-copy.ts @@ -272,6 +272,63 @@ const PERMISSION_CENTER_COPY = { } satisfies Record)[health], reasonFallback: 'See the runtime logs for details.', }, + ko: { + readiness: { + not_configured: { label: '설정 필요', detail: '먼저 기능을 켜거나 구성을 완료하세요.', tone: 'neutral' }, + denied: { label: '시스템에서 거부됨', detail: '필요한 시스템 권한이 거부되었거나 이 플랫폼에서 지원되지 않습니다.', tone: 'error' }, + enabled: { label: '사용 가능', detail: '현재 스냅샷은 사용 가능합니다. 자세한 내용은 아래 계층에서 확인하세요.', tone: 'success' }, + degraded: { label: '부분 사용 가능', detail: '일부 기능은 사용할 수 있지만 런타임, 권한, 하위 기능에 남은 작업이 있습니다.', tone: 'attention' }, + paused: { label: '일시 중지됨', detail: '구성은 저장된 채로 기능만 명시적으로 꺼졌습니다.', tone: 'neutral' }, + }, + osPermissions: { + accessibility: { label: '손쉬운 사용', purpose: 'Computer Use가 창 포커스를 읽고 키보드나 마우스 입력을 시뮬레이션하려면 필요합니다.', impact: 'Computer Use · 키보드와 마우스 자동 입력' }, + screen_recording: { label: '화면 및 시스템 오디오 녹음', purpose: 'Computer Use가 창 내용을 읽으려면 필요합니다. 앞으로 화면 활동 기록에도 사용됩니다.', impact: 'Computer Use · 스크린샷 컨텍스트' }, + notifications: { label: '알림', purpose: '권한 요청, 데일리 리뷰 완료 등 시스템 알림에 필요합니다.', impact: '권한 알림 · 데일리 리뷰 완료' }, + automation: { label: '자동화(Apple Events)', purpose: 'Computer Use가 다른 앱을 제어하려면 대상별 허용이 필요합니다.', impact: 'Computer Use · 앱 간 자동화' }, + }, + osStates: { + unsupported: { label: '이 플랫폼 미지원', tone: 'neutral' }, unknown: { label: '상태를 알 수 없음', tone: 'neutral' }, + not_determined: { label: '권한 대기 중', tone: 'attention' }, denied: { label: '거부됨', tone: 'error' }, granted: { label: '허용됨', tone: 'success' }, + }, + loading: '권한 스냅샷 불러오는 중', readFailed: '권한 스냅샷 읽기 실패', noData: '권한 서비스가 데이터를 반환하지 않았습니다.', readAgain: '다시 읽기', + actionFailed: '권한 동작 실패', + actionFailures: { + invalid_id: '내부 오류: 권한 ID를 인식할 수 없습니다.', + unsupported_platform: '이 운영체제는 권한 동작을 지원하지 않습니다.', + unsupported_permission: '이 플랫폼은 해당 권한의 직접 진입점을 제공하지 않습니다.', + denied: '권한이 허용되지 않았습니다. 시스템 설정에서 켤 수 있습니다.', + already_open: '다른 권한 안내가 아직 열려 있습니다. 먼저 완료하거나 닫아 주세요.', + open_settings_failed: '시스템 설정을 열지 못했습니다. 개인정보 보호 및 보안을 직접 열어 주세요.', + failed: '권한 동작이 성공하지 못했습니다. 잠시 후 다시 시도해 주세요.', + }, + title: '권한과 기능 상태', subtitle: 'Maka에 필요한 시스템 권한과 현재 상태를 확인하세요. 해당하는 개인정보 보호 및 보안 섹션을 바로 열어 접근을 허용하거나 철회하세요.', + lastRead: '최근 읽음: ', detectAgain: '다시 확인', summaryAria: '허용 상태로 시스템 권한 필터링', summaryFilterAria: (label, count, selected) => selected ? `${label}, ${count}개. 필터 적용됨. 다시 누르면 모든 권한을 표시합니다` : `${label} 권한만 표시, ${count}개`, granted: '허용됨', pending: '대기 중', denied: '거부됨', other: '알 수 없음 / 미지원', + osSection: '시스템 권한', osSectionHelp: 'Maka가 읽은 OS 수준 권한 상태입니다. 오른쪽 동작으로 시스템 설정의 해당 개인정보 보호 및 보안 섹션을 열 수 있습니다.', osListAria: '시스템 권한 목록', + capabilitiesSection: '기능 상태', capabilitiesHelp: '각 준비 상태는 기능 토글, 구성, 시스템 권한, 런타임 프로브를 합쳐서 결정됩니다.', + capabilityListAria: '기능 상태 목록', + footnote: 'Maka는 손쉬운 사용, 자동화, 화면 및 시스템 오디오 녹음을 자동으로 허용하지 않습니다. 고위험 자동화는 건별 승인, 감사 가능, 철회 가능 상태로 유지되어야 합니다. 이 페이지는 현재 스냅샷을 읽기만 합니다. 권한 변경은 여전히 시스템 설정의 개인정보 보호 및 보안에서 해야 합니다.', + layers: { + aria: (label) => `${label} 기능 상태 상세`, feature: '기능 토글', configuration: '구성', approval: '동작 승인', memory: '메모리 쓰기', runtime: '런타임 프로브', + featureStates: { enabled: '켜짐', partial: '부분 사용 가능', disabled: '꺼짐', not_available: '사용할 수 없음' }, + configurationStates: { not_required: '구성 불필요', missing: '구성 필요', present: '구성됨' }, + approvalStates: { not_required: '승인 불필요', required_per_action: '호출마다 승인 필요', required_scoped_lease: '대상과 동작 범주별 허용', pending: '승인 대기 중', approved: '이 작업에 승인됨', denied: '이 작업에 거부됨' }, + memoryStates: { not_applicable: '메모리 쓰기 없음', disabled: '메모리 쓰기 꺼짐', draft_required: '메모리 프로토콜을 먼저 작성하세요', accepted: '메모리 쓰기 수락됨' }, + runtimeStates: { not_available: '런타임 프로브 없음', not_run: '프로브 미실행', healthy: '프로브 통과', degraded: '프로브 저하' }, + }, + requiredPermissions: '필요한 시스템 권한', requiredPermissionsAria: (label) => `${label} 필요 시스템 권한`, + auditSection: '감사 기록', noAudit: '감사 기록 없음', auditAria: (label) => `${label} 감사 기록`, + impact: '영향 범위', opening: '여는 중…', openSettings: '시스템 설정 열기', requesting: '요청하는 중…', request: '권한 요청', dragGrant: '안내 받기', dragGranting: '여는 중…', + cuBackendStatus: (missing, health) => + 'maka-cu 아티팩트가 로컬 무결성 검사를 통과했습니다. ' + + (missing.length > 0 ? `${missing.join(', ')} 권한을 기다리는 중입니다. ` : '') + + ({ + not_available: 'maka-cu 서비스가 시작에 실패했거나, 종료됐거나, 중지되었습니다.', + degraded: 'maka-cu 서비스가 시작 중이거나 복구 중입니다.', + healthy: '동작·스크린샷 서비스가 준비됐습니다. 로컬 앱을 조작하려면 대상과 동작 범주별로 허용하세요.', + not_run: '서비스는 처음 사용할 때 시작됩니다. 로컬 앱을 조작하려면 대상과 동작 범주별로 허용하세요.', + } satisfies Record)[health], + reasonFallback: '자세한 내용은 런타임 로그를 확인하세요.', + }, } satisfies UiCatalog; export function getPermissionCenterCopy(locale: UiLocale): PermissionCenterCopy { diff --git a/apps/desktop/src/renderer/locales/settings-preferences-copy.ts b/apps/desktop/src/renderer/locales/settings-preferences-copy.ts index a065bc83d3..cbdf97c306 100644 --- a/apps/desktop/src/renderer/locales/settings-preferences-copy.ts +++ b/apps/desktop/src/renderer/locales/settings-preferences-copy.ts @@ -270,7 +270,7 @@ const SETTINGS_PREFERENCES_COPY_BY_LOCALE = { 'zh-CN': { personalization: { saveFailed: '保存失败', displayName: '显示名称', displayNameHelp: 'Maka 在聊天里会以这个名字称呼你。留空就用默认的“你”。', displayNamePlaceholder: '例如:JK', displayNameUnset: '未设置,Maka 会称呼你“你”', displayNameChange: '更改', displayNameSet: '设置', - interfaceLanguage: '界面语言', interfaceLanguageHelp: '选择 Maka 界面的显示语言。切换后立即生效,重启后保持。', localeOptions: [['auto', '跟随系统'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], ['en', 'English']], + interfaceLanguage: '界面语言', interfaceLanguageHelp: '选择 Maka 界面的显示语言。切换后立即生效,重启后保持。', localeOptions: [['auto', '跟随系统'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], ['ko', '한국어'], ['en', 'English']], assistantTone: '助手语气偏好', assistantToneHelp: '最多 500 字,只影响回答的语气和风格。权限确认与安全规则不受影响;改动会自动保存。', assistantTonePlaceholder: '例如:技术严谨、偏简洁、不要 emoji。', }, sections: { @@ -369,7 +369,7 @@ const SETTINGS_PREFERENCES_COPY_BY_LOCALE = { 'zh-TW': { personalization: { saveFailed: '儲存失敗', displayName: '顯示名稱', displayNameHelp: 'Maka 在聊天裡會以這個名字稱呼你。留空就用預設的“你”。', displayNamePlaceholder: '例如:JK', displayNameUnset: '未設定,Maka 會稱呼你“你”', displayNameChange: '更改', displayNameSet: '設定', - interfaceLanguage: '介面語言', interfaceLanguageHelp: '選擇 Maka 介面的顯示語言。切換後立即生效,重新啟動後仍會保留。', localeOptions: [['auto', '自動(跟隨系統)'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], ['en', 'English']], + interfaceLanguage: '介面語言', interfaceLanguageHelp: '選擇 Maka 介面的顯示語言。切換後立即生效,重新啟動後仍會保留。', localeOptions: [['auto', '自動(跟隨系統)'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], ['ko', '한국어'], ['en', 'English']], assistantTone: '助手語氣偏好', assistantToneHelp: '最多 500 字,只影響回答的語氣和風格。權限確認與安全規則不受影響;改動會自動儲存。', assistantTonePlaceholder: '例如:技術嚴謹、偏簡潔、不要 emoji。', }, sections: { @@ -459,7 +459,7 @@ const SETTINGS_PREFERENCES_COPY_BY_LOCALE = { }, en: { personalization: { - saveFailed: 'Could not save', displayName: 'Display name', displayNameHelp: 'Maka uses this name when addressing you. Leave it blank to use “you”.', displayNamePlaceholder: 'For example: JK', displayNameUnset: 'Not set — Maka will say “you”', displayNameChange: 'Change', displayNameSet: 'Set', interfaceLanguage: 'Interface language', interfaceLanguageHelp: 'Choose the language used by Maka. Changes apply immediately and persist after restart.', localeOptions: [['auto', 'Follow system'], ['zh-CN', 'Simplified Chinese'], ['zh-TW', 'Traditional Chinese'], ['en', 'English']], assistantTone: 'Assistant tone', assistantToneHelp: 'Up to 500 characters. This changes response style only; permission and safety rules still apply. Changes save automatically.', assistantTonePlaceholder: 'For example: technically rigorous, concise, and no emoji.', + saveFailed: 'Could not save', displayName: 'Display name', displayNameHelp: 'Maka uses this name when addressing you. Leave it blank to use “you”.', displayNamePlaceholder: 'For example: JK', displayNameUnset: 'Not set — Maka will say “you”', displayNameChange: 'Change', displayNameSet: 'Set', interfaceLanguage: 'Interface language', interfaceLanguageHelp: 'Choose the language used by Maka. Changes apply immediately and persist after restart.', localeOptions: [['auto', 'Follow system'], ['zh-CN', 'Simplified Chinese'], ['zh-TW', 'Traditional Chinese'], ['ko', 'Korean'], ['en', 'English']], assistantTone: 'Assistant tone', assistantToneHelp: 'Up to 500 characters. This changes response style only; permission and safety rules still apply. Changes save automatically.', assistantTonePlaceholder: 'For example: technically rigorous, concise, and no emoji.', }, sections: { identity: 'Identity', identityHelp: 'How Maka addresses you, plus interface language and response tone.', @@ -519,6 +519,68 @@ const SETTINGS_PREFERENCES_COPY_BY_LOCALE = { }, password: { copyFailed: 'Copy failed', clipboardUnavailable: 'The clipboard is unavailable or access was denied.', copying: 'Copying', copied: 'Copied', copy: 'Copy', hide: 'Hide', show: 'Show', value: 'credential value' }, }, + ko: { + personalization: { + saveFailed: '저장 실패', displayName: '표시 이름', displayNameHelp: 'Maka가 사용자를 부를 때 이 이름을 씁니다. 비워 두면 이름 없이 부릅니다.', displayNamePlaceholder: '예: JK', displayNameUnset: '설정 안 됨 — Maka가 이름 없이 부릅니다', displayNameChange: '변경', displayNameSet: '설정', interfaceLanguage: '인터페이스 언어', interfaceLanguageHelp: 'Maka에서 사용할 언어를 선택하세요. 변경 사항은 즉시 적용되며 다시 시작한 후에도 유지됩니다.', localeOptions: [['auto', '시스템 설정 따름'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'], ['ko', '한국어'], ['en', 'English']], assistantTone: '어시스턴트 어조', assistantToneHelp: '최대 500자입니다. 응답 스타일만 바뀌며 권한과 안전 규칙은 그대로 적용됩니다. 변경 사항은 자동으로 저장됩니다.', assistantTonePlaceholder: '예: 기술적으로 엄밀하게, 간결하게, 이모지 없이.', + }, + sections: { + identity: '프로필', identityHelp: 'Maka가 사용자를 부르는 방식과 인터페이스 언어, 응답 어조를 정합니다.', + privacy: '개인정보 보호 및 알림', privacyHelp: 'Maka가 로컬에서 읽고 쓸 수 있는 범위와 알림을 보내는 시점을 정합니다.', + chatDefaults: '작업 기본값', chatDefaultsHelp: '새 작업이 시작할 때 쓰는 모델, 권한 모드, 사고 수준입니다.', + shell: '명령 실행 환경', shellHelp: 'Runtime Host가 Bash 도구와 터미널 명령에 사용할 셸을 선택하세요.', + network: '네트워크', networkHelp: 'AI 모델 요청이 거치는 네트워크 경로입니다.', + theme: '테마', themeHelp: '시스템 화면 모드를 따르거나 라이트 또는 다크로 고정합니다.', + palette: '색상 팔레트', paletteHelp: '강조 색상과 캔버스 색상입니다. 변경 사항은 즉시 적용되고 로컬에 저장됩니다.', + appIcon: '앱 아이콘', appIconHelp: 'Dock, 작업 표시줄, 앱 전환기에 표시되는 Maka 아이콘입니다. 변경 사항은 즉시 적용됩니다.', + fontSize: '글꼴 크기', fontSizeHelp: '인터페이스와 터미널 전체의 텍스트 크기입니다. 변경 사항은 즉시 적용되고 로컬에 저장됩니다.', + pets: '사용자 지정 펫', petsHelp: '직접 가져온 PetPack을 관리합니다. Maka는 기본으로 포함하거나 켜 두는 펫이 없습니다.', + }, + appearance: { + saveFailed: '모양 설정 저장 실패', theme: '테마', palette: '색상 팔레트', themeOptions: { light: { label: '라이트', help: '항상 라이트 인터페이스를 사용합니다.' }, dark: { label: '다크', help: '항상 다크 인터페이스를 사용합니다.' }, auto: { label: '시스템 설정 따름', help: '현재 시스템 화면 모드에 맞춥니다.' } }, paletteLabels: { default: '기본', onedark: 'One Dark', 'catppuccin-mocha': 'Catppuccin Mocha', 'tokyo-night': 'Tokyo Night', nord: 'Nord', coral: '코랄', azure: '애저', forest: '포레스트', dusk: '더스크', sand: '샌드', mono: '모노크롬' }, paletteHelp: { default: 'Maka 브랜드 블루 강조 색상', onedark: '클래식 다크 에디터 테마', 'catppuccin-mocha': '부드러운 보라색 다크 테마', 'tokyo-night': '짙은 파란색 에디터 테마', nord: '차가운 북유럽 색감', coral: '따뜻한 분홍·코랄 강조 색상', azure: '깔끔하고 차분한 파란색 강조 색상', forest: '짙은 이끼색과 따뜻한 꿀색', dusk: '차가운 캔버스 위의 짙은 보라색', sand: '앰버 샌드와 따뜻한 아이보리', mono: '색이 없는 순수 회색조' }, paletteGroups: { editor: '에디터 테마', product: '제품 색상' }, appIconLabels: { default: '클래식', mono: '모노크롬', 'sky': '스카이', 'cyan': '시안', 'ice': '아이스', 'pale-inverted': '인버티드', 'ink': '잉크', 'paper': '페이퍼', 'graphite': '그래파이트', 'pencil-kraft': '펜슬, 크래프트', 'pencil-sky': '펜슬, 스카이', 'pencil-navy': '펜슬, 네이비', 'alpine': '알파인', 'dusk': '더스크', 'night': '나이트', 'midnight': '미드나이트', 'carbon': '카본', 'slate': '슬레이트', 'obsidian': '옵시디언', 'neon-cyan': '네온 시안', 'matrix': '포스퍼', 'magenta': '마젠타', 'amber-crt': '앰버 CRT', 'clay': '클레이', 'sage': '세이지', 'dust': '더스트', 'fog': '포그', 'sunset': '선셋', 'amber': '앰버', 'terracotta': '테라코타', 'ocean': '오션', 'moss': '모스', 'desert': '데저트', 'glacier': '글레이셔', 'gold': '골드', 'chrome': '크롬', 'mono-black': '모노 블랙', 'mono-white': '모노 화이트', 'hazard': '해저드', 'forest': '포레스트' }, appIconHelp: { default: '기본 Maka 마크', mono: '회색조, 더 차분한 Dock용', 'sky': '브랜드 블루의 기하학적 M 마크', 'cyan': '시안에 가까운 파란색', 'ice': '옅은 파란색에서 짙은 파란색으로 이어지는 그라데이션', 'pale-inverted': '옅은 바탕에 짙은 파란색 마크', 'ink': '검은 바탕에 흰색, 가장 높은 대비', 'paper': '흰 바탕에 검은색', 'graphite': '흰 바탕에 검은색, 끝은 회색', 'pencil-kraft': '펜슬 모티프, 크래프트 바탕', 'pencil-sky': '펜슬 모티프, 스카이 블루 바탕', 'pencil-navy': '펜슬 모티프, 짙은 네이비 바탕', 'alpine': '맑은 하늘 아래 눈 덮인 봉우리', 'dusk': '황혼의 눈 덮인 봉우리', 'night': '밤의 눈 덮인 봉우리', 'midnight': '짙은 네이비 바탕의 밝은 마크. 어두운 Dock에서도 윤곽이 살아 있음', 'carbon': '완전한 검정이라 OLED 화면에는 마크만 보임', 'slate': '차가운 슬레이트 바탕에 옅은 회색', 'obsidian': '보랏빛 검정 그라데이션 바탕에 라일락색', 'neon-cyan': '검정에 가까운 바탕에 선명한 시안', 'matrix': '포스퍼 터미널의 녹색', 'magenta': '짙은 보라색 바탕에 핫핑크', 'amber-crt': '초기 터미널의 앰버색', 'clay': '차분한 테라코타', 'sage': '차분한 회녹색', 'dust': '차분한 더스티 로즈', 'fog': '차분한 청회색', 'sunset': '주황에서 분홍으로 이어지는 대각선', 'amber': '앰버 바탕에 어두운 마크', 'terracotta': '벽돌색 그라데이션', 'ocean': '짙은 청록 그라데이션', 'moss': '짙은 모스 그라데이션', 'desert': '데저트 샌드 바탕에 어두운 마크', 'glacier': '옅은 빙하색 파랑', 'gold': '마크 자체에 골드 그라데이션', 'chrome': '마크 자체에 은색 그라데이션', 'mono-black': '순백 바탕에 검은색. 한 가지 색으로 인쇄 가능', 'mono-white': '완전한 검정 바탕에 흰색', 'hazard': '검은 바탕에 노란색, 이 묶음에서 대비가 가장 높음', 'forest': '녹색 바탕의 눈 덮인 봉우리' }, appIconGroups: { mascot: '마스코트', blue: '파란색 계열', contrast: '흑백', pencil: '펜슬', mountain: '산', dark: '다크', neon: '네온', muted: '차분한 색', warm: '따뜻한 색', nature: '자연', metal: '금속', highContrast: '고대비', custom: '가져온 항목' }, appIconSplitLabel: '다크 모드에서 다른 아이콘 사용', appIconSplitHelp: '끄면 두 화면 모드 모두 같은 아이콘을 사용합니다.', appIconTargets: { light: '라이트', dark: '다크' }, appIconCustom: '가져온 아이콘', appIconCustomHelp: '직접 가져온 이미지', appIconImport: '아이콘 가져오기…', appIconImporting: '가져오는 중…', appIconImportHelp: '정사각형 PNG가 가장 좋습니다. Dock에서 다른 앱과 같은 크기로 보이도록 가장자리에 약 10%의 투명 여백을 두세요.', appIconRemove: '제거', appIconImportError: '아이콘 가져오기 실패', appIconRemoveFailed: '아이콘 제거 실패', appIconSelectFailed: '아이콘 전환 실패', appIconImportFailed: { too_large: '파일이 너무 큽니다. 더 작은 이미지를 선택하세요', too_many_pixels: '이미지가 너무 큽니다. 최대 4096×4096입니다', unsupported_format: 'PNG와 JPEG만 지원됩니다', unreadable: '이 파일에서 이미지를 읽지 못했습니다', too_small: '이미지가 너무 작습니다. 최소 128×128입니다', write_failed: '가져온 아이콘 저장 실패' }, appIconUnavailable: '앱 아이콘 불러오기 실패', fontSize: { uiLabel: 'UI 글꼴 크기', uiHelp: '인터페이스 전체에 쓰이는 기본 글꼴 크기', terminalLabel: '터미널 글꼴 크기', terminalHelp: '터미널 출력과 코드에 쓰이는 글꼴 크기' }, + }, + pets: { + import: 'PetPack 가져오기', importing: '가져오는 중…', loading: '사용자 지정 펫 불러오는 중…', + status: '데스크톱 펫', activePet: (name) => `현재 사용 중: ${name}`, disabled: '꺼짐', disable: '펫 끄기', disabling: '끄는 중…', + empty: '아직 가져온 펫 없음', emptyHelp: 'pet.json과 스프라이트 시트가 들어 있는 로컬 폴더를 선택하세요.', + selected: '사용 중', select: '사용', selecting: '전환하는 중…', remove: '제거', removing: '제거하는 중…', + removeTitle: (name) => `“${name}” 제거할까요?`, removeDescription: 'Maka에 저장된 이 펫 팩의 로컬 사본이 제거되며 되돌릴 수 없습니다. 원본 폴더에는 영향이 없습니다.', confirmRemove: '제거', cancel: '취소', + loadFailed: '사용자 지정 펫 불러오기 실패', importFailed: '펫 가져오기 실패', selectFailed: '펫 전환 실패', removeFailed: '펫 제거 실패', + importErrors: { invalid_directory: '선택한 폴더가 올바르지 않습니다.', invalid_manifest: 'pet.json이 maka.pet/v1 형식과 맞지 않습니다.', invalid_asset: '스프라이트 시트가 없거나, 올바르지 않거나, 지원 범위를 벗어났습니다.', already_installed: '같은 ID의 펫이 이미 설치되어 있습니다.', read_failed: '선택한 폴더를 읽지 못했습니다.' }, + selectErrors: { invalid_id: '펫 ID가 올바르지 않습니다.', not_found: '이 펫은 더 이상 로컬 라이브러리에 없습니다.', read_failed: '펫 라이브러리를 읽지 못했습니다.', write_failed: '펫 선택을 저장하지 못했습니다.' }, + removeErrors: { invalid_id: '펫 ID가 올바르지 않습니다.', remove_failed: '로컬 펫 팩을 제거하지 못했습니다.' }, + }, + general: { + incognito: '시크릿 모드', incognitoHelp: '로컬 메모리, 웹 검색, 정기 작업 실행을 일시 중지합니다.', enableIncognito: '시크릿 모드 켜기', incognitoFailed: '시크릿 모드 변경 실패', notifications: '완료되면 시스템 알림 보내기', notificationsHelp: '창이 백그라운드에 있을 때 응답이 완료되거나 실패하면 알립니다.', notificationsFailed: '알림 설정 변경 실패', workspaceInstructions: '프로젝트 지침 따르기', workspaceInstructionsHelp: '각 프로젝트에 있는 AGENTS.md, CLAUDE.md, GEMINI.md 파일을 자동으로 읽습니다. 파일은 각 프로젝트에서 관리하세요.', workspaceInstructionsFailed: '프로젝트 지침 설정 변경 실패', workHub: 'WorkHub 켜기', workHubHelp: 'WorkHub는 아직 사용할 수 없습니다. 이 토글은 개발 테스트용이며, 켜도 사용할 수 있는 기능이 생기지 않습니다.', workHubFailed: 'WorkHub 설정 변경 실패', updateFailed: '설정이 적용되지 않았습니다. 잠시 후 다시 시도해 주세요.', defaultModel: '기본 모델', defaultModelHelp: '새 작업에 사용할 모델입니다.', notSet: '설정 안 됨', saveDefaultModelFailed: '기본 모델 저장 실패', defaultPermission: '기본 권한 모드', defaultPermissionHelp: '새 작업의 초기 권한 모드입니다. 언제든지 바꿀 수 있습니다.', saveDefaultPermissionFailed: '기본 권한 모드 저장 실패', defaultThinking: '기본 사고 수준', defaultThinkingHelp: '새 작업의 사고 수준입니다. 선택한 수준을 지원하지 않는 모델은 자체 기본값을 사용합니다.', followModelDefault: '모델 기본값 따름', saveDefaultThinkingFailed: '기본 사고 수준 저장 실패', proxy: '프록시 서버', proxyHelp: 'AI 모델 요청에 사용할 네트워크 프록시를 설정하세요', enableProxy: '프록시 서버 켜기', saveNetworkFailed: '네트워크 설정 저장 실패', proxyProtocol: '프록시 프로토콜', serverAddress: '서버 주소', port: '포트', proxyAuth: '프록시 인증', proxyAuthHelp: '사용자 이름과 비밀번호가 필요할 때 켜세요.', enableProxyAuth: '프록시 인증 켜기', username: '사용자 이름', password: '비밀번호', bypassList: '프록시 우회 목록', bypassHelp: '이 도메인은 프록시를 거치지 않고 직접 연결됩니다. 여러 도메인은 쉼표로 구분하세요.', autoBypass: (count) => `도메인 ${count}개가 자동으로 추가되었습니다. 프록시는 AI 모델 요청에만 적용됩니다.`, testing: '테스트하는 중…', testCurrent: '현재 구성 테스트', proxyReachable: '프록시에 연결할 수 있음', proxyTestFailed: '프록시 테스트 실패', proxyTestError: '프록시를 테스트하지 못함', + shellPreference: 'Bash 도구 셸', shellPreferenceHelp: '자동은 PowerShell을 우선하는 Windows 기본 동작을 유지합니다. Git Bash는 현재 Runtime Host에만 적용되는 명시적 재정의입니다.', shellAuto: '자동(권장)', shellGitBash: 'Git Bash', shellExecutable: 'Git Bash 실행 파일', shellExecutableHelp: 'Runtime Host를 실행하는 Windows 컴퓨터에서 bash.exe의 절대 경로를 입력하세요. 기존 System32 WSL Bash 심(shim)도 인식합니다. Maka는 저장하기 전에 GNU Bash인지 확인합니다.', saveShell: '셸 설정 저장', savingShell: '저장하는 중…', shellSaved: '저장됨', saveShellFailed: '셸 설정 저장 실패', shellExecutableRejected: '현재 Runtime Host에서 이 경로를 GNU Bash로 실행하지 못했습니다. Host가 Windows에서 실행 중인지, 경로가 있는지, 파일 이름이 bash.exe인지 확인하세요.', + passwordSavedPlaceholder: '비밀번호가 저장되어 있습니다. 바꾸려면 새 비밀번호를 입력하세요', + }, + about: { + loadFailed: '앱 정보 불러오기 실패', loading: '앱 정보 불러오는 중', unavailable: '앱 정보를 사용할 수 없음', copied: '진단 정보 복사됨', pasteHint: '내용을 확인한 뒤 이슈 보고서에 붙여 넣으세요', copyFailed: '복사 실패', clipboardUnavailable: '클립보드를 사용할 수 없거나 접근이 거부되었습니다.', + channelSummaries: { + dev: '로컬 개발 빌드입니다. 업데이트를 확인하지 않습니다.', + nightly: '매일 나오는 사전 릴리스 빌드입니다. 최신 nightly로 자동 업데이트되며 정식 릴리스 설치를 대체합니다.', + release: '공식 릴리스 빌드입니다. 안정 업데이트를 자동으로 받습니다.', + }, + supportTitle: '지원', + copyDiagnostics: '진단 정보 복사', copyAction: '복사', copyHelp: '버전, 플랫폼, 홈 경로를 가린 작업 공간 경로, 민감 정보를 가린 최근 로그를 복사합니다. 보고서는 클립보드에만 기록되며 자동으로 업로드되지 않습니다.', + reportIssueLabel: '이슈 보고', reportIssueHelp: '진단 정보를 첨부해 GitHub 이슈를 여세요 — 더 빨리 답변을 받을 수 있습니다.', reportIssueOpen: '열기', + keyboardShortcuts: '키보드 단축키', keyboardShortcutsHelp: 'Maka가 지원하는 모든 단축키입니다.', keyboardShortcutsOpen: '보기', + checkForUpdates: '업데이트 확인', + checkingForUpdates: '업데이트 확인하는 중…', + updateIdle: '아직 업데이트를 확인하지 않음', + updateNotAvailable: '최신 버전을 사용 중입니다', + updateAvailable: (version) => `v${version} 사용 가능`, + updateDownloading: (version, percent) => `v${version} 다운로드하는 중(${percent}%)`, + updateVerifying: (version) => `v${version}의 릴리스 출처 확인하는 중`, + updateDownloaded: (version) => `v${version} 설치 준비됨`, + updateDownloadedHint: '사이드바 아래쪽에서 다시 시작하면 설치됩니다.', + updateInstalling: (version) => `v${version} 설치하는 중`, + updateFailed: { check: '업데이트 확인 실패', download: '업데이트 다운로드 실패', install: '업데이트 설치 실패' }, + openSourceSummary: 'Apache Maka (incubating) · Apache License 2.0', + sourceCode: '소스 코드', releaseNotes: '릴리스 노트', + }, + password: { copyFailed: '복사 실패', clipboardUnavailable: '클립보드를 사용할 수 없거나 접근이 거부되었습니다.', copying: '복사하는 중', copied: '복사됨', copy: '복사', hide: '숨기기', show: '표시', value: '인증 정보 값' }, + }, } satisfies UiCatalog; export function getSettingsPreferencesCopy(locale: UiLocale): SettingsPreferencesCopy { diff --git a/apps/desktop/src/renderer/locales/shell-copy.ts b/apps/desktop/src/renderer/locales/shell-copy.ts index 037fcae303..68b5541d9a 100644 --- a/apps/desktop/src/renderer/locales/shell-copy.ts +++ b/apps/desktop/src/renderer/locales/shell-copy.ts @@ -74,7 +74,7 @@ type CommandCopy = { }; const STATIC_COMMAND_KEYWORDS: Record = { - 'action:new-chat': ['new', 'chat', 'start', '新', '建', '任务'], + 'action:new-chat': ['new', 'chat', 'start', '新', '建', '任务', '대화', '채팅'], 'action:side-chat': [ 'side', 'chat', @@ -84,24 +84,24 @@ const STATIC_COMMAND_KEYWORDS: Record = { '侧边', '侧聊', '任务', - '追问', + '追问', '질문', ], 'action:new-deep-research': ['deep', 'research', 'explore', 'readonly', '研究', '深度', '探索', '只读'], - 'action:new-scheduled-task': ['plan', 'task', 'schedule', 'new', 'create', '计划', '提醒', '新建', '创建'], - 'action:open-settings': ['settings', 'preferences', '设置', 'options'], - 'action:keyboard-help': ['shortcuts', 'keyboard', 'help', '快捷键', '帮助'], - 'theme:light': ['light', 'theme', '浅色', '主题'], - 'theme:dark': ['dark', 'theme', '深色', 'night', '主题'], - 'theme:auto': ['auto', 'system', 'theme', '跟随', '系统', '主题'], - 'nav:sessions': ['sessions', 'chats', '任务', '会话', '对话', 'left'], - 'nav:automations': ['automations', 'plan', 'task', 'schedule', 'cron', '定时任务', '计划', '提醒'], - 'nav:skills': ['skills', '技能'], - 'nav:mcp': ['mcp', 'server', 'tools', '扩展', '工具'], - 'nav:daily-review': ['daily', 'review', 'today', '每日', '回顾', '今天'], - 'diag:open-workspace': ['workspace', 'folder', 'open', 'finder', '工作区', '文件夹', '目录'], + 'action:new-scheduled-task': ['plan', 'task', 'schedule', 'new', 'create', '计划', '提醒', '新建', '创建', '예약', '일정'], + 'action:open-settings': ['settings', 'preferences', '设置', 'options', '환경설정'], + 'action:keyboard-help': ['shortcuts', 'keyboard', 'help', '快捷键', '帮助', '도움말'], + 'theme:light': ['light', 'theme', '浅色', '主题', '밝은'], + 'theme:dark': ['dark', 'theme', '深色', 'night', '主题', '어두운', '야간'], + 'theme:auto': ['auto', 'system', 'theme', '跟随', '系统', '主题', '자동'], + 'nav:sessions': ['sessions', 'chats', '任务', '会话', '对话', 'left', '세션', '대화'], + 'nav:automations': ['automations', 'plan', 'task', 'schedule', 'cron', '定时任务', '计划', '提醒', '정기 작업', '예약'], + 'nav:skills': ['skills', '技能', '스킬'], + 'nav:mcp': ['mcp', 'server', 'tools', '扩展', '工具', '서버', '도구'], + 'nav:daily-review': ['daily', 'review', 'today', '每日', '回顾', '今天', '오늘'], + 'diag:open-workspace': ['workspace', 'folder', 'open', 'finder', '工作区', '文件夹', '目录', '워크스페이스'], 'diag:open-project-folder': ['project', 'folder', 'open', 'finder', '项目', '目录', '文件夹'], - 'diag:open-skills': ['skills', 'folder', 'open', 'finder', '技能', '文件夹'], - 'diag:export-conversation': ['export', 'markdown', 'copy', 'conversation', '导出', '任务', '剪贴板', 'md'], + 'diag:open-skills': ['skills', 'folder', 'open', 'finder', '技能', '文件夹', '스킬'], + 'diag:export-conversation': ['export', 'markdown', 'copy', 'conversation', '导出', '任务', '剪贴板', 'md', '내보내기', '마크다운'], 'diag:save-conversation-file': [ 'save', 'file', @@ -112,10 +112,10 @@ const STATIC_COMMAND_KEYWORDS: Record = { '文件', '任务', '导出', - 'md', + 'md', '내보내기', '마크다운', ], - 'diag:copy-today-daily-review': ['daily', 'review', 'today', 'copy', 'markdown', '今日', '回顾', '复制', '剪贴板'], - 'diag:paste-today-daily-review': ['daily', 'review', 'paste', 'composer', '今日', '回顾', '粘贴', '输入框'], + 'diag:copy-today-daily-review': ['daily', 'review', 'today', 'copy', 'markdown', '今日', '回顾', '复制', '剪贴板', '데일리 리뷰'], + 'diag:paste-today-daily-review': ['daily', 'review', 'paste', 'composer', '今日', '回顾', '粘贴', '输入框', '데일리 리뷰'], 'diag:save-today-daily-review': [ 'daily', 'review', @@ -127,7 +127,7 @@ const STATIC_COMMAND_KEYWORDS: Record = { '回顾', '保存', '文件', - '导出', + '导出', '데일리 리뷰', '내보내기', ], 'diag:copy-diagnostics': [ 'env', @@ -143,10 +143,10 @@ const STATIC_COMMAND_KEYWORDS: Record = { '日志', '关于', '诊断', - '汇报', + '汇报', '환경', '버전', '로그', '버그', '보고', ], - 'diag:test-network-proxy': ['network', 'proxy', 'test', 'ping', '网络', '代理', '测试', '连接', '诊断'], - 'diag:open-local-memory': ['memory', 'md', 'open', '记忆', '本地', '编辑', 'edit'], + 'diag:test-network-proxy': ['network', 'proxy', 'test', 'ping', '网络', '代理', '测试', '连接', '诊断', '연결'], + 'diag:open-local-memory': ['memory', 'md', 'open', '记忆', '本地', '编辑', 'edit', '메모리'], }; type ShellCopy = { @@ -716,6 +716,105 @@ const EN_STATIC_COMMANDS: Record = { }, }; +const KO_STATIC_COMMANDS: Record = { + 'action:new-chat': { + label: '새 작업', + hint: '새 작업 시작', + group: '동작', + }, + 'action:side-chat': { + label: '사이드 채팅 열기', + platformHint: { apple: '⌥⌘S', other: 'Ctrl+Alt+S' }, + group: '동작', + }, + 'action:new-deep-research': { + label: '새 심층 리서치', + hint: '읽기 전용 탐색', + group: '동작', + }, + 'action:new-scheduled-task': { + label: '새 정기 작업', + hint: '작업 양식 열기', + group: '동작', + }, + 'action:open-settings': { + label: '설정 열기', + platformHint: { apple: '⌘,', other: 'Ctrl+,' }, + group: '동작', + }, + 'action:keyboard-help': { + label: '키보드 단축키 보기', + hint: '?', + group: '동작', + }, + 'theme:light': { label: '테마 · 라이트', group: '테마' }, + 'theme:dark': { label: '테마 · 다크', group: '테마' }, + 'theme:auto': { label: '테마 · 시스템 설정 따름', group: '테마' }, + 'nav:sessions': { label: '사이드바 · 작업', group: '내비게이션' }, + 'nav:automations': { label: '사이드바 · 자동화', group: '내비게이션' }, + 'nav:skills': { label: '열기 · Skills', group: '내비게이션' }, + 'nav:mcp': { label: '열기 · MCP', group: '내비게이션' }, + 'nav:daily-review': { label: '열기 · 데일리 리뷰', group: '내비게이션' }, + 'diag:open-workspace': { + label: '작업 공간 폴더 열기', + hint: 'Finder', + group: '진단', + }, + 'diag:open-project-folder': { + label: '프로젝트 폴더 열기', + hint: 'Finder', + group: '진단', + }, + 'diag:open-skills': { + label: 'Skills 폴더 열기', + hint: 'Finder', + group: '진단', + }, + 'diag:export-conversation': { + label: '작업을 Markdown으로 복사', + hint: '클립보드에 복사', + group: '진단', + }, + 'diag:save-conversation-file': { + label: '작업을 .md 파일로 저장', + hint: '시스템 저장 대화상자 사용', + group: '진단', + }, + 'diag:copy-today-daily-review': { + label: "오늘의 리뷰를 Markdown으로 복사", + hint: '클립보드에 복사', + group: '진단', + }, + 'diag:paste-today-daily-review': { + label: "오늘의 리뷰를 입력창에 붙여 넣기", + hint: '클립보드를 거치지 않음', + group: '진단', + }, + 'diag:save-today-daily-review': { + label: "오늘의 리뷰를 .md 파일로 저장", + hint: '시스템 저장 대화상자 사용', + group: '진단', + }, + 'diag:copy-diagnostics': { + label: '진단 정보 복사', + platformHint: { + apple: '⇧⌘D · 민감 정보를 가린 로그 · 클립보드에만', + other: 'Ctrl+Shift+D · 민감 정보를 가린 로그 · 클립보드에만', + }, + group: '진단', + }, + 'diag:test-network-proxy': { + label: '현재 네트워크 프록시 테스트', + hint: '설정을 열지 않고 진단', + group: '진단', + }, + 'diag:open-local-memory': { + label: '로컬 MEMORY.md 열기', + hint: '시스템 편집기', + group: '진단', + }, +}; + const ZH_SETTINGS_SECTIONS: Record = { general: '通用', appearance: '外观', @@ -754,6 +853,25 @@ const EN_SETTINGS_SECTIONS: Record = { about: 'About', }; +const KO_SETTINGS_SECTIONS: Record = { + general: '일반', + appearance: '모양', + projects: '작업 공간', + models: '모델', + subagents: '하위 에이전트', + usage: '사용량', + 'archived-tasks': '보관된 작업', + 'import-tasks': '작업 가져오기', + memory: '메모리', + 'daily-review': '데일리 리뷰', + 'bot-chat': '원격 접속', + search: '웹 검색', + data: '데이터', + permissions: '권한과 기능 상태', + health: '상태 점검', + about: '앱 정보', +}; + const SHELL_COPY_BY_LOCALE = { 'zh-CN': { navigation: { settings: '设置' }, @@ -2310,6 +2428,557 @@ const SHELL_COPY_BY_LOCALE = { resizeWorkbar: 'Resize task workbar', }, }, + ko: { + navigation: { settings: '설정' }, + actions: { retry: '다시 시도' }, + paths: { + workspace: '작업 공간', + project: '프로젝트 폴더', + skills: 'Skills 폴더', + }, + errors: { + messageRead: '작업 내용을 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.', + messageRefresh: '작업 내용을 새로고침하지 못했습니다. 잠시 후 다시 시도해 주세요.', + openPath: (path: string) => `${path} 열기에 실패했습니다. 잠시 후 다시 시도해 주세요.`, + workspaceUnavailableTitle: '작업 디렉터리를 사용할 수 없음', + workspaceUnavailableDescription: + '작업 디렉터리가 없거나 접근할 수 없습니다. 새 작업에 사용할 올바른 폴더를 선택하세요.', + }, + chatActions: { + newConversation: '새 작업', + sendFailedTitle: '메시지를 보내지 못함', + sendFailedFallback: '메시지를 보내지 못했습니다. 잠시 후 다시 시도해 주세요.', + skillInvocationBlockedTitle: 'Skill 호출에 실패해 메시지를 보내지 못함', + skillInvocationBlockedDescription: (items) => `${items.join(', ')}. 선택을 조정한 뒤 다시 시도해 주세요.`, + skillInvocationFailedTitle: '일부 Skill을 호출하지 못했습니다', + skillInvocationFailedDescription: (items) => + `${items.join(', ')}. 나머지 Skill은 호출되었습니다.`, + skillInvocationFailureReason: { + invalid_name: '잘못된 이름', + not_found: '찾을 수 없음', + disabled: '꺼짐', + host_incompatible: '필요한 도구를 사용할 수 없음', + resolution_failed: '해석 실패', + too_many_requests: '서로 다른 Skill 호출 요청이 50개를 넘음', + }, + responseFailedTitle: '응답 실패', + responseFailedFallback: '작업 동작을 수행하지 못했습니다. 잠시 후 다시 시도해 주세요.', + refreshFailedTitle: '작업 새로고침 실패', + sessionStartFailedTitle: '작업 시작 실패', + sessionStartFailedFallback: '작업을 시작하지 못했습니다. 잠시 후 다시 시도해 주세요.', + }, + projectActions: { + currentProject: '현재 프로젝트', + readPathFailedTitle: '프로젝트 경로 읽기 실패', + readPathFailedFallback: '프로젝트 경로를 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.', + selectDirectoryFailedTitle: '작업 디렉터리 선택 실패', + selectedPathUnreadable: '선택한 경로가 없거나 읽을 수 없습니다.', + directorySwitchedTitle: '작업 디렉터리 변경됨', + projectUpdateFailedTitle: '프로젝트 업데이트 실패', + projectUpdateFailedFallback: '프로젝트를 업데이트하지 못했습니다. 잠시 후 다시 시도해 주세요.', + catalogUnavailable: 'Runtime Host를 사용할 수 없음', + retryCatalog: '불러오기 다시 시도', + remoteDirectoryTitle: (host: string) => `${host}에 프로젝트 추가`, + remoteDirectoryBreadcrumbs: '현재 폴더', + remoteDirectoryHome: '홈', + remoteDirectoryEmpty: '이 위치에 폴더 없음', + remoteDirectorySelect: '이 폴더 추가', + remoteDirectoryCancel: '취소', + remoteDirectoryRetry: '다시 시도', + remoteDirectoryLoading: '폴더 불러오는 중…', + remoteDirectoryShowHidden: '숨김 폴더 표시', + remoteDirectoryHideHidden: '숨김 폴더 숨기기', + runtimeHostReadiness: { + connecting: '연결하는 중', + reconnecting: '다시 연결하는 중', + unavailable: '사용할 수 없음', + }, + openFailedTitle: (path: string) => `${path} 열기 실패`, + openPathLabels: { + workspace: '작업 공간 폴더', + skills: 'Skills 폴더', + memory: '메모리 폴더', + project: '프로젝트 폴더', + }, + openPathFailures: { + 'unknown-key': '알 수 없는 작업 공간 폴더입니다.', + 'not-allowed': '경로가 Maka에서 열 수 있는 폴더 밖에 있습니다.', + missing: '폴더가 없습니다.', + 'not-a-directory': '대상이 폴더가 아닙니다.', + 'open-failed': '시스템에서 폴더를 열지 못했습니다.', + unknown: '폴더를 열지 못했습니다.', + }, + }, + commandActions: { + connectionVerified: (name: string) => `연결 확인됨 · ${name}`, + connectionLatency: (latency: number | string, model?: string) => + `지연 시간 ${latency}ms${model ? ` · ${model}` : ''}`, + connectionTestFailed: (name: string) => `연결 테스트 실패 · ${name}`, + testErrorTitle: '테스트 오류', + connectionUnavailable: '연결 테스트를 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.', + connectionFailures: { + rateLimit: '계정 또는 모델 서비스의 속도 제한을 초과했습니다. 잠시 후 다시 시도해 주세요.', + timeout: '요청 시간 초과. 네트워크 또는 프록시를 확인한 뒤 다시 시도해 주세요.', + auth: '인증 실패. 모델 키, 구독 로그인 또는 인증 정보를 확인한 뒤 다시 시도해 주세요.', + network: '네트워크 오류. 네트워크 또는 프록시를 확인한 뒤 다시 시도해 주세요.', + provider: '모델 서비스가 오류를 반환했습니다. 잠시 후 다시 시도해 주세요.', + unknown: '연결 테스트에 실패했습니다. 잠시 후 다시 시도해 주세요.', + }, + setDefaultSuccess: (name: string) => `기본값으로 설정됨 · ${name}`, + setDefaultFailedTitle: '기본값 변경 실패', + setDefaultFallback: '기본 모델을 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + newConversation: '새 작업', + conversationCopiedTitle: '작업이 Markdown으로 복사됨', + lineCount: (lines: number) => `${lines}줄 · Notion / Obsidian / GitHub에 바로 붙여 넣을 수 있음`, + copyFailedTitle: '복사 실패', + clipboardUnavailable: '클립보드를 사용할 수 없음', + conversationSavedTitle: '작업 저장됨', + saveSummary: (lines: number, fileName: string) => `${lines}줄 · ${fileName} 파일로 저장됨`, + saveFailedTitle: '저장 실패', + invalidExport: '내보낼 내용이 올바르지 않습니다', + writeFailed: '선택한 위치에 쓰지 못했습니다', + exportFallback: '작업을 내보내지 못했습니다. 잠시 후 다시 시도해 주세요.', + memoryOpenFailedTitle: 'MEMORY.md 열기 실패', + openFailedTitle: '열기 실패', + memoryOpenFallback: 'MEMORY.md를 열지 못했습니다. 잠시 후 다시 시도해 주세요.', + today: '오늘', + reviewCopiedTitle: "오늘의 리뷰가 Markdown으로 복사됨", + reviewSummary: (sessions: number, requests: number) => `작업 ${sessions}개 · 요청 ${requests}개`, + reviewCopyFallback: "오늘의 리뷰를 사용할 수 없거나 클립보드 접근이 거부되었습니다.", + reviewPastedTitle: "오늘의 리뷰가 입력창에 추가됨", + reviewCopied: (label: string) => `${label} 리뷰 복사됨`, + reviewPasted: (label: string) => `${label} 리뷰가 입력창에 추가됨`, + reviewSaved: (label: string) => `${label} 리뷰 저장됨`, + reviewSaveFallback: '데일리 리뷰를 저장하지 못했습니다. 잠시 후 다시 시도해 주세요.', + pasteFailedTitle: '붙여 넣기 실패', + reviewUnavailable: "오늘의 리뷰를 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.", + diagnosticsCopiedTitle: '진단 정보 복사됨', + diagnosticsCopiedDescription: '내용을 확인한 뒤 이슈 보고서에 붙여 넣으세요', + clipboardDenied: '클립보드를 사용할 수 없거나 접근이 거부되었습니다', + networkPassedTitle: '네트워크 프록시 테스트 통과', + networkFailedTitle: '네트워크 프록시 테스트 실패', + genericTestFailedTitle: '테스트 실패', + networkTestFallback: '네트워크 프록시 테스트를 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.', + }, + sessionRowActions: { + actionFallback: '작업 동작을 수행하지 못했습니다. 잠시 후 다시 시도해 주세요.', + flagFailedTitle: '작업 깃발 표시 실패', + unflagFailedTitle: '깃발 제거 실패', + archiveFailedTitle: '작업 보관 실패', + unarchiveFailedTitle: '작업 복원 실패', + renameFailedTitle: '작업 이름 변경 실패', + deleteFailedTitle: '작업 삭제 실패', + currentConversation: '현재 작업', + deleteTitle: (name: string) => `"${name}" 삭제`, + deleteDescription: + '작업과 모든 메시지가 디스크에서 영구적으로 제거됩니다. 이 동작은 되돌릴 수 없습니다.', + deleteLabel: '삭제', + cancelLabel: '취소', + deletedTitle: (name: string) => `${name} 삭제됨`, + deleteRestoredTitle: (name: string) => `${name}: 복원되어 유지됨`, + deleteSubtaskNote: () => '일반 하위 작업은 유지되며 보관된 작업으로 이동합니다.', + deleteSubtaskNoteUncertain: () => + '일반 하위 작업이 있으면 유지되며 보관된 작업으로 이동합니다.', + deletedSubtaskNote: (count: number) => + `하위 작업 ${count}개를 보관된 작업으로 이동했습니다`, + bulkArchiveDescription: '보관된 작업은 설정 › 활동에서 계속 볼 수 있습니다.', + bulkArchivedTitle: (count: number) => `${count}개 작업을 보관했습니다`, + bulkArchiveFailedTitle: '일부 작업을 보관하지 못했습니다', + bulkFailedBody: (count: number) => `그중 ${count}개는 처리되지 않았습니다.`, + }, + skillActions: { + refreshSkillsFailedTitle: 'Skills 새로고침 실패', + refreshSkillsFallback: 'Skills를 새로고침하지 못했습니다. 잠시 후 다시 시도해 주세요.', + refreshSourcesFailedTitle: 'Skill 소스 새로고침 실패', + refreshSourcesFallback: 'Skill 소스를 새로고침하지 못했습니다. 잠시 후 다시 시도해 주세요.', + refreshBundledFailedTitle: '기본 제공 Skills 새로고침 실패', + refreshBundledFallback: '기본 제공 Skills를 새로고침하지 못했습니다. 잠시 후 다시 시도해 주세요.', + installBundledFailedTitle: '기본 제공 Skill 설치 실패', + installBundledFallback: '기본 제공 Skill을 설치하지 못했습니다. 잠시 후 다시 시도해 주세요.', + installedBundledTitle: '기본 제공 Skill 설치됨', + installedDescription: (id: string) => `${id}/SKILL.md가 현재 작업 공간에 추가되었습니다.`, + importSourceFailedTitle: 'Skill 소스 가져오기 실패', + importSourceFallback: 'Skill 소스를 가져오지 못했습니다. 잠시 후 다시 시도해 주세요.', + importedSourceTitle: 'Skill 소스 가져오기 완료', + installFailedTitle: 'Skill 설치 실패', + installFallback: 'Skill을 설치하지 못했습니다. 잠시 후 다시 시도해 주세요.', + installedTitle: 'Skill 설치됨', + previewFailedTitle: 'Skill 업데이트 미리 보기 실패', + previewFallback: 'Skill 업데이트를 미리 보지 못했습니다. 잠시 후 다시 시도해 주세요.', + updateFailedTitle: 'Skill 업데이트 실패', + updateFallback: 'Skill을 업데이트하지 못했습니다. 잠시 후 다시 시도해 주세요.', + updatedTitle: 'Skill 업데이트됨', + forceUpdatedTitle: 'Skill을 업데이트로 덮어씀', + updatedDescription: (id: string) => `${id}/SKILL.md가 소스 라이브러리 버전으로 업데이트되었습니다.`, + toggleFailedTitle: 'Skill 상태 변경 실패', + toggleFallback: 'Skill 상태를 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + enabledTitle: 'Skill 켜짐', + disabledTitle: 'Skill 꺼짐', + pinnedTitle: 'Skill이 컨텍스트에 고정됨', + unpinnedTitle: 'Skill 고정 해제됨', + runtimeDescription: (name: string) => `현재 프로젝트의 ${name} 런타임 상태가 업데이트되었습니다.`, + deleteFailedTitle: 'Skill 삭제 실패', + deleteFallback: 'Skill을 삭제하지 못했습니다. 잠시 후 다시 시도해 주세요.', + deletedTitle: 'Skill 삭제됨', + deletedDescription: (id: string) => `${id} 항목이 제거되었습니다.`, + openFailedTitle: 'Skill 열기 실패', + openFallback: 'Skill을 열지 못했습니다. 잠시 후 다시 시도해 주세요.', + openFailures: { + invalid_id: '허용되지 않는 Skill 이름입니다.', + missing: '해당하는 SKILL.md를 찾을 수 없습니다.', + blocked_path: 'Skill 경로가 작업 공간의 skills 폴더 밖에 있어 열기가 차단되었습니다.', + not_file: '대상이 열 수 있는 SKILL.md 파일이 아닙니다.', + not_directory: '대상이 열 수 있는 폴더가 아닙니다.', + open_failed: '시스템에서 파일을 열지 못했습니다.', + }, + sourceFailures: { + invalid_skill: '올바른 SKILL.md 파일을 선택하세요.', + already_exists: '소스 라이브러리에 같은 이름의 Skill이 이미 있습니다.', + blocked_path: '이 파일 경로는 가져올 수 없습니다.', + write_failed: '소스 라이브러리에 쓰지 못했습니다. 파일 권한을 확인해 주세요.', + cancelled: '취소되었습니다.', + }, + installFailures: { + not_found: '이 Skill 소스를 찾을 수 없습니다.', + already_exists: '이 작업 공간에 같은 이름의 Skill이 이미 있습니다.', + blocked_path: '대상 경로에 쓸 수 없습니다.', + write_failed: '작업 공간에 쓰지 못했습니다. 파일 권한을 확인해 주세요.', + }, + updateFailures: { + not_managed: '이 Skill은 관리되는 소스에서 온 것이 아닙니다.', + source_missing: '소스 라이브러리에서 해당 소스를 찾을 수 없습니다.', + local_modified: + '작업 공간의 사본이 수정되었습니다. 업데이트하기 전에 로컬 파일과 소스 파일을 열어 비교하세요.', + metadata_error: 'Skill 메타데이터가 올바르지 않아 안전하게 업데이트할 수 없습니다.', + blocked_path: '대상 경로에 쓸 수 없습니다.', + write_failed: '작업 공간에 쓰지 못했습니다. 파일 권한을 확인해 주세요.', + }, + previewFailures: { + not_managed: '이 Skill은 관리되는 소스에서 온 것이 아닙니다.', + source_missing: '소스 라이브러리에서 해당 소스를 찾을 수 없습니다.', + metadata_error: 'Skill 메타데이터가 올바르지 않아 안전하게 미리 볼 수 없습니다.', + blocked_path: '대상 경로를 읽을 수 없습니다.', + read_failed: 'Skill 내용을 읽지 못했습니다. 파일 권한을 확인해 주세요.', + }, + deleteFailures: { + not_found: '현재 작업 공간에서 이 Skill을 찾을 수 없습니다.', + blocked_path: '이 Skill 경로는 삭제할 수 없습니다.', + blocked_scope: '프로젝트 Skills는 저장소에서 관리합니다. 대신 프로젝트에서 삭제해 주세요.', + delete_failed: 'Skill을 삭제하지 못했습니다. 파일 권한을 확인해 주세요.', + }, + runtimeFailures: { + not_found: '현재 작업 공간에서 이 Skill을 찾을 수 없습니다.', + blocked_path: 'Skill 상태 경로에 쓸 수 없습니다.', + state_error: '이 작업 공간의 Skill 상태 파일이 올바르지 않아 먼저 고쳐야 합니다.', + write_failed: '현재 프로젝트의 Skill 상태를 쓰지 못했습니다. 파일 권한을 확인해 주세요.', + }, + }, + sessionSettingsActions: { + bypassConfirmTitle: '전체 접근으로 전환할까요?', + bypassConfirmDescription: + "로컬 도구가 Maka의 보호 계층을 거치지 않고 파일을 직접 읽고 쓰며 네트워크에 직접 접근합니다. 완전히 신뢰하는 작업이나 실행 환경으로 이미 격리된 작업에만 사용하세요.", + bypassConfirmLabel: '전체 접근 켜기', + bypassCancelLabel: '자동 유지', + permissionFailedTitle: '권한 모드 변경 실패', + permissionFallback: '권한 모드를 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + attachmentIngestBlocked: { + item_too_large: '첨부 파일 하나가 크기 제한을 넘습니다.', + items_invalid: '첨부 파일 목록이 올바르지 않습니다. 파일을 다시 선택해 다시 보내 주세요.', + count_limit: '메시지 하나에 첨부 파일은 최대 8개까지입니다.', + duplicate_source: '첨부 파일 원본이 중복되었습니다. 같은 파일을 두 번 추가하지 마세요.', + total_size_exceeded: '첨부 파일 전체 크기가 제한을 넘습니다.', + source_expired: '첨부 파일 원본이 만료되었거나 올바르지 않습니다. 파일을 다시 선택해 다시 보내 주세요.', + }, + modelFailedTitle: '모델 변경 실패', + modelFallback: '모델을 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + thinkingFailedTitle: '사고 수준 변경 실패', + thinkingFallback: '사고 수준을 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + }, + goalDialog: { + title: '목표 설정', + description: 'Maka는 목표를 달성하거나, 불가능하다고 판단하거나, 아래 예산에 도달할 때까지 턴마다 스스로 이어서 진행합니다. 입력창 위에서 언제든지 멈출 수 있습니다.', + conditionLabel: '완료 조건', + conditionDescription: '무엇을 완료로 볼지 한 문장으로 적으세요. Maka가 매 턴이 끝날 때마다 확인합니다.', + conditionPlaceholder: '예: 모든 테스트가 통과하고 lint 경고가 없음', + maxIterationsLabel: '최대 턴 수', + maxIterationsDescription: '비워 두면 기본값을 사용합니다.', + maxIterationsInvalid: (max) => `1부터 ${max}까지의 정수를 입력하거나 비워 두세요.`, + tokenBudgetLabel: '토큰 예산', + tokenBudgetDescription: '비워 두면 토큰 상한이 없습니다.', + tokenBudgetInvalid: (min) => `${min} 이상의 정수를 입력하거나 비워 두세요.`, + cancel: '취소', + close: '닫기', + submit: '시작', + failedFallback: '목표를 설정하지 못했습니다. 다시 시도해 주세요.', + statusLabels: { + active: '진행 중', + waiting: '대기 중', + paused: '일시 중지됨', + achieved: '달성됨', + impossible: '불가능', + cleared: '지워짐', + stalled: '정체됨', + budget_limited: '토큰 예산 도달', + max_iterations: '최대 턴 수 도달', + }, + reconciledMatching: (condition, status) => + `다시 연결한 뒤의 현재 목표: “${condition}” (${status}). 요청과 일치하지만, 중단된 요청이 실제로 반영되었다는 뜻은 아닙니다.`, + reconciledDifferent: (condition, status) => + `다시 연결한 뒤의 현재 목표: “${condition}” (${status}). 이 요청과 다릅니다.`, + reconciledNoGoal: '다시 연결한 뒤의 현재 상태: 목표를 찾을 수 없습니다.', + reconciliationUnavailable: '연결이 끊겨 현재 목표를 아직 확인할 수 없습니다. 닫았다가 다시 열어 확인해 주세요. 이 대화상자는 두 번 제출되지 않습니다.', + }, + errorBoundary: { + copyPending: '복사하는 중…', + copied: '복사됨', + copyFailed: '복사 실패', + copyReport: '진단 정보 복사', + title: 'Maka 렌더러가 비정상 종료되었습니다', + description: + '처리되지 않은 React 오류를 포착했습니다. 다시 시도해 이 오류 화면을 닫거나, 다시 불러와 창 전체를 새로고침해 주세요. 이슈를 전달하기 전에 진단 정보를 복사하세요.', + retry: '다시 시도', + reload: '다시 불러오기', + clipboardFailure: '클립보드를 사용할 수 없거나 접근이 거부되었습니다. 잠시 후 다시 시도해 주세요.', + }, + commandPalette: { + label: '명령 팔레트', + searchLabel: '명령 팔레트 검색', + placeholder: '명령, 설정, 작업 검색…', + closeLabel: '명령 팔레트 닫기', + resultsLabel: '명령 팔레트 결과', + emptyTitle: '일치하는 명령 없음', + emptyDescription: '다른 검색어를 입력하거나 Esc를 눌러 닫으세요.', + selectHint: '선택', + runHint: '실행', + closeHint: '닫기', + current: '현재', + groups: { + settings: '설정', + permissions: '권한', + connections: '연결', + conversations: '작업', + }, + staticKeywords: STATIC_COMMAND_KEYWORDS, + commands: KO_STATIC_COMMANDS, + settingsSections: KO_SETTINGS_SECTIONS, + permissionModes: { + explore: { + label: '권한 · 읽기 전용', + hint: '직접 읽고 검색합니다. 쓰기와 네트워크 접근은 확인을 받습니다', + }, + ask: { + label: '권한 · 자동', + hint: "Maka의 보호 계층 안에서 실행합니다. 현재 권한을 넘어서는 동작은 먼저 묻습니다", + }, + bypass: { + label: '권한 · 전체 접근', + hint: "Maka의 보호 계층을 거치지 않고 파일과 네트워크에 직접 접근합니다", + }, + }, + settingsCommand: (section: string) => `설정 · ${section}`, + testDefaultConnection: (name: string) => `기본 연결 테스트 · ${name}`, + setDefaultConnection: (name: string) => `기본값으로 설정 · ${name}`, + testConnection: (name: string) => `연결 테스트 · ${name}`, + settingsKeywords: (section: SettingsSection, label: string) => [section, label, 'settings', '설정'], + permissionKeywords: (mode: PermissionMode) => [mode, 'permission', 'mode', '권한', '모드'], + connectionKeywords: (action: 'default' | 'test', name: string, providerType: string) => [ + action, + 'connection', + '연결', + '기본', + '테스트', + name, + providerType, + ], + }, + keyboardHelp: { + title: '키보드 단축키', + sections: [ + { + heading: '일반', + rows: [ + { + keys: ['⌘', 'K'], + description: '명령 팔레트 열기(작업, 설정, 테마 등)', + }, + { keys: ['?'], description: '이 단축키 패널 열기 또는 닫기' }, + { keys: ['⌘', 'N'], description: '새 작업 만들기' }, + { keys: ['⌘', ','], description: '설정 열기' }, + { + keys: ['⌘', 'Shift', 'D'], + description: '현재 컨텍스트의 진단 정보 복사', + }, + { keys: ['Esc'], description: '현재 대화상자 닫기' }, + ], + }, + { + heading: '입력창', + rows: [ + { keys: ['Enter'], description: '메시지 보내기' }, + { keys: ['Shift', 'Enter'], description: '줄 바꿈 넣기' }, + { + keys: ['Alt', 'Enter'], + description: '줄 바꿈 넣기(대체 키)', + }, + ], + }, + { + heading: '작업 목록', + rows: [ + { + keys: ['Tab'], + description: '작업과 내비게이션 사이에서 포커스 이동', + }, + { + keys: ['↑', '↓'], + description: '포커스된 작업 사이 이동', + }, + { + keys: ['Home', 'End'], + description: '목록의 맨 위 또는 맨 아래로 이동', + }, + { keys: ['Enter'], description: '포커스된 작업 열기' }, + { + keys: ['Delete'], + description: '삭제 확인 창 열기(확인 없이 삭제하지 않음)', + }, + { + keys: ['F'], + description: '작업 검색으로 포커스 이동(Esc를 누르면 지워짐)', + }, + ], + }, + { + heading: '채팅', + rows: [ + { + keys: ['Tab'], + description: '도구 활동과 복사 버튼으로 포커스 이동', + }, + { + keys: ['Space', 'Enter'], + description: '도구 호출 펼치기 또는 접기', + }, + ], + }, + { + heading: '패널 크기 조절', + rows: [ + { keys: ['Tab'], description: '왼쪽 또는 오른쪽 분할선으로 포커스 이동' }, + { + keys: ['←', '→'], + description: '작업 목록 너비 조절(±10px)', + }, + { + keys: ['Shift', '←', '→'], + description: '빠르게 조절(±50px)', + }, + { + keys: ['Home', 'End'], + description: '최소 또는 최대 너비로 바로 이동', + }, + ], + }, + ], + }, + chrome: { + windowActions: '창 바로 가기', + searchConversations: '작업 검색', + expandSidebar: '사이드바 펼치기', + collapseSidebar: '사이드바 접기', + newTask: '새 작업', + expandWorkbar: '작업 워크바 펼치기', + collapseWorkbar: '작업 워크바 접기', + workspaceActions: '작업 공간 동작', + }, + app: { + returnToWorkHub: 'WorkHub로 돌아가기', + loadingWorkbarLabel: '작업 워크바 불러오는 중', + loadingWorkbar: '작업 워크바 불러오는 중…', + useSkillPrompt: (skillName: string) => `${skillName} Skill 사용: `, + newConversation: '새 작업', + compactSuccessTitle: '컨텍스트 압축됨', + compactSuccessDescription: '이전 컨텍스트를 체크포인트 요약으로 대체했습니다.', + compactStartedTitle: '컨텍스트 압축하는 중', + compactStartedDescription: '이전 컨텍스트를 체크포인트로 요약하는 중입니다.', + compactUnchangedTitle: '압축할 내용 없음', + compactUnchangedDescription: '작업이 이미 최신 체크포인트를 사용하고 있습니다.', + compactErrorTitle: '압축 실패', + compactErrorFallback: '작업을 압축하지 못했습니다. 잠시 후 다시 시도해 주세요.', + slashCommands: { + compact: { name: '컨텍스트 압축', description: '현재 작업은 유지하면서 이전 기록을 압축합니다' }, + graph: { name: 'Graph 사용', description: 'Graph를 확인하거나 전환하거나 한 번 실행합니다' }, + side: { name: '사이드 채팅 열기', description: '사이드 패널에서 특정 주제를 시작합니다' }, + swarm: { name: 'Swarm 사용', description: 'Swarm을 확인하거나 전환하거나 한 번 실행합니다' }, + }, + sideChatUnavailableTitle: '사이드 채팅을 아직 사용할 수 없음', + sideChatUnavailableDescription: + '/side를 사용하기 전에 메인 작업에서 메시지를 보내세요.', + sideChatContextPendingTitle: '대기 중인 컨텍스트를 먼저 처리하세요', + sideChatContextPendingDescription: + '입력창에 아직 첨부 파일, 인용, 파일 멘션이 있습니다. /side를 사용하기 전에 보내거나 제거하세요.', + resumeStartedTitle: '이 턴을 이어서 진행하는 중', + resumeStartedDescription: '마지막으로 완료된 실행 경계부터 이어서 진행합니다', + resumeFailedTitle: '이어서 진행 실패', + resumeFailedFallback: '이 턴을 이어서 진행하지 못했습니다. 작업 상태를 확인한 뒤 다시 시도해 주세요.', + goalClearFailedTitle: '목표 중지 실패', + goalClearFailedFallback: '목표가 아직 실행 중일 수 있습니다. 지금 다시 시도해 주세요.', + goalPauseFailedTitle: '목표 일시 중지 실패', + goalPauseFailedFallback: '목표가 아직 계속 진행 중일 수 있습니다. 지금 다시 시도해 주세요.', + goalResumeFailedTitle: '목표 재개 실패', + goalResumeFailedFallback: '목표가 아직 일시 중지된 상태입니다. 다시 시도해 주세요.', + appearanceLoadErrorTitle: '모양 설정 불러오기 실패', + appearanceLoadErrorFallback: '모양 설정을 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.', + memoryRefreshErrorTitle: '로컬 메모리 상태 새로고침 실패', + memoryLoadErrorTitle: '로컬 메모리 상태 불러오기 실패', + memoryErrorFallback: '로컬 메모리 상태를 새로고침하지 못했습니다. 잠시 후 다시 시도해 주세요.', + openModelSettings: '설정 열기 · 모델', + configureModelsOnHost: (hostName: string) => + `작업을 시작하기 전에 ${hostName}에서 모델 연결을 설정하세요.`, + sidebarCollapsed: '사이드바가 접혀 있음', + resizeConversationList: '작업 목록 크기 조절', + skipErrorTitle: '온보딩 건너뛰기 실패', + tryAgainLater: '잠시 후 다시 시도해 주세요.', + loading: '불러오는 중', + goToModels: '모델로 이동', + boundaryUnreadableTitle: '이 작업의 권한 읽기 실패', + boundaryUnreadableDetail: + '권한을 읽을 수 있을 때까지 여기에 입력할 수 없습니다. 다시 시도하거나 다른 작업으로 전환해 주세요.', + boundaryUnreadableRetry: '다시 시도', + boundaryUnreadableRetrying: '다시 시도하는 중…', + permissionModeStreaming: + '이 작업의 응답을 스트리밍하는 중입니다. 완료될 때까지 기다린 뒤 권한 모드를 변경하세요.', + permissionModeRunning: '이 작업이 실행 중입니다. 완료될 때까지 기다린 뒤 권한 모드를 변경하세요.', + permissionModeWaiting: '도구 호출이 확인을 기다리고 있습니다. 먼저 응답한 뒤 권한 모드를 변경하세요.', + modeChangeLoading: '이 작업을 아직 불러오는 중입니다. 잠시 후 모드를 변경할 수 있습니다.', + modeChanging: '모드를 변경하는 중입니다. 완료될 때까지 기다린 뒤 계속하세요.', + modeChangeStreaming: '이 작업의 응답을 스트리밍하는 중입니다. 완료될 때까지 기다린 뒤 모드를 변경하세요.', + modeChangeRunning: '이 작업이 실행 중입니다. 완료될 때까지 기다린 뒤 모드를 변경하세요.', + modeChangeWaiting: '도구 호출이 확인을 기다리고 있습니다. 먼저 응답한 뒤 모드를 변경하세요.', + goalTurnActive: + '목표는 다음 턴부터 적용됩니다. 이 턴이 끝날 때까지 기다린 뒤 설정하세요.', + planModeFailedTitle: 'Plan Mode 변경 실패', + planModeFallback: 'Plan Mode를 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + orchestrationModeFailedTitle: '오케스트레이션 모드 변경 실패', + orchestrationModeFallback: '오케스트레이션 모드를 변경하지 못했습니다. 잠시 후 다시 시도해 주세요.', + planModeExitPendingTitle: '현재 계획을 포기할까요?', + planModeExitPendingDescription: (title: string) => + `“${title}” 계획이 아직 승인되지 않았습니다. Plan Mode를 나가면 기록은 보존되고 이 계획은 포기됨으로 표시됩니다.`, + planModeExitConfirm: '포기하고 나가기', + planModeExitCancel: '계속 계획하기', + planModeExecutionActiveTitle: '계획이 아직 실행 중입니다', + planModeExecutionActiveDescription: '계획을 수정하려면 진행 중인 실행을 중단한 뒤 Plan Mode에 들어가세요.', + swarmModeEnabledTitle: 'Swarm Mode 켜짐', + swarmModeDisabledTitle: 'Swarm Mode 꺼짐', + swarmModeStatusDescription: '/swarm on, /swarm off를 사용하거나, 한 턴에만 쓰려면 /swarm <작업>을 사용하세요.', + graphModeEnabledTitle: 'Graph Mode 켜짐', + graphModeDisabledTitle: 'Graph Mode 꺼짐', + graphModeStatusDescription: '/graph on, /graph off를 사용하거나, 한 턴에만 쓰려면 /graph <작업>을 사용하세요.', + graphHistoryTitle: 'Graph 기록', + graphHistoryDescription: 'Agent Graph 패널의 실행 메뉴에서 기록을 확인하세요.', + resizeWorkbar: '작업 워크바 크기 조절', + }, + }, } satisfies UiCatalog; export function getShellCopy(locale: UiLocale): ShellCopy { diff --git a/apps/desktop/src/renderer/locales/shell-remaining-copy.ts b/apps/desktop/src/renderer/locales/shell-remaining-copy.ts index 17fb805908..f5fe4f92ff 100644 --- a/apps/desktop/src/renderer/locales/shell-remaining-copy.ts +++ b/apps/desktop/src/renderer/locales/shell-remaining-copy.ts @@ -251,10 +251,90 @@ const enCopy: ShellRemainingCopy = { }, }; +const koCopy: ShellRemainingCopy = { + scheduledTaskActions: { + refreshFailed: "작업 새로고침 실패", + refreshFallback: "정기 작업을 새로고침하지 못했습니다. 잠시 후 다시 시도해 주세요.", + created: "정기 작업 생성됨", + createFailed: "작업 생성 실패", + createFallback: "정기 작업을 생성하지 못했습니다. 잠시 후 다시 시도해 주세요.", + createIncognitoBlocked: + "시크릿 모드가 켜져 있는 동안에는 정기 작업을 생성할 수 없습니다.", + saved: "정기 작업 저장됨", + saveFailed: "작업 저장 실패", + saveFallback: "정기 작업을 저장하지 못했습니다. 잠시 후 다시 시도해 주세요.", + enabled: "정기 작업 켜짐", + paused: "정기 작업 일시 중지됨", + updateFailed: "작업 업데이트 실패", + updateFallback: "정기 작업을 업데이트하지 못했습니다. 잠시 후 다시 시도해 주세요.", + triggered: "정기 작업 실행됨", + triggerFailed: "작업 실행 실패", + triggerFallback: + "정기 작업을 실행하지 못했습니다. 잠시 후 다시 시도해 주세요.", + snoozed: "10분 연기됨", + snoozeFailed: "작업 연기 실패", + snoozeFallback: "정기 작업을 연기하지 못했습니다. 잠시 후 다시 시도해 주세요.", + task: "정기 작업", + clearTitle: (name) => `“${name}”의 실행 기록을 지울까요?`, + clearDescription: + "정기 작업은 그대로 유지됩니다. 최근 실행 기록과 상태만 지워집니다.", + clear: "기록 지우기", + cancel: "취소", + cleared: "실행 기록 지워짐", + clearFailed: "기록 지우기 실패", + clearFallback: + "정기 작업 기록을 지우지 못했습니다. 잠시 후 다시 시도해 주세요.", + deleteTitle: (name) => `“${name}” 삭제할까요?`, + deleteDescription: + "작업과 최근 실행 기록이 삭제됩니다. 이 동작은 되돌릴 수 없습니다.", + delete: "삭제", + deleted: "정기 작업 삭제됨", + deleteFailed: "작업 삭제 실패", + deleteFallback: "정기 작업을 삭제하지 못했습니다. 잠시 후 다시 시도해 주세요.", + }, + dailyReview: { + yesterday: "어제", + today: "오늘", + followSettings: "설정 따름", + unavailable: "데일리 리뷰를 생성할 수 없음", + historyUnavailable: "데일리 리뷰 기록을 사용할 수 없음", + archiveMissing: "데일리 리뷰 보고서를 찾을 수 없음", + settingsUnavailable: "데일리 리뷰 설정을 사용할 수 없음", + }, + connections: { + refreshFailed: "모델 연결 새로고침 실패", + refreshFallback: + "모델 연결을 일시적으로 사용할 수 없습니다. 잠시 후 다시 시도해 주세요.", + }, + tasks: { loadFailed: "할 일 목록을 불러오지 못했습니다. 다시 시도해 주세요." }, + projects: { ungrouped: "프로젝트 없음" }, + models: { unavailable: "현재 사용할 수 없음" }, + overlays: { + loadingSettings: "설정 불러오는 중", + loadingSettingsProgress: "설정 불러오는 중…", + }, + notifications: { + scheduledTask: "정기 작업", + viewScheduledTasks: "정기 작업 보기", + }, + previousMainProcessInterruption: { + title: "Maka 복구됨", + description: "이전 종료가 완료되지 않았습니다.", + copyDiagnostics: "보고서 복사", + }, + conversationExport: { + exported: (date) => `${date}에 Maka에서 내보냈습니다.`, + you: "나", + toolCalls: "도구 호출", + intentSeparator: " — ", + }, +}; + const COPY = { 'zh-CN': zhCopy, 'zh-TW': zhTwCopy, en: enCopy, + ko: koCopy, } satisfies UiCatalog; export function getShellRemainingCopy(locale: UiLocale): ShellRemainingCopy {