From 8ad7653a2e4015e19c37bddbaddc44cc5cd348fd Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Thu, 14 May 2026 19:14:13 -0400 Subject: [PATCH] feat(dashboard): add Korean language support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds Korean (ko) as a supported dashboard locale alongside en, zh-CN, vi, ja. Browser locales starting with `ko` (e.g. `ko-KR`) normalize to `ko` and the Language switcher exposes "Korean" / "한국어" as a selectable option. The full ~2670-key translation block was translated from the English source with the formal-polite register (하십시오체) appropriate for an enterprise dashboard. Technical names (CCS, Claude, CLIProxy, OAuth, provider names, env vars, paths) are kept untranslated. All placeholders (e.g. {{name}}, {{count}}, {{provider}}) are preserved verbatim, matching the parity test. Also backfills 23 keys missing from zh-CN, vi, and ja that were added to en with the recent "Shared Resource Controls" feature (#1206 -> 2a422b3b): accountsPage.resources*, accountsTable.{sharedResources,resourcesTitle, resourcesShared,resourcesProfileLocal,badges.profileLocal}, commonToast.resourcesUpdated, and the full editAccountSharedResources section. Without this backfill the existing i18n parity test was red for all non-en locales on dev. Closes #1241 --- ui/src/lib/i18n.ts | 2760 +++++++++++++++++ ui/src/lib/locales.ts | 3 +- .../unit/ui/i18n/language-switcher.test.tsx | 1 + 3 files changed, 2763 insertions(+), 1 deletion(-) diff --git a/ui/src/lib/i18n.ts b/ui/src/lib/i18n.ts index 3541ed4d..578aed34 100644 --- a/ui/src/lib/i18n.ts +++ b/ui/src/lib/i18n.ts @@ -10,6 +10,7 @@ const resources = { 'zh-CN': 'Simplified Chinese', vi: 'Vietnamese', ja: 'Japanese', + ko: 'Korean', }, layout: { languageSwitcher: 'Language', @@ -2680,6 +2681,7 @@ const resources = { 'zh-CN': '简体中文', vi: '越南语', ja: '日语', + ko: '韩语', }, layout: { languageSwitcher: '语言', @@ -2760,6 +2762,7 @@ const resources = { settingsSaved: '设置已保存', defaultTargetUpdated: '默认目标已更新', failedUpdateDefaultTarget: '更新默认目标到 {{target}} 失败{{suffix}}', + resourcesUpdated: '共享资源已更新', }, profileDialog: { editTitle: '编辑配置', @@ -3296,8 +3299,10 @@ const resources = { created: '创建时间', lastUsed: '最后使用', historySync: '历史同步', + sharedResources: '资源', actions: '操作', syncTitle: '编辑同步模式、分组与连续性深度', + resourcesTitle: '编辑共享资源继承', confirmLegacyTitle: '确认此旧账号的当前模式为显式', sync: '同步', confirm: '确认', @@ -3317,6 +3322,8 @@ const resources = { sharedGroupLegacy: '共享({{group}},标准旧策略)', isolatedLegacy: '隔离(旧默认)', isolated: '隔离', + resourcesShared: '共享', + resourcesProfileLocal: '配置本地', noSameGroupPeer: '同组中还没有其他账号', sameGroupPeerCount_one: '{{count}} 个同组账号', sameGroupPeerCount_other: '{{count}} 个同组账号', @@ -3327,6 +3334,7 @@ const resources = { deeper: '更深', legacy: '旧策略', isolated: '隔离', + profileLocal: '本地', }, }, addAccountDialog: { @@ -3791,6 +3799,9 @@ const resources = { quickCommandsDesc: '复制后在终端运行。', workspaceBadge: 'ccs auth 工作区', historySyncBadge: '历史同步控制', + resourcesBadge: '共享资源控制', + resourcesShared: '共享', + resourcesProfileLocal: '配置本地', authAccounts: '认证账号', tableScopePrefix: '该表仅展示', tableScopeMiddle: '账号。模式/分组/深度调整请使用', @@ -4132,6 +4143,22 @@ const resources = { profileLocalAccounts: '{{count}} 个 profile-local', moreProfileLocalAccounts: '+{{count}} 个更多', }, + editAccountSharedResources: { + title: '编辑共享资源', + description: '配置「{{name}}」如何从 CCS 共享目录继承命令、技能与设置。', + resourceMode: '资源模式', + selectResourceMode: '选择资源模式', + sharedOption: '共享', + sharedHint: '从共享目录继承命令、技能与代理。', + profileLocalOption: '配置本地', + profileLocalHint: '使用该账号私有目录中的隔离资源。', + implicationTitle: '保存后会发生什么', + sharedImplication: '此账号将看到共享资源中心内的所有工具与配置。', + profileLocalImplication: '此账号不会看到共享工具,并出于安全或测试目的保持完全隔离。', + cancel: '取消', + save: '保存', + saving: '保存中...', + }, heroSection: { title: 'CCS Config', subtitle: 'Claude Code Switch Dashboard', @@ -5194,6 +5221,7 @@ const resources = { 'zh-CN': 'Tiếng Trung giản thể', vi: 'Tiếng Việt', ja: 'Tiếng Nhật', + ko: 'Tiếng Hàn', }, layout: { languageSwitcher: 'Ngôn ngữ', @@ -5281,6 +5309,7 @@ const resources = { defaultTargetUpdated: 'Đã cập nhật mục tiêu mặc định', failedUpdateDefaultTarget: 'Không cập nhật được mục tiêu mặc định thành {{target}}{{suffix}}', + resourcesUpdated: 'Đã cập nhật tài nguyên dùng chung', }, profileDialog: { editTitle: 'Chỉnh sửa hồ sơ', @@ -5868,8 +5897,10 @@ const resources = { created: 'Ngày tạo', lastUsed: 'Được sử dụng lần cuối', historySync: 'Đồng bộ hóa lịch sử', + sharedResources: 'Tài nguyên', actions: 'Hành động', syncTitle: 'Chỉnh sửa chế độ đồng bộ, nhóm và độ sâu liên tục', + resourcesTitle: 'Chỉnh sửa kế thừa tài nguyên dùng chung', confirmLegacyTitle: 'Xác nhận chế độ hiện tại của tài khoản cũ này là rõ ràng', sync: 'Đồng bộ hóa', confirm: 'Xác nhận', @@ -5890,6 +5921,8 @@ const resources = { sharedGroupLegacy: 'chia sẻ ({{group}}, kế thừa tiêu chuẩn)', isolatedLegacy: 'tách biệt (mặc định cũ)', isolated: 'tách biệt', + resourcesShared: 'dùng chung', + resourcesProfileLocal: 'cục bộ hồ sơ', noSameGroupPeer: 'Chưa có tài khoản cùng nhóm', sameGroupPeerCount_one: '{{count}} tài khoản cùng nhóm', sameGroupPeerCount_other: '{{count}} tài khoản cùng nhóm', @@ -5900,6 +5933,7 @@ const resources = { deeper: 'Sâu hơn', legacy: 'Kế thừa', isolated: 'Tách biệt', + profileLocal: 'Cục bộ', }, }, addAccountDialog: { @@ -6397,6 +6431,9 @@ const resources = { quickCommandsDesc: 'Sao chép và chạy trong terminal.', workspaceBadge: 'Không gian làm việc `ccs auth`', historySyncBadge: 'Kiểm soát đồng bộ hóa lịch sử', + resourcesBadge: 'Kiểm soát tài nguyên dùng chung', + resourcesShared: 'Dùng chung', + resourcesProfileLocal: 'Cục bộ hồ sơ', authAccounts: 'Tài khoản xác thực', tableScopePrefix: 'Bảng này được cố ý đặt trong phạm vi', tableScopeMiddle: 'tài khoản. Sử dụng', @@ -6747,6 +6784,25 @@ const resources = { profileLocalAccounts: '{{count}} profile-local', moreProfileLocalAccounts: '+{{count}} khác', }, + editAccountSharedResources: { + title: 'Chỉnh sửa tài nguyên dùng chung', + description: + 'Cấu hình cách "{{name}}" kế thừa lệnh, kỹ năng và cài đặt từ thư mục dùng chung của CCS.', + resourceMode: 'Chế độ tài nguyên', + selectResourceMode: 'Chọn chế độ tài nguyên', + sharedOption: 'Dùng chung', + sharedHint: 'Kế thừa lệnh, kỹ năng và agent từ thư mục dùng chung.', + profileLocalOption: 'Cục bộ hồ sơ', + profileLocalHint: 'Sử dụng tài nguyên cô lập trong thư mục riêng của tài khoản.', + implicationTitle: 'Sau khi lưu sẽ ra sao', + sharedImplication: + 'Tài khoản này sẽ thấy mọi công cụ và cấu hình trong trung tâm tài nguyên dùng chung.', + profileLocalImplication: + 'Tài khoản này sẽ không thấy các công cụ dùng chung. Nó vẫn cô lập hoàn toàn để phục vụ bảo mật hoặc kiểm thử.', + cancel: 'Hủy bỏ', + save: 'Lưu', + saving: 'Đang lưu...', + }, heroSection: { title: 'CCS Config', subtitle: 'Bảng điều khiển Claude Code Switch', @@ -7827,6 +7883,7 @@ const resources = { 'zh-CN': '簡体字中国語', vi: 'ベトナム語', ja: '日本語', + ko: '韓国語', }, layout: { languageSwitcher: '言語', @@ -7914,6 +7971,7 @@ const resources = { defaultTargetUpdated: 'デフォルトターゲットを更新しました', failedUpdateDefaultTarget: 'デフォルトターゲットを {{target}}{{suffix}} に更新できませんでした', + resourcesUpdated: '共有リソースを更新しました', }, profileDialog: { editTitle: 'プロファイルを編集', @@ -8501,8 +8559,10 @@ const resources = { created: '作成日', lastUsed: '最終使用', historySync: '履歴同期', + sharedResources: 'リソース', actions: '操作', syncTitle: '同期モード、グループ、継続性レベルを編集', + resourcesTitle: '共有リソースの継承を編集', confirmLegacyTitle: 'このレガシーアカウントの現在のモードを明示的に確定する', sync: '同期', confirm: '確定', @@ -8523,6 +8583,8 @@ const resources = { sharedGroupLegacy: '共有({{group}}、標準・レガシー)', isolatedLegacy: '分離(旧既定値)', isolated: '分離', + resourcesShared: '共有', + resourcesProfileLocal: 'プロファイルローカル', noSameGroupPeer: '同じグループの相手がまだいません', sameGroupPeerCount_one: '{{count}} 件の同グループアカウント', sameGroupPeerCount_other: '{{count}} 件の同グループアカウント', @@ -8533,6 +8595,7 @@ const resources = { deeper: '拡張', legacy: 'レガシー', isolated: '分離', + profileLocal: 'ローカル', }, }, addAccountDialog: { @@ -9037,6 +9100,9 @@ const resources = { quickCommandsDesc: 'コピーしてターミナルで実行します。', workspaceBadge: 'ccs auth ワークスペース', historySyncBadge: '履歴同期設定', + resourcesBadge: '共有リソース設定', + resourcesShared: '共有', + resourcesProfileLocal: 'プロファイルローカル', authAccounts: '認証アカウント', tableScopePrefix: 'この表では', tableScopeMiddle: 'のアカウントのみを表示します。モード/グループ/継続性の変更は', @@ -9800,6 +9866,25 @@ const resources = { title: 'ヘルス', subtitle: 'システムヘルスの監視。', }, + editAccountSharedResources: { + title: '共有リソースを編集', + description: + 'CCS 共有ディレクトリのコマンド、スキル、設定を「{{name}}」がどのように継承するかを設定します。', + resourceMode: 'リソースモード', + selectResourceMode: 'リソースモードを選択', + sharedOption: '共有', + sharedHint: '共有ディレクトリからコマンド、スキル、エージェントを継承します。', + profileLocalOption: 'プロファイルローカル', + profileLocalHint: 'このアカウント専用ディレクトリの分離されたリソースを使用します。', + implicationTitle: '保存するとどうなるか', + sharedImplication: + 'このアカウントは共有リソースハブにあるすべてのツールと設定を参照します。', + profileLocalImplication: + 'このアカウントは共有ツールを参照しません。セキュリティやテスト目的のため完全に分離されたままです。', + cancel: 'キャンセル', + save: '保存', + saving: '保存中...', + }, heroSection: { title: 'CCS Config', subtitle: 'Claude Code Switch Dashboard', @@ -10476,6 +10561,2681 @@ const resources = { }, }, }, + ko: { + translation: { + locale: { + en: '영어', + 'zh-CN': '중국어 간체', + vi: '베트남어', + ja: '일본어', + ko: '한국어', + }, + layout: { + languageSwitcher: '언어', + }, + nav: { + general: '일반', + home: '홈', + analytics: '분석', + identityAccess: 'ID 및 액세스', + apiProfiles: '프로필', + cliproxyPlus: 'CLIProxy Plus', + cliproxyOverview: '개요', + controlPanel: '제어판', + githubCopilot: 'GitHub Copilot', + cursorIde: 'Cursor IDE', + claudeExtension: 'Claude 확장', + accounts: '계정', + allAccounts: '모든 계정', + sharedData: '공유 리소스', + compatibleClis: '호환', + deprecated: '지원 중단', + factoryDroid: 'Factory Droid', + system: '시스템', + health: '헬스', + logs: '로그', + settings: '설정', + openrouterTooltip: '추천: OpenRouter + Alibaba Coding Plan + Ollama', + }, + home: { + profiles: '프로필', + cliproxy: 'CLIProxy', + accounts: '계정', + health: '헬스', + configurationRequired: '구성이 필요합니다', + }, + auth: { + dashboardTitle: 'CCS 대시보드', + protectedAccessLabel: '보호된 액세스', + remoteGuardLabel: '원격 액세스 가드', + loading: '대시보드 액세스 확인 중…', + loginDescription: + '이 CCS 인스턴스에 구성된 사용자 이름과 비밀번호로 대시보드에 액세스하십시오.', + username: '사용자 이름', + password: '비밀번호', + usernamePlaceholder: '사용자 이름 입력', + passwordPlaceholder: '비밀번호 입력', + signIn: '로그인', + signingIn: '로그인 중...', + loginFailed: '로그인 실패', + lightMode: '라이트', + darkMode: '다크', + noDefaultCredentials: 'CCS는 기본 자격 증명을 제공하지 않습니다.', + credentialsHint: + '자격 증명은 CCS 호스트에서 `ccs config auth setup`으로 생성됩니다. Docker 배포의 경우 컨테이너 내부에서 해당 명령을 실행해야 합니다.', + remoteSetupTitle: '원격 액세스에는 인증 설정이 필요합니다', + remoteSetupDescription: + '이 대시보드는 비로컬 주소에서 열렸지만, 이 CCS 인스턴스에는 아직 대시보드 인증이 활성화되어 있지 않습니다.', + incompleteSetupDescription: + '대시보드 인증이 활성화되어 있지만 설정이 완료되지 않았습니다. 로그인 전에 이 CCS 인스턴스의 구성을 완료하십시오.', + safetyNoteRemote: + 'CCS 호스트 소유자가 대시보드 인증을 활성화할 때까지 원격 관리는 잠금 상태로 유지됩니다.', + safetyNoteLocal: '동일한 머신에 있다면 localhost URL이 가장 간단한 접근 방법입니다.', + safetyNoteSession: + '로그인이 성공하면 이 대시보드 호스트로 범위가 지정된 HTTP 전용 세션이 생성됩니다.', + hostStepTitle: 'CCS 호스트에서', + hostStepDescription: + '대시보드 자격 증명을 생성하거나 다시 활성화한 후, 원격 디바이스에서 이 페이지를 다시 여십시오.', + dockerStepDescription: + 'Docker 배포입니까? 실행 중인 컨테이너 내부에서 설정을 실행하십시오:', + localStepTitle: '이 머신이 본인의 것이라면', + localStepDescription: + 'LAN 또는 Tailscale 주소 대신 `ccs config`가 출력하는 localhost URL을 여십시오.', + showPassword: '비밀번호 표시', + hidePassword: '비밀번호 숨기기', + }, + commonToast: { + apiKeyRequired: 'API 키가 필요합니다', + accountAddedPresetFailed: '계정이 추가되었지만 기본 프리셋 적용에 실패했습니다', + settingsCopied: '설정이 클립보드에 복사되었습니다', + enterPresetName: '저장할 프리셋 이름을 입력하십시오', + codeCopied: '코드가 클립보드에 복사되었습니다', + copyCodeFailed: '코드 복사에 실패했습니다', + appliedModelAllTiers: '모델을 모든 티어에 적용했습니다', + settingsSaved: '설정이 저장되었습니다', + defaultTargetUpdated: '기본 대상이 업데이트되었습니다', + failedUpdateDefaultTarget: '기본 대상을 {{target}}{{suffix}}(으)로 업데이트하지 못했습니다', + resourcesUpdated: '공유 리소스가 업데이트되었습니다', + }, + profileDialog: { + editTitle: '프로필 편집', + createTitle: 'API 프로필 생성', + name: '이름', + namePlaceholder: 'my-api', + baseUrl: 'Base URL', + baseUrlPlaceholder: 'https://api.example.com', + apiKey: 'API 키', + defaultModel: '기본 모델 (ANTHROPIC_MODEL)', + defaultModelHint: '비워두면 다음을 사용합니다: {{model}}', + modelMappingTitle: '모델 매핑 (Opus/Sonnet/Haiku)', + modelMappingDesc: + '각 티어에 다른 모델 ID를 구성합니다. 다양한 모델 유형을 서로 다른 백엔드로 라우팅하는 API 프록시에 유용합니다.', + opusModel: 'Opus 모델 (ANTHROPIC_DEFAULT_OPUS_MODEL)', + sonnetModel: 'Sonnet 모델 (ANTHROPIC_DEFAULT_SONNET_MODEL)', + haikuModel: 'Haiku 모델 (ANTHROPIC_DEFAULT_HAIKU_MODEL)', + cancel: '취소', + saving: '저장 중...', + update: '업데이트', + create: '생성', + }, + modelTierMapping: { + title: '모델 티어 매핑', + advanced: '고급', + description: 'Claude Code의 opus/sonnet/haiku 티어에 대해 서로 다른 모델을 구성합니다.', + autoSuggest: '{{provider}} 기반 자동 추천', + opusPlaceholder: '예: anthropic/claude-opus-4', + sonnetPlaceholder: '예: anthropic/claude-sonnet-4', + haikuPlaceholder: '예: anthropic/claude-3.5-haiku', + footer: + '이들은 ANTHROPIC_DEFAULT_OPUS_MODEL, ANTHROPIC_DEFAULT_SONNET_MODEL, ANTHROPIC_DEFAULT_HAIKU_MODEL을 설정합니다.', + }, + envEditor: { + sensitive: '민감', + none: '환경 변수가 구성되지 않았습니다.', + noneHint: '아래 입력란을 사용하여 변수를 추가하거나 JSON을 직접 편집하십시오.', + addVariable: '환경 변수 추가', + keyPlaceholder: 'VARIABLE_NAME', + valuePlaceholder: '값', + }, + setupVariant: { + using: '사용 중:', + variantNameRequired: '런타임 변형 이름 *', + variantNamePlaceholder: '예: my-gemini, g3, flash', + invokeHintPrefix: '이 변형으로 실행:', + model: '모델', + modelPlaceholder: '예: gemini-2.5-pro, claude-opus-4-6-thinking', + choosePresetInstead: '대신 프리셋에서 선택', + selectModel: '모델 선택', + customModelName: '사용자 정의 모델 이름...', + enterAnyModel: 'CLIProxy가 지원하는 모델 이름을 입력하십시오', + defaultModel: '기본값: {{model}}', + providerDefault: '프로바이더 기본값', + back: '뒤로', + skip: '건너뛰기', + creating: '생성 중...', + createVariant: '변형 생성', + skipHint: '계정 설정으로 충분하고 별도의 런타임 변형이 필요하지 않으면 건너뛰십시오', + }, + customPresetDialog: { + title: '사용자 정의 프리셋', + presetNameOptional: '프리셋 이름 (선택)', + presetNamePlaceholder: '예: My Custom Config', + codexTipPrefix: 'Codex 팁: 접미사', + codexTipSuffix: + '는 작업 강도를 고정합니다. 접미사가 없는 모델은 Thinking 설정을 사용합니다.', + defaultModel: '기본 모델', + defaultModelDesc: '특정 티어가 요청되지 않을 때 사용됩니다', + opusModel: 'Opus (가장 강력)', + opusModelDesc: '복잡한 추론 작업용', + sonnetModel: 'Sonnet (균형)', + sonnetModelDesc: '속도와 성능의 균형', + haikuModel: 'Haiku (빠름)', + haikuModelDesc: '간단한 작업에 대한 빠른 응답', + cancel: '취소', + savePreset: '프리셋 저장', + applyPreset: '프리셋 적용', + deletePreset: '프리셋 삭제', + }, + componentModelSelector: { + selectModel: '모델 선택', + availableModelsCount: '사용 가능한 모델 ({{count}})', + preview: '미리보기', + }, + searchableSelect: { + searchModels: '모델 검색...', + noResults: '결과를 찾을 수 없습니다.', + }, + copilotSettings: { + enableCopilot: 'Copilot 사용', + enableCopilotDesc: 'GitHub Copilot 구독 사용 허용', + basicSettings: '기본 설정', + accountType: '계정 유형', + accountTypeIndividual: '개인', + accountTypeBusiness: '비즈니스', + accountTypeEnterprise: '엔터프라이즈', + rateLimiting: '속도 제한', + rateLimitSeconds: '속도 제한 (초)', + noLimit: '제한 없음', + waitOnRateLimit: '속도 제한 시 대기', + waitOnRateLimitDesc: '한도 도달 시 오류 대신 대기', + daemonSettings: '데몬 설정', + autoStartDaemon: '데몬 자동 시작', + autoStartDaemonDesc: '프로필 사용 시 copilot-api 시작', + }, + providerModelSelector: { + selectModel: '모델 선택', + noModelsForProvider: '이 프로바이더에 사용 가능한 모델이 없습니다', + broken: '손상됨', + deprecated: '지원 중단', + paid: '유료', + freeTier: '무료 티어', + paidTier: '유료 티어', + modelKnownIssues: '이 모델에는 알려진 문제가 있습니다', + viewIssueDetails: '이슈 상세 보기', + modelDeprecated: '이 모델은 지원이 중단되었습니다', + recommended: '추천', + allModelsCount: '모든 모델 ({{count}})', + noModelsAvailable: '사용 가능한 모델이 없습니다', + shadowed: '가려짐', + prefixOnly: '접두사 전용', + current: '현재', + currentValue: '현재 값', + preferredPinnedModel: '선호하는 고정 모델:', + pinnedRouteStatus: '고정된 라우트 상태:', + pinnedModelNotAdvertised: '고정된 모델이 현재 프록시에서 알리지 않고 있습니다: {{model}}', + }, + createAuthProfileDialog: { + title: '새 계정 생성', + description: + '인증 프로필에는 Claude CLI 로그인이 필요합니다. 터미널에서 아래 명령을 실행하십시오. 동기화 모드, 그룹, 연속성 깊이는 나중에 계정 테이블에서 편집할 수 있습니다.', + profileName: '프로필 이름', + profileNamePlaceholder: '예: work, personal, client', + invalidProfileName: + '이름은 문자로 시작해야 하며 문자, 숫자, 대시 또는 밑줄만 포함할 수 있습니다.', + enableSharedHistory: '다른 ccs auth 계정과 공유 기록 동기화 활성화', + historySyncGroupOptional: '기록 동기화 그룹 (선택)', + historySyncGroupPlaceholder: 'default, sprint-a, client-x', + historySyncGroupHint: + '기본 공유 그룹을 사용하려면 비워두십시오. 공백은 대시로 정규화됩니다.', + deeperContinuity: '고급: 심층 연속성 모드', + deeperContinuityHint: + 'session-env, file-history, shell-snapshots, todos에 대한 동기화를 추가합니다. 자격 증명은 분리된 상태로 유지됩니다.', + invalidContextGroup: + '그룹은 문자로 시작하고 문자, 숫자, 대시, 밑줄만 사용해야 합니다 (최대 {{max}}자).', + command: '명령', + commandFallback: 'ccs auth create ', + afterRunPrefix: '명령 실행 후:', + afterRunStep1: '브라우저에서 Claude 로그인을 완료하십시오', + afterRunStep2: '여기로 돌아와서 새로 고침하여 새 계정을 확인하십시오', + poolingHint: + '풀링된 Claude OAuth 라우팅을 선호하십니까? 계정 페이지 작업 버튼에서 CLIProxy Claude 풀을 사용하십시오.', + close: '닫기', + copied: '복사됨!', + copyCommand: '명령 복사', + }, + accountRouteGuide: { + title: '추천 2계정 라우트', + description: + '토큰 격리를 위해 별도의 계정 프로필을 사용하십시오. 두 계정이 동일한 로컬 연속성을 봐야 할 때만 기록 동기화를 켜십시오.', + status: { + empty: '계정 생성', + isolated: '격리 준비됨', + shared: '공유 프로젝트 컨텍스트', + deeper: '심층 동기화 준비됨', + mixed: '혼합 설정', + }, + cards: { + isolated: { + title: '토큰은 분리된 상태로 유지', + desc: '각 ccs auth 계정은 자체 Claude 구성, 로그인, 자격 증명을 소유합니다. 동기화 설정은 토큰을 복사하지 않습니다.', + }, + select: { + title: '계정을 선택하십시오', + desc: '명시적 사용을 위해 ccs work 또는 ccs personal을 실행하십시오. 단순한 ccs가 하나의 계정을 따라야 할 때만 기본값을 설정하십시오.', + }, + settings: { + title: '설정은 루트를 따름', + desc: '비-bare 계정은 CCS 공유 상태를 통해 settings.json을 ~/.claude/settings.json에 연결합니다. ccs auth show로 확인하십시오.', + }, + sync: { + title: '기록 동기화는 옵트인', + desc: '두 계정 모두 Shared 모드와 동일한 그룹이 필요합니다. 심층 동기화는 추가 로컬 연속성 아티팩트를 추가합니다.', + }, + }, + commands: { + isolated: '격리된 계정 사용', + sync: '선택적 공유 기록', + syncDesc: + '두 계정에서 로컬 기록을 공유하려면 동일한 그룹(예: "{{group}}")을 사용하십시오.', + }, + }, + cliproxyModelCategory: { + google: 'Google (Gemini)', + openai: 'OpenAI (GPT)', + anthropic: 'Anthropic (Claude)', + antigravity: 'Antigravity', + other: '기타', + }, + cliproxyOverviewComponents: { + availableModels: '사용 가능한 모델', + noModelsAvailable: '사용 가능한 모델이 없습니다', + startSessionHint: '사용 가능한 모델을 가져오려면 CLIProxy 세션을 시작하십시오', + totalCount: '총 {{count}}개', + availableThroughGroupedByProvider: + '{{backendLabel}}을(를) 통해 사용 가능한 모델, 프로바이더별 그룹화', + moreCount: '+{{count}}개 더', + }, + categorizedModelSelector: { + selectModel: '모델 선택', + noModelsAvailable: '사용 가능한 모델이 없습니다', + modelPlaceholder: '모델...', + }, + openrouterQuickStart: { + recommended: '추천', + title: 'OpenRouter로 시작', + description: + 'OpenAI, Anthropic, Google, Meta 등의 {{modelCountLabel}}개 모델에 단일 API로 액세스하십시오.', + featureOneApi: '하나의 API, 모든 프로바이더', + profileSummaryCount: '프로필 {{count}}개', + profileSummaryCount_other: '프로필 {{count}}개', + profileSummaryEmpty: '프리미엄 품질 + 로컬 제어', + summaryBadgeDefaultQuality: '기본적으로 최고의 품질', + summaryBadgeLocalLane: '작업에 적합할 때 로컬 레인', + summaryExistingTitle: '프로필을 선택하거나 다른 레인 추가', + summaryEmptyTitle: '첫 번째 프로필 레인 선택', + summaryExistingDescription: + '이 워크스페이스에 이미 {{count}}개의 프로필이 있습니다. 본격적인 코딩에는 프리미엄 품질의 프로바이더를 유지하고, 개인 정보 보호, 비용 또는 오프라인 작업이 중요할 때는 로컬 런타임을 추가하십시오.', + summaryExistingDescription_other: + '이 워크스페이스에 이미 {{count}}개의 프로필이 있습니다. 본격적인 코딩에는 프리미엄 품질의 프로바이더를 유지하고, 개인 정보 보호, 비용 또는 오프라인 작업이 중요할 때는 로컬 런타임을 추가하십시오.', + summaryEmptyDescription: + '작업에 맞는 레인을 선택하십시오. 안정적인 코딩에는 프리미엄 프로바이더가 기본값으로 유지됩니다. 로컬 런타임은 개인 정보 보호, 저렴한 변환, 실험에 가장 적합합니다.', + qualityLanesTitle: '최고 품질 레인', + qualityLaneHighlightDefaultQuality: '고품질 코딩에 가장 적합한 기본 레인', + alibabaLaneDescription: + 'OpenRouter 카탈로그 외부의 전용 프리미엄 레인을 원할 때의 강력한 직접 코딩 프로필.', + alibabaLaneHighlightQuality: '전용 엔드포인트로 프리미엄 품질을 원할 때 적합', + localRuntimesTitle: '로컬 런타임', + localOllamaTitle: 'Ollama + Gemma 4', + localOllamaLabel: 'Ollama', + localOllamaHighlight: '비공개 프롬프트, 로컬 정리, 저렴한 배치 변환에 가장 적합', + localLlamacppTitle: 'llama.cpp', + localLlamacppLabel: 'llama.cpp', + localLlamacppHighlight: + '사용자 정의 GGUF 설정 및 고급 자체 호스팅 로컬 워크플로에 가장 적합', + localDetectedModels: '로컬 모델 {{count}}개 감지됨', + localDetectedModels_other: '로컬 모델 {{count}}개 감지됨', + localNoModelsDetected: '아직 로컬 모델이 감지되지 않았습니다', + localWaitingServer: '로컬 서버 및 모델 목록 대기 중', + localRuntimeCheckingBadge: '확인 중', + localRuntimeReadyBadge: '준비됨', + localRuntimeNeedsModelBadge: '모델 필요', + localRuntimeOfflineBadge: '오프라인', + localRuntimeCheckingDescription: + '설정 안내를 표시하기 전에 로컬 런타임 상태를 확인하고 있습니다.', + localRuntimeReadyDescription: + '비공개 프롬프트, 오프라인 워크플로, 저렴한 배치 변환에 가장 적합합니다.', + localRuntimeNeedsModelDescription: + '런타임은 실행 중이지만 추천 로컬 모델을 아직 가져오거나 로드해야 합니다.', + localRuntimeOfflineDescription: + '개인 정보 보호가 민감한 작업, 저렴한 로컬 변환, 오프라인 세션에 이 레인을 사용하십시오.', + localRuntimeCheckingFooter: '로컬 런타임 확인 중...', + localRuntimeReadyFooter: '{{endpoint}}에서 엔드포인트 준비됨', + localRuntimeMissingModelFooter: '로컬 설정을 완료하려면 `{{command}}`을(를) 실행하십시오.', + localRuntimeOfflineFooter: + '로컬 엔드포인트를 온라인으로 전환하려면 `{{command}}`을(를) 실행하십시오.', + localRuntimeSetupAction: '{{label}} 설정', + localRuntimeUseAction: '{{label}} 사용', + localRuntimeFinishAction: '{{label}} 설정 완료', + runtimeProviderBadge: '런타임 프로바이더 설정', + runtimeProviderTitle: 'AI 프로바이더 열기', + runtimeProviderManagedDescription: + 'CLIProxy 관리 커넥터, 프로바이더 시크릿, 고급 라우팅 제어가 필요할 때 사용하십시오.', + runtimeProviderFeatureConnectors: 'Gemini, Codex, Claude, Vertex 및 OpenAI 호환 커넥터', + runtimeProviderFeatureSecrets: '공유 시크릿이 개별 API 프로필 외부에 유지됩니다', + runtimeProviderFooter: + '여러 프로필이 하나의 프로바이더 구성을 공유해야 할 때 가장 적합합니다.', + createOpenRouterProfile: 'OpenRouter 프로필 생성', + getApiKeyAt: 'API 키 받기:', + createCustomProfile: '사용자 정의 API 프로필 생성', + }, + alibabaCodingPlanQuickStart: { + recommended: '추천', + title: 'Alibaba Coding Plan 사용해보기', + description: + '코딩 워크로드에 Anthropic 호환 엔드포인트를 통해 Alibaba Cloud Coding Plan을 사용하십시오.', + featureEndpoint: 'Anthropic 호환 엔드포인트', + featureKeyFormat: '전용 sk-sp API 키', + createAlibabaProfile: 'Alibaba Coding Plan 프로필 생성', + readGuideAt: '설정 가이드 읽기:', + }, + alibabaCodingPlanPromo: { + title: 'Alibaba Coding Plan', + subtitle: 'Anthropic 엔드포인트를 통한 Model Studio Coding Plan', + add: '추가', + }, + credentialHealth: { + title: '자격 증명 상태', + ready: '준비됨', + noCredentialsConfigured: + '구성된 자격 증명이 없습니다. 위의 로그인 버튼을 사용하여 인증하십시오.', + neverUsed: '사용 안 함', + justNow: '방금 전', + unknown: '알 수 없음', + daysAgo: '{{count}}일 전', + hoursAgo: '{{count}}시간 전', + minutesAgo: '{{count}}분 전', + }, + proxyStatusWidget: { + justNow: '방금 전', + minutesAgo: '{{count}}분 전', + hoursAgo: '{{count}}시간 전', + syncReady: '동기화 준비됨', + noConfig: '구성 없음', + remoteProxy: '원격 프록시', + active: '활성', + trafficAutoRouted: '트래픽이 원격 서버로 자동 라우팅됨', + tooltipSync: 'CLIProxy로 프로필 동기화', + tooltipRestart: '다시 시작', + tooltipStop: '중지', + tooltipClose: '닫기', + tooltipVersionSettings: '버전 설정', + versionManagement: '버전 관리', + selectVersionPlaceholder: '설치할 버전 선택...', + stable: '(안정)', + install: '설치', + versionsAboveUnstable: '{{version}} 이상 버전에는 알려진 문제가 있습니다', + versionsKnownIssues: '{{version}} 버전에는 알려진 문제가 있습니다', + lastChecked: '마지막 확인 {{time}}', + notRunning: '실행 중이 아님', + start: '시작', + port: '포트 {{port}}', + sessionCount: '세션 {{count}}개', + sessionCount_other: '세션 {{count}}개', + installFaultyTitle: '알려진 문제가 있는 버전을 설치하시겠습니까?', + installFaultyDesc: + '알려진 결함 범위 {{range}}에 해당하는 v{{version}}을(를) 설치하려고 합니다.', + installFaultyWarning: + '이 버전에는 알려진 버그가 있어 실패하거나 프록시를 좋지 않은 상태로 만들 수 있습니다.', + installUnstableTitle: '불안정한 버전을 설치하시겠습니까?', + installUnstableDesc: + '최대 안정 버전 v{{maxStable}}보다 높은 v{{version}}을(를) 설치하려고 합니다.', + installUnstableWarning: + '이 버전에는 알려진 안정성 문제가 있어 예기치 않은 동작을 유발할 수 있습니다.', + installUnstableConfirm: '계속 진행하시겠습니까?', + cancel: '취소', + installAnyway: '그래도 설치', + clickToDowngrade: '다운그레이드하려면 클릭', + clickToUpdate: '업데이트하려면 클릭', + }, + syncStatusCard: { + profileSync: '프로필 동기화', + ready: '준비됨', + noConfig: '구성 없음', + syncsProfilesDesc: 'API 프로필을 로컬 CLIProxy 구성으로 동기화', + runDoctorHint: '구성을 생성하려면 ccs doctor --fix를 실행하십시오.', + details: '상세', + syncNow: '지금 동기화', + }, + syncDialog: { + title: '로컬 CLIProxy로 프로필 동기화', + description: 'CCS API 프로필을 로컬 CLIProxy config.yaml로 동기화합니다.', + noProfiles: '동기화할 프로필이 구성되지 않았습니다.', + createProfilesFirst: '프로필 탭에서 먼저 API 프로필을 생성하십시오.', + modelLabel: '모델:', + ready: '준비됨', + profilesToSync_one: '동기화할 프로필 {{count}}개', + profilesToSync_other: '동기화할 프로필 {{count}}개', + cancel: '취소', + syncing: '동기화 중...', + synced: '동기화 완료!', + syncNow: '지금 동기화', + }, + errorLogs: { + title: '오류 로그', + failedRequests_one: '실패한 요청 {{count}}개', + failedRequests_other: '실패한 요청 {{count}}개', + cliproxyDiagnostics: 'CLIProxy 진단', + showingCount: '총 {{total}}개 로그 중 50개 표시', + selectLog: '상세 정보를 보려면 로그를 선택하십시오', + failedLoadContent: '로그 콘텐츠를 로드하지 못했습니다', + copyAbsolutePath: '절대 경로 복사', + copyRawContent: '원시 로그 콘텐츠 복사', + tabOverview: '개요', + tabHeaders: '헤더', + tabRequest: '요청', + tabResponse: '응답', + tabRaw: '원시', + modelLabel: '모델:', + quotaResetsIn: '쿼터 초기화: ', + method: '메서드', + provider: '프로바이더', + version: '버전', + endpoint: '엔드포인트', + url: 'URL', + timestamp: '타임스탬프', + na: 'N/A', + noHeaders: '사용 가능한 헤더가 없습니다', + noRequestBody: '요청 본문 없음', + noResponseBody: '응답 본문 없음', + rateLimitedMsg: + '속도 제한. 다른 계정으로 전환하거나 쿼터 초기화를 기다리십시오. 모델 {{model}}이(가) 쿼터를 소진했습니다.', + rateLimitedMsgNoModel: '속도 제한. 다른 계정으로 전환하거나 쿼터 초기화를 기다리십시오.', + authFailedMsg: '인증 실패. CLIProxy 설정을 통해 재인증하거나 API 키를 확인하십시오.', + notFoundMsg: + '엔드포인트를 찾을 수 없습니다. 이 엔드포인트는 이 프로바이더에 존재하지 않을 수 있습니다.', + serverErrorMsg: + '업스트림 서버 오류. 나중에 다시 시도하거나 프로바이더 상태 페이지를 확인하십시오.', + timeoutMsg: '요청 시간 초과. 네트워크 연결을 확인하거나 시간 초과 설정을 늘리십시오.', + unknown: '알 수 없음', + }, + editAccountContext: { + title: '기록 동기화 편집', + description: + '"{{name}}"이(가) 다른 ccs auth 계정과 기록 및 연속성을 공유하는 방법을 구성합니다.', + syncMode: '동기화 모드', + selectContextMode: '컨텍스트 모드 선택', + isolatedOption: '격리', + sharedOption: '공유', + sharedModeHint: '동일한 기록 그룹의 계정 간에 워크스페이스 컨텍스트를 재사용합니다.', + isolatedModeHint: '이 계정을 다른 ccs auth 계정과 완전히 분리된 상태로 유지합니다.', + historySyncGroup: '기록 동기화 그룹', + groupPlaceholder: 'default', + groupHint: + '소문자로 정규화됩니다(공백은 대시로 변환). 허용: 문자, 숫자, _, - (최대 {{max}}자).', + invalidGroup: '문자로 시작하는 유효한 그룹 이름을 입력하십시오.', + continuityDepth: '연속성 깊이', + selectContinuityDepth: '연속성 깊이 선택', + standardOption: '표준', + deeperOption: '심층', + deeperHint: '포괄적인 session-env, file-history, shell-snapshots, todos를 동기화합니다.', + standardHint: '표준 모드는 프로젝트 워크스페이스 컨텍스트만 동기화합니다.', + credentialsIsolated: '자격 증명 및 .anthropic은 모든 모드에서 계정별로 격리됩니다.', + implicationTitle: '저장 후 의미', + isolatedImplication: + '이 계정은 분리된 상태로 유지됩니다. 다른 계정은 이 계정의 연속성 상태를 재개할 수 없습니다.', + sameGroupRule: + '계정이 서로 연속성을 공유하려면 먼저 동일한 그룹 "{{group}}"을(를) 사용해야 합니다.', + noSameGroupPeer: '현재 이 그룹을 공유하는 다른 계정이 없습니다.', + sameGroupPeerCount_one: '이미 이 그룹을 공유하는 다른 계정이 {{count}}개 있습니다.', + sameGroupPeerCount_other: '이미 이 그룹을 공유하는 다른 계정이 {{count}}개 있습니다.', + deeperReady_one: + '동일 그룹 계정 {{count}}개가 이미 심층 연속성을 사용 중입니다. 이는 사용 가능한 가장 강력한 핸드오프 설정입니다.', + deeperReady_other: + '동일 그룹 계정 {{count}}개가 이미 심층 연속성을 사용 중입니다. 이는 사용 가능한 가장 강력한 핸드오프 설정입니다.', + deeperNeedsPeers: + '여기에 심층 연속성이 활성화되어 있지만, 더 강력한 계정 간 재개를 기대하려면 이 그룹의 다른 계정에도 심층 연속성이 필요합니다.', + standardWarning: + '표준 공유 모드는 프로젝트 컨텍스트에만 적합합니다. 두 계정 모두 심층 연속성을 사용할 때 계정 간 재개 기대치가 더 강합니다.', + resumeOriginalWarning: + '이전 대화가 중요한 경우, 설정을 변경하기 전에 원래 계정에서 재개하십시오.', + cancel: '취소', + save: '저장', + saving: '저장 중...', + }, + historySyncLearningMap: { + title: '기록 동기화 작동 방식', + description: + '격리 -> 공유 -> 심층. 계정 간 재개에는 두 계정 모두에 동일한 그룹이 필요합니다.', + learningMap: '학습 맵', + isolated: '격리', + shared: '공유', + deeper: '심층', + cliproxyManaged_one: + 'CLIProxy Claude 풀 계정 {{count}}개가 Action Center / CLIProxy 페이지에서 관리됩니다.', + cliproxyManaged_other: + 'CLIProxy Claude 풀 계정 {{count}}개가 Action Center / CLIProxy 페이지에서 관리됩니다.', + showDetails: '상세 보기: 그룹, 전환, 레거시 정책', + modeSwitch: '모드 전환', + modeSwitchDesc: + '각 계정에서 동기화를 사용하여 격리/공유 간을 이동하고 심층 연속성을 선택하십시오.', + historySyncGroup: '기록 동기화 그룹', + historySyncGroupDesc: + '계정이 연속성을 공유하기 전에 동일한 그룹이 필요합니다. 기본 폴백은 default입니다.', + sameGroupRule: '현재 계정은 동일한 그룹에서 공유 상태일 때만 연속성을 공유합니다.', + deeperRecommendation: + '그룹 "{{group}}"이(가) 공유되어 있지만, 사용자가 계정 간 재개를 기대하는 경우 심층 연속성이 더 안전한 선택입니다.', + partialGroup: + '그룹 "{{group}}"은 양호한 상태이지만, 다른 계정이나 그룹은 여전히 동일 그룹 또는 심층 설정이 필요합니다.', + readyGroup: + '그룹 "{{group}}"은 이미 여러 계정에서 심층 연속성을 사용하고 있습니다. 이는 사용 가능한 가장 강력한 핸드오프 설정입니다.', + legacyConfirmation_one: '레거시 계정 {{count}}개가 아직 명시적 확인을 필요로 합니다.', + legacyConfirmation_other: '레거시 계정 {{count}}개가 아직 명시적 확인을 필요로 합니다.', + }, + continuityReadiness: { + title: '계정 간 재개 확인', + description: + '사용자가 계정을 전환하기 전에 누락된 것이 무엇인지 보려면 이 카드를 사용하십시오.', + state: { + single: '단일 계정', + isolated: '재개 꺼짐', + 'shared-alone': '공유되었지만 미완료', + 'shared-standard': '프로젝트만', + partial: '부분적으로 준비됨', + ready: '더 강력한 핸드오프 준비됨', + }, + metrics: { + isolated: '격리', + sharedPeers: '피어와 공유', + deeperReady: '심층 준비됨', + }, + messages: { + single: { + title: '인증 계정이 하나만 구성되어 있습니다.', + description: + '아직 계정 간 핸드오프가 적용되지 않습니다. 공유 연속성을 구성하기 전에 다른 인증 계정을 추가하십시오.', + }, + isolated: { + title: '현재 계정 간 재개가 꺼져 있습니다.', + description: + '표시되는 모든 계정이 격리되어 있으므로 한 계정에서 생성된 세션은 해당 계정에 머무릅니다.', + }, + 'shared-alone': { + title: '공유 모드가 존재하지만 아직 어떤 그룹에도 피어가 없습니다.', + description_one: + '공유 계정 {{count}}개가 동일 그룹의 다른 계정을 여전히 기다리고 있습니다.', + description_other: + '공유 계정 {{count}}개가 동일 그룹의 다른 계정을 여전히 기다리고 있습니다.', + }, + 'shared-standard': { + title: + '그룹 "{{group}}"은 프로젝트 컨텍스트를 공유하지만 심층 연속성이 아직 페어링되지 않았습니다.', + description: + '사용자는 프로젝트 공유 이상을 기대할 수 있습니다. 더 강력한 핸드오프 기대치를 위해 이 그룹의 두 계정 모두에서 심층 연속성을 활성화하십시오.', + }, + partial: { + title: '한 그룹은 준비되었지만 전체 설정은 여전히 혼합 상태입니다.', + description: + '적어도 한 그룹은 이미 심층 연속성을 사용 중이지만, 다른 계정은 여전히 격리되어 있거나 공유 그룹에 혼자 있거나 심층 연속성이 누락되었습니다.', + }, + ready: { + title: '그룹 "{{group}}"이(가) 사용 가능한 가장 강력한 연속성 설정을 갖추고 있습니다.', + description: + '이 그룹의 여러 계정에서 이미 심층 연속성을 사용 중입니다. 재개 동작은 여전히 Claude가 업스트림에 저장하는 내용에 따라 달라집니다.', + }, + }, + stepsTitle: '사용자가 다음에 해야 할 작업', + steps: { + syncBoth: '전환하려는 계정뿐만 아니라 두 계정 모두에서 동기화를 여십시오.', + sameGroup: + '두 계정에서 동일한 기록 동기화 그룹을 사용하십시오. "{{group}}"이(가) 현재 추천 그룹입니다.', + enableDeeper: + '프로젝트 전용 공유 대신 계정 간 재개를 기대하는 사용자라면 두 계정 모두에서 심층 연속성을 켜십시오.', + resumeOriginal: + '원래 대화가 중요한 경우, 연속성 설정을 변경하기 전에 원래 계정에서 재개하십시오.', + }, + singleSteps: { + addAccount: '계정 간 핸드오프를 계획하기 전에 두 번째 ccs auth 계정을 생성하십시오.', + sameGroupLater: + '해당 두 번째 계정이 존재하면, 두 계정 모두 동일한 기록 동기화 그룹에 두십시오.', + enableDeeperLater: + '사용자가 프로젝트 전용 공유 대신 계정 간 재개를 기대한다면, 두 계정 모두에서 심층 연속성을 활성화하십시오.', + resumeOriginal: + '원래 대화가 중요한 경우, 두 번째 계정이 준비될 때까지 원래 계정에서 계속 재개하십시오.', + }, + }, + continuityOverview: { + plainLaneTitle: '단순 ccs가 다른 재개 레인을 사용 중입니다', + plainLaneDescription: + '단순 ccs는 현재 이 계정 레인이 아닌 {{lane}}에서 재개합니다. 동기화 설정을 변경하기 전에 먼저 원래 레인을 복구하십시오.', + setDefaultHint: + '향후 세션에서 단순 ccs가 따라야 할 계정에 기본값 설정 작업을 사용하십시오.', + recommendBadge: '추천 {{group}}', + partialBadge: '부분 동기화 {{group}}', + lane: { + native: '네이티브 Claude (~/.claude)', + accountDefault: '계정 {{name}}', + accountInherited: '연속성 상속을 통한 계정 {{name}}', + profileDefault: '네이티브 Claude 레인을 통한 기본 프로필 {{name}}', + }, + }, + accountsTable: { + name: '이름', + type: '유형', + defaultBadge: '기본값', + created: '생성됨', + lastUsed: '마지막 사용', + historySync: '기록 동기화', + sharedResources: '리소스', + actions: '작업', + syncTitle: '동기화 모드, 그룹, 연속성 깊이 편집', + resourcesTitle: '공유 리소스 상속 편집', + confirmLegacyTitle: '이 레거시 계정의 현재 모드를 명시적으로 확인', + sync: '동기화', + confirm: '확인', + active: '활성', + setDefault: '기본값으로 설정', + deleteAccount: '계정 삭제', + cannotDeleteDefault: '기본 계정을 삭제할 수 없습니다', + noAccounts: 'CCS auth 계정을 찾을 수 없습니다. ccs auth create로 계정을 추가하십시오.', + resetToDefault: 'CCS 기본값으로 재설정', + deleteDialogTitle: '계정 삭제', + deleteDialogDesc: + '"{{name}}" 계정을 삭제하시겠습니까? 이렇게 하면 프로필과 모든 세션 데이터가 제거됩니다. 이 작업은 취소할 수 없습니다.', + cancel: '취소', + delete: '삭제', + sharedGroupStandard: '공유 ({{group}}, 프로젝트 전용)', + sharedGroupDeeper: '공유 ({{group}}, 심층 연속성)', + sharedGroupLegacy: '공유 ({{group}}, 프로젝트 전용, 레거시)', + isolatedLegacy: '격리 (레거시 기본값)', + isolated: '격리', + resourcesShared: '공유', + resourcesProfileLocal: '프로필 로컬', + noSameGroupPeer: '아직 동일 그룹 피어가 없습니다', + sameGroupPeerCount_one: '동일 그룹 피어 {{count}}개', + sameGroupPeerCount_other: '동일 그룹 피어 {{count}}개', + legacyReview: '이 추론된 기본값을 검토하고 확인하십시오.', + noHandoff: '계정 간 재개는 원래 계정에 머무릅니다.', + badges: { + shared: '공유', + deeper: '심층', + legacy: '레거시', + isolated: '격리', + profileLocal: '로컬', + }, + }, + addAccountDialog: { + title: '{{displayName}} 계정 추가', + descKiro: 'Kiro 인증 방법을 선택한 다음, 브라우저로 인증하거나 Kiro IDE에서 가져오십시오.', + descDeviceCode: + '인증을 클릭하십시오. 프로바이더 웹사이트에서 입력할 검증 코드가 표시됩니다.', + descOauth: + '인증을 클릭하여 OAuth URL을 받으십시오. 아무 브라우저에서나 열어 로그인하십시오.', + powerUserEnabled: '파워 유저 모드 활성화됨', + powerUserSkipped: + '설정 > 프록시 파워 유저 모드가 AGY 책임 체크리스트와 Gemini 대시보드 위험 문구를 건너뛰고 있습니다. OAuth/계정 위험에 대한 전적인 책임을 수락합니다.', + powerUserLoadFailed: + '파워 유저 모드 설정을 로드하지 못했습니다. 설정 > 프록시를 확인하고 다시 시도하십시오.', + powerUserLoading: '파워 유저 안전 설정을 로드 중입니다. 잠시 기다린 후 다시 시도하십시오.', + powerUserUnavailableRetry: + '파워 유저 모드를 사용할 수 없습니다. 필요한 프로바이더 안전 단계를 완료하고 다시 시도하십시오.', + authMethod: '인증 방법', + selectKiroAuthMethod: 'Kiro 인증 방법 선택', + gitlabAuthMethod: 'GitLab 인증 방법', + selectGitlabAuthMethod: 'GitLab 인증 방법 선택', + gitlabAuthOAuth: '브라우저 OAuth', + gitlabAuthPat: '개인 액세스 토큰', + gitlabAuthHint: + 'gitlab.com에는 브라우저 OAuth를, 자체 호스팅 및 관리자 관리 설정에는 PAT를 사용하십시오.', + gitlabUrl: 'GitLab URL', + gitlabUrlPlaceholder: 'https://gitlab.com', + gitlabUrlHint: + '선택 사항. gitlab.com의 경우 비워두거나 자체 호스팅 GitLab base URL을 설정하십시오.', + gitlabPat: '개인 액세스 토큰', + gitlabPatPlaceholder: 'glpat-...', + gitlabPatHint: '토큰에는 최소한 다음이 포함되어야 합니다', + gitlabPatRequired: 'PAT 로그인에는 GitLab 개인 액세스 토큰이 필요합니다.', + nicknameRequired: '닉네임 (필수)', + nicknameOptional: '닉네임 (선택)', + nicknamePlaceholder: '예: work, personal', + nicknameRequiredHint: + '이 프로바이더에 필요합니다. 고유한 친숙한 이름을 사용하십시오(예: work, personal).', + nicknameOptionalHint: + '이 계정을 식별할 친숙한 이름입니다. 안전한 생성된 식별자를 사용하려면 비워두십시오.', + waitingForAuth: '인증 대기 중...', + deviceCodeHint: + '검증 코드 대화 상자가 곧 나타납니다. 프로바이더 웹사이트에 코드를 입력하십시오.', + browserHint: '브라우저에서 인증을 완료하십시오. 이 대화 상자는 자동으로 닫힙니다.', + openUrlLabel: '아무 브라우저에서나 이 URL을 열어 로그인하십시오:', + copied: '복사됨', + copy: '복사', + open: '열기', + popupBlocked: '팝업이 차단되었습니다. 위 URL을 복사하여 브라우저에서 수동으로 여십시오.', + redirectPasteLabel: '리디렉션이 작동하지 않았습니까? 콜백 URL을 붙여넣으십시오:', + callbackPlaceholder: '리디렉션 URL을 여기에 붙여넣으십시오...', + submitCallback: '콜백 제출', + submitting: '제출 중...', + preparingUrl: '로그인 URL 준비 중...', + cancel: '취소', + importingToken: 'Kiro IDE에서 토큰을 가져오는 중...', + authenticate: '인증', + importFromIde: 'IDE에서 가져오기', + importing: '가져오는 중...', + }, + flowViz: { + backToProviders: '프로바이더로 돌아가기', + showDetails: '상세 표시', + hideDetails: '상세 숨기기', + showPausedAccounts: '일시 중지 표시 ({{count}})', + hidePausedAccounts: '일시 중지 숨기기 ({{count}})', + visibleTotalRequests: '표시되는 요청', + visibleAccounts: '표시되는 계정', + excludingPausedAccounts: '일시 중지된 {{count}}개 제외', + resetLayout: '레이아웃 재설정', + provider: '프로바이더', + totalRequests: '총 요청', + accounts: '계정', + connectionTimeline: '연결 타임라인', + noRecentConnections: '최근 연결 없음', + }, + quickStats: { + totalRequests: '총 요청', + successRate: '성공률', + totalTokens: '총 토큰', + activeModels: '활성 모델', + }, + authMonitor: { + accounts: '계정', + accountsCount: '계정 {{count}}개', + success: '성공', + failed: '실패', + successRate: '성공률', + }, + accountCard: { + resumeAccount: '계정 재개', + pauseAccount: '계정 일시 중지', + quotaLoading: '쿼터...', + quota: '쿼터', + quotaUnavailable: '쿼터 한도 사용 불가', + reauthNeeded: '재인증 필요', + failureLabelReauth: '재인증', + failureLabelWorkspace: '워크스페이스', + failureLabelNoAccess: '액세스 없음', + failureLabelRetry: '재시도', + failureLabelReconnect: '재연결', + failureLabelTemporary: '일시적', + failureLabelUnavailable: '사용 불가', + failureHintReauth: '인증 흐름을 다시 실행하여 이 계정을 새로 고치십시오.', + failureHintWorkspace: + '이 계정을 활성 워크스페이스로 다시 이동한 다음, 제거하고 다시 추가하십시오.', + failureHintNoAccess: '이 계정은 프로바이더 쿼터 엔드포인트에 액세스할 수 없습니다.', + failureHintRetry: '잠시 후 쿼터 요청을 다시 시도하십시오.', + failureHintReconnect: '오래된 계정을 제거하고 다시 인증하십시오.', + failureHintTemporary: '나중에 다시 시도하십시오. 일시적인 것으로 보입니다.', + removeAndReadd: '계정 제거 후 다시 추가', + autoRefreshFailed: '자동 새로 고침 실패', + }, + antigravityChecklist: { + title: 'Antigravity OAuth 책임', + subtitle: '인증하기 전에 4단계를 모두 완료하십시오.', + mandatory: '필수', + completion: '완료', + stepsCount: '{{current}}/4 단계', + }, + accountSafetyWarning: { + title: 'OAuth 계정 안전 경고', + subtitle: '이슈 #509 · Gemini + AGY OAuth 위험', + firstLine: + '이슈 #509는 ccs agy와 ccs gemini 및 ccs agy 간의 계정 공유 사용과 관련된 정지/차단 보고를 문서화합니다.', + secondLine: + 'OAuth 및 계정 액세스 위험에 대한 전적인 책임을 수락하는 경우에만 계속하십시오.', + issueLabel: '이슈 #509 읽기', + proxySettingsLabel: 'Gemini + AGY 제어: 설정 > 프록시', + }, + cliproxyDialog: { + name: '이름', + provider: '프로바이더', + account: '계정', + accountOptional: '계정 (선택)', + model: '모델', + modelOptional: '모델 (선택)', + defaultTarget: '기본 대상', + defaultTier: '기본 티어', + tierConfig: '티어 구성', + selectProvider: '프로바이더 선택...', + useDefaultAccount: '기본 계정 사용', + defaultSuffix: '(기본값)', + opus: 'Opus', + sonnet: 'Sonnet', + haiku: 'Haiku', + claudeCode: 'Claude Code', + factoryDroid: 'Factory Droid', + cancel: '취소', + create: '생성', + creating: '생성 중...', + saveChanges: '변경 사항 저장', + saving: '저장 중...', + placeholderName: 'my-gemini', + placeholderModel: 'gemini-2.5-pro', + placeholderComposite: 'my-composite', + placeholderModelId: 'model-id', + placeholderAccountId: 'account-id', + editCompositeTitle: '복합 변형 편집: {{name}}', + editSingleTitle: '단일 변형 편집: {{name}}', + }, + profileEditor: { + profileInfo: '프로필 정보', + profileName: '프로필 이름', + filePath: '파일 경로', + lastModified: '마지막 수정', + defaultTarget: '기본 대상', + quickUsage: '빠른 사용', + runWithProfile: '프로필로 실행', + runOnDroid: 'Droid에서 실행', + runOnDroidWithFlag: 'Droid에서 실행 (--target)', + droidAliasExplicit: 'Droid 별칭 (명시적)', + overrideToClaude: 'Claude로 재정의', + overrideToClaudeExplicit: 'Claude로 재정의 (명시적)', + targetHintPreferredAlias: '선호하는 명시적 별칭:', + targetHintClaudeDefault: '기본 명령:', + targetHintLegacyAlias: '레거시 단축키도 여전히 작동합니다:', + targetHintOverride: '각 실행을 다음으로 재정의할 수도 있습니다', + setAsDefault: '기본값으로 설정', + provider: '프로바이더', + custom: '사용자 정의', + providerChooserHint: + '프리셋으로 시작한 다음, 필요에 따라 URL, API 키 또는 모델 매핑을 조정하십시오.', + featuredProviders: '추천 프로바이더', + scrollHint: '화면이 좁으면 스크롤하십시오', + customEndpoint: '사용자 정의 엔드포인트', + morePresets: '더 많은 프리셋', + customEndpointDescription: + '빈 Anthropic 호환 URL에서 시작하여 모든 것을 수동으로 구성하십시오.', + }, + settings: { + sectionLoadFailed: '섹션을 로드하지 못했습니다', + unknownError: '알 수 없는 오류가 발생했습니다', + reloadPage: '페이지 다시 로드', + refresh: '새로 고침', + copy: '복사', + copied: '복사됨', + saved: '저장됨', + loading: '로드 중...', + configFileNotFound: '구성 파일을 찾을 수 없습니다', + }, + settingsTabs: { + browser: '브라우저', + web: '웹', + image: '이미지', + channels: '채널', + env: '환경 변수', + think: '사고', + proxy: '프록시', + auth: '인증', + backup: '백업', + }, + settingsAuth: { + failedFetchTokens: '인증 토큰을 가져오지 못했습니다', + failedSaveTokens: '토큰을 저장하지 못했습니다', + tokensUpdated: '토큰이 업데이트되었습니다. 적용하려면 CLIProxy를 다시 시작하십시오.', + failedRegenerate: '시크릿 재생성에 실패했습니다', + secretRegenerated: + '새 관리 시크릿이 생성되었습니다. 적용하려면 CLIProxy를 다시 시작하십시오.', + failedReset: '토큰 재설정에 실패했습니다', + tokensReset: '토큰이 기본값으로 재설정되었습니다. 적용하려면 CLIProxy를 다시 시작하십시오.', + description: 'CLIProxy 인증 토큰을 구성합니다. 변경 사항은 CLIProxy 재시작이 필요합니다.', + apiKey: 'API 키', + custom: '사용자 정의', + apiKeyDesc: 'Claude Code가 CLIProxy로 인증할 때 사용됩니다', + apiKeyPlaceholder: 'API 키', + managementSecret: '관리 시크릿', + managementSecretDesc: 'CCS 대시보드가 CLIProxy 관리 API에 액세스할 때 사용됩니다', + managementSecretPlaceholder: '관리 시크릿', + generateSecret: '새 보안 시크릿 생성', + resetDefaults: '기본값으로 재설정', + resetDesc: 'API 키와 관리 시크릿을 모두 기본값으로 재설정합니다.', + saving: '저장 중...', + save: '저장', + }, + settingsGlobalEnv: { + description: + 'Claude 구독이 아닌 모든 프로필(gemini, codex, agy, ghcp 등)에 주입되는 환경 변수', + enabled: '글로벌 환경 변수 활성화됨', + disabled: '글로벌 환경 변수 비활성화됨', + enabledDesc: '환경 변수가 타사 프로필에 주입됩니다', + disabledDesc: '환경 변수가 주입되지 않습니다', + envVars: '환경 변수', + noneConfigured: '구성된 환경 변수가 없습니다', + addNew: '새 변수 추가', + keyName: 'KEY_NAME', + value: '값', + add: '추가', + quickAdd: '공통 변수 빠른 추가', + allConfigured: '모든 공통 변수가 구성되었습니다', + }, + settingsBackups: { + failedFetch: '백업을 가져오지 못했습니다', + failedRestore: '백업 복원에 실패했습니다', + restoreSuccess: '백업이 성공적으로 복원되었습니다', + title: '설정 백업', + description: + 'settings.json 파일의 이전 버전을 복원합니다. 설정이 수정될 때 백업이 자동으로 생성됩니다.', + none: '사용 가능한 백업이 없습니다', + noneHint: '설정을 수정하면 여기에 백업이 표시됩니다', + latest: '최신', + restoring: '복원 중...', + restore: '복원', + restoreConfirmTitle: '백업을 복원하시겠습니까?', + restoreConfirmPrefix: '현재 설정을 다음 백업으로 교체합니다', + restoreConfirmSuffix: '이 작업은 취소할 수 없습니다.', + cancel: '취소', + }, + settingsWebsearch: { + description: '타사 프로필(gemini, codex, agy 등)을 위한 CLI 기반 웹 검색', + enabled: 'WebSearch 활성화됨', + disabled: 'WebSearch 비활성화됨', + checking: '상태 확인 중...', + providers: '프로바이더', + noneConfigured: '구성된 프로바이더가 없습니다', + noneConfiguredHint: '웹 검색 프로바이더를 활성화하려면 CLI 도구를 설치하십시오', + checkProviders: '프로바이더 확인', + installed: '설치됨', + notInstalled: '설치되지 않음', + model: '모델:', + howInstall: '{{name}} CLI 설치 방법', + installGlobally: '전역 설치', + requiresKey: '(xAI API 키 필요)', + freeTier: '(무료 티어 사용 가능)', + viewDocs: '문서 보기', + }, + settingsProxy: { + failedLoadAgyMode: '파워 유저 모드를 로드하지 못했습니다', + failedUpdateAgyMode: '파워 유저 모드를 업데이트하지 못했습니다', + failedVerifyAgyMode: '파워 유저 모드 지속성을 확인하지 못했습니다', + notPersistedAgyMode: + '파워 유저 모드가 지속되지 않았습니다. 다른 프로세스가 구성을 수정했을 수 있습니다.', + agyModeEnabled: '파워 유저 모드가 활성화되었습니다.', + agyModeDisabled: '파워 유저 모드가 비활성화되었습니다.', + typePhraseToContinue: '계속하려면 "{{value}}"을(를) 입력하십시오.', + description: '프록시 기반 프로필을 위한 로컬 또는 원격 {{backend}} 연결을 구성합니다', + backendPlus: 'CLIProxy Plus', + backend: 'CLIProxy', + instanceStatus: '인스턴스 상태', + connectionMode: '연결 모드', + local: '로컬', + remote: '원격', + localDesc: '이 머신에서 {{backend}} 바이너리 실행', + remoteDesc: '원격 {{backend}} 서버에 연결', + backendBinary: '백엔드 바이너리', + stopProxyToSwitch: '백엔드를 전환하려면 인스턴스 상태에서 실행 중인 프록시를 중지하십시오.', + default: '기본값', + plusDesc: + '추가 프로바이더를 위한 선택적 트랙. 여전히 지원되지만 현재 업스트림이 아닌 커뮤니티가 유지 관리합니다.', + originalDesc: '코어 프로바이더 트랙용 기본, 항상 사용 가능한 백엔드.', + plusFallbackNotice: + 'Plus 프로바이더 트랙은 지원이 중단되지 않았지만, 유지 관리되는 포크 경로가 복원되는 동안 로컬 CLIProxy는 여전히 원래 백엔드로 폴백됩니다.', + variantsIncompatible: + '기존 plus-extra 변형({{providers}})은 원래 백엔드에서 실행되지 않습니다. 참조용으로 표시된 상태로 유지하되, 사용하기 전에 Plus로 전환하십시오.', + safety: '안전', + agyModeTitle: 'Antigravity + Gemini 파워 유저 모드', + agyModeDesc: 'AGY 책임 체크리스트와 Gemini 대시보드 입력 확인을 건너뜁니다.', + agyWarning: + 'OAuth 정지/차단 위험 패턴(#509)을 완전히 이해하는 경우에만 사용하십시오. CCS는 계정 손실에 대한 책임을 지지 않습니다.', + finalConfirm: '최종 확인 필요', + finalConfirmDesc: + '이를 활성화하면 AGY 안전 체크포인트와 Gemini 대시보드 위험 문구 게이트를 건너뜁니다. 이슈 #509를 검토하고 정확한 문구를 입력하여 진행하십시오.', + step1: '1단계', + readIssue: '이슈 #509 읽기', + step2: '2단계', + typePrefix: '입력', + typeSuffix: '하여 활성화하십시오.', + typePhraseAria: + 'Antigravity + Gemini 파워 유저 모드를 활성화하려면 I ACCEPT RISK를 입력하십시오', + exactPhrase: '정확한 문구가 필요합니다.', + enableAgyMode: 'Antigravity + Gemini 파워 유저 모드 활성화', + toggleAgyMode: 'Antigravity + Gemini 파워 유저 모드 전환', + fallbackSettings: '폴백 설정', + enableFallback: '로컬로 폴백 활성화', + enableFallbackDesc: '원격에 도달할 수 없으면 로컬 프록시 사용', + autoStartLocal: '로컬 프록시 자동 시작', + autoStartLocalDesc: '폴백 시 로컬 프록시 자동 시작', + advanced: '고급', + debugMode: '디버그 모드', + debugModeDesc: '브라우저 콘솔에서 개발자 진단 활성화', + debugModeEnabled: + '디버그 모드가 활성화되었습니다. 자세한 로그는 브라우저 콘솔을 확인하십시오.', + localProxy: '로컬 프록시', + port: '포트', + autoStart: '자동 시작', + localAutoStartDesc: '필요할 때 로컬 프록시 자동 시작', + remoteConfigTitle: '원격 서버 구성', + host: '호스트', + hostPlaceholder: '192.168.1.100 또는 proxy.example.com', + defaultPort: '기본값: {{value}}', + portPlaceholder: '기본값을 사용하려면 {{value}}을(를) 비워두십시오', + protocol: '프로토콜', + http: 'HTTP', + https: 'HTTPS', + apiKeyOptional: 'API 키 (선택)', + apiKeyPlaceholder: '/v1/* API 엔드포인트용', + apiKeyDesc: '/v1/chat/completions에 대한 API 요청에 사용됩니다', + managementKeyOptional: '관리 키 (선택)', + managementKeyPlaceholder: '/v0/management/* 엔드포인트용', + managementKeyDesc: '대시보드 관리 API에 사용됩니다. 설정되지 않으면 API 키로 폴백합니다.', + testing: '테스트 중...', + testConnection: '연결 테스트', + connectedLatency: '연결됨 ({{value}}ms)', + connectionFailed: '연결 실패', + invalidPortOrEmpty: '포트는 1에서 65535 사이의 정수이거나 기본값을 위해 비워두어야 합니다', + invalidLocalPort: '로컬 포트는 1에서 65535 사이의 정수여야 합니다', + backendPlusApi: 'CLIProxyAPIPlus', + backendApi: 'CLIProxyAPI', + }, + settingsThinking: { + description: '지원되는 모델에 대해 확장 사고/추론을 구성합니다.', + supportedProviders: '지원되는 프로바이더', + modeTitle: '사고 모드', + modeAutoDesc: '모델 티어에 따라 자동으로 사고 설정', + modeOffDesc: '확장 사고 비활성화', + modeManualDesc: '지속적인 재정의 수준을 설정하거나 실행별 CLI 플래그 사용', + tierDefaults: '티어 기본값', + tierDefaultsDesc: '자동 모드에서 각 모델 티어의 기본 사고 수준입니다.', + persistentOverride: '지속적 재정의', + persistentOverrideDesc: '모든 세션에 적용됩니다. CLI 플래그가 여전히 우선합니다.', + enterCustomBudget: '사용자 정의 예산 입력', + apply: '적용', + providerOverrides: '프로바이더 재정의 ({{count}})', + providerOverridesDesc: + '특정 프로바이더에 대한 티어 기본값을 재정의합니다. 필요에 따라 사용자 정의 프로바이더 키를 추가하십시오.', + addProviderPlaceholder: '프로바이더 키 추가 (예: qwen)', + showWarnings: '경고 표시', + showWarningsDesc: '사고 값이 클램프되거나 조정될 때 경고 표시', + cliEnvOverride: 'CLI 및 환경 변수 재정의', + supportLine1Prefix: '사고 예산:', + supportLine1Suffix: '(토큰 기반)', + supportLine2Prefix: '추론 강도:', + supportLine2SuffixPrefix: '(접미사 또는 ', + supportLine2SuffixPostfix: ': minimal/low/medium/high/xhigh)', + supportLine3Prefix: 'Codex 접미사는 강도를 고정합니다 (예: ', + supportLine3Suffix: '); 접미사가 없는 모델은 Thinking 모드를 사용합니다.', + }, + analytics: { + title: '분석', + noDailyUsage: '오늘 사용 데이터 없음', + noUsageData: '사용 가능한 사용 데이터 없음', + subtitle: '사용량 및 인사이트 추적', + month: '월', + allTime: '전체 기간', + updated: '업데이트됨 {{value}}', + }, + analyticsSummary: { + totalTokens: '총 토큰', + totalTokensSubtitle: '입력 {{input}} / 출력 {{output}}', + totalCost: '총 비용', + totalCostSubtitle: '평균 ${{value}}/일', + cacheTokens: '캐시 토큰', + cacheTokensSubtitle: '${{cost}} (비용의 {{percent}}%)', + inputCost: '입력 비용', + outputCost: '출력 비용', + tokensSubtitle: '{{value}} 토큰', + }, + apiProfiles: { + title: '프로필', + sidebarTitle: 'API 프로필', + sidebarSubtitle: '프리미엄 API, 로컬 런타임, 사용자 정의 엔드포인트', + new: '새로 만들기', + searchPlaceholder: '프로필 검색...', + loadingProfiles: '프로필 로드 중...', + failedLoadTitle: '프로필을 로드하지 못했습니다', + failedLoadDesc: 'API 프로필을 가져올 수 없습니다. 다시 시도하십시오.', + retry: '재시도', + noProfilesYet: '아직 API 프로필이 없습니다', + noProfilesDesc: '사용자 정의 API 엔드포인트에 연결하려면 첫 번째 프로필을 생성하십시오', + createProfile: '프로필 생성', + noProfileMatch: '"{{query}}"과(와) 일치하는 프로필이 없습니다', + profileCount: '프로필 {{count}}개', + profileCount_other: '프로필 {{count}}개', + configuredCount: '구성됨 {{count}}개', + deleteProfileTitle: '프로필 삭제', + deleteProfileDesc: + '"{{name}}"을(를) 삭제하시겠습니까? 이렇게 하면 설정 파일이 제거되며 취소할 수 없습니다.', + delete: '삭제', + unsavedChangesTitle: '저장되지 않은 변경 사항', + unsavedChangesDesc: + '"{{current}}"에 저장되지 않은 변경 사항이 있습니다. 폐기하고 "{{next}}"(으)로 전환하시겠습니까?', + discardSwitch: '폐기 후 전환', + noOrphansFound: '고아 프로필 설정을 찾을 수 없습니다', + confirmRegisterOrphans: + '{{total}}개의 고아 프로필 설정 파일을 찾았으며, 그 중 {{valid}}개를 등록할 준비가 되었습니다. 지금 등록하시겠습니까?', + registeredWithSkipped: ' ({{count}}개 건너뜀)', + registeredProfiles: '프로필 {{count}}개 등록됨', + copyPrompt: '"{{name}}"을(를) 어떤 새 프로필 이름으로 복사하시겠습니까?', + destinationEmpty: '대상 프로필 이름은 비어 있을 수 없습니다', + exportRedacted: + '편집된 토큰으로 내보내기를 생성했습니다. 필요한 경우 CLI의 include-secrets 흐름을 사용하십시오.', + exportDownloaded: '프로필 내보내기가 다운로드되었습니다', + importFailed: '프로필 번들을 가져오지 못했습니다', + discoverOrphans: '고아 프로필 검색', + importProfileBundle: '프로필 번들 가져오기', + }, + accountsPage: { + title: '계정', + managePrefix: '관리', + manageSuffix: '계정과 풀 온보딩을 하나의 패널에서.', + mobileManageSuffix: '계정별 연속성.', + primaryActions: '주요 작업', + createAccount: '계정 생성', + authClaudeInPool: '풀에서 Claude 인증', + openClaudePoolSettings: 'Claude 풀 설정 열기', + openCliProxyClaudePool: 'CLIProxy Claude 풀 열기', + migrationFollowup: '마이그레이션 후속 조치', + legacyContextPending: '계정 {{count}}개가 아직 첫 모드 확인이 필요합니다.', + legacyContextPending_other: '계정 {{count}}개가 아직 첫 모드 확인이 필요합니다.', + legacyContinuityPending: '공유 계정 {{count}}개가 표준 레거시 연속성 깊이로 남아 있습니다.', + legacyContinuityPending_other: + '공유 계정 {{count}}개가 표준 레거시 연속성 깊이로 남아 있습니다.', + confirmingLegacy: '레거시 정책 확인 중...', + confirmLegacy: '레거시 정책 확인 ({{count}})', + noLegacyFollowup: '대기 중인 레거시 후속 조치가 없습니다.', + continuityGuide: '연속성 가이드', + expandWhenNeeded: '필요할 때만 확장하십시오.', + sharedStandard: '공유 표준', + sharedStandardDesc: + '공유 워크스페이스만. 핸드오프를 기대하기 전에 두 계정을 동일한 그룹에 두십시오.', + sharedDeeper: '공유 심층', + sharedDeeperPrefix: '추가', + sharedDeeperDesc: + 'session-env, file-history, shell-snapshots, todos를 추가합니다. 사용자가 계정 간 재개를 기대할 때 권장됩니다.', + isolated: '격리', + isolatedDesc: '연결 없음. 대화는 원래 계정에 머무릅니다.', + quickCommands: '빠른 명령', + quickCommandsDesc: '터미널에 복사하여 실행하십시오.', + workspaceBadge: 'ccs auth 워크스페이스', + historySyncBadge: '기록 및 재개 제어', + resourcesBadge: '공유 리소스 제어', + resourcesShared: '공유', + resourcesProfileLocal: '프로필 로컬', + authAccounts: '인증 계정', + tableScopePrefix: '이 테이블은 의도적으로', + tableScopeMiddle: '계정으로 범위가 지정되어 있습니다. 모드/그룹/깊이 변경에는', + tableScopeSuffix: '을(를) 사용하십시오.', + accountMatrix: '계정 매트릭스', + sharedTotalDesc: '공유 총합: {{count}}. 작업에는 동기화 설정 및 레거시 확인이 포함됩니다.', + loadingAccounts: '계정 로드 중...', + }, + health: { + justNow: '방금 전', + secondsAgo: '{{count}}초 전', + minutesAgo: '{{count}}분 전', + hoursAgo: '{{count}}시간 전', + systemHealth: '시스템 헬스', + build: '빌드 {{version}}', + lastScan: '마지막 스캔:', + autoRefresh: '자동 새로 고침:', + refresh: '새로 고침', + checks: '검사', + version: '버전', + platform: '플랫폼', + liveMonitoring: '실시간 모니터링 활성', + copied: '클립보드에 복사되었습니다', + refreshing: '헬스 검사 새로 고침 중...', + fix: '수정', + applyFix: '수정 적용', + healthLabel: '헬스', + }, + updates: { + actionRequired: '작업 필요', + done: '완료', + all: '전체', + inboxTitle: '업데이트 센터', + inboxSubtitle: '작업에 집중한 다음 업데이트를 완료 또는 해제로 표시하십시오.', + needsAction: '작업 필요', + doneCount: '완료', + searchPlaceholder: '작업 또는 명령 검색', + noNotices: '이 보기와 일치하는 알림이 없습니다.', + noUpdates: '사용 가능한 업데이트가 없습니다.', + published: '게시됨 {{date}}', + markDone: '완료로 표시', + dismiss: '해제', + reopen: '다시 열기', + doNext: '다음 작업', + impactedIntegrations: '영향받는 통합', + impactedDesc: '업데이트 범위 및 라우팅에 따른 관련 영역.', + whyMatters: '왜 중요한가', + whyMattersDesc: '짧은 컨텍스트만, 긴 릴리스 노트는 없습니다.', + open: '열기', + progressNeedsAction: '작업 필요', + progressInReview: '검토 중', + progressDone: '완료', + progressDismissed: '해제됨', + statusNew: '신규', + statusStable: '안정', + statusPlanned: '계획됨', + dashboard: '대시보드', + cliUsage: 'CLI 사용', + }, + cliproxyPage: { + connected: '연결됨', + notConnected: '연결되지 않음', + variant: '변형', + parentNotConnected: '상위가 연결되지 않음', + viaProvider: '{{provider}}을(를) 통해', + emptyTitle: 'CCS 프로필 관리자', + emptyDesc: + 'CLIProxy 프로바이더에 대한 OAuth 인증, 계정 환경설정 및 모델 선택을 관리합니다. CCS가 다양한 AI 백엔드로 요청을 라우팅하는 방법을 구성합니다.', + emptyControlPanelPrefix: + '실시간 사용 통계 및 실시간 모니터링을 보려면 다음을 방문하십시오:', + controlPanel: '제어판', + quickSetup: '빠른 설정', + addAccount: '계정 추가', + advancedVariant: '고급 변형', + setupActionsHint: + '여기에 계정을 추가하십시오. 별도의 런타임/프로필이 필요할 때만 변형을 생성하십시오.', + accountManagement: 'CCS 레벨 계정 관리', + providers: '프로바이더', + variants: '변형', + providerCount: '프로바이더 {{count}}개', + providerCount_other: '프로바이더 {{count}}개', + connectedCount: '연결됨 {{count}}개', + variantDisplay: '{{name}} ({{provider}} 변형)', + }, + copilotPage: { + title: 'Copilot', + subtitle: '지원 중단된 GitHub Copilot 호환성 브리지', + deprecatedBadge: '지원 중단', + deprecationTitle: '지원 중단된 호환성 브리지', + deprecationItem1: 'GitHub 사용량 기반 Copilot 청구는 2026년 6월 1일에 시작됩니다', + deprecationItem2: '기존 로컬 설정은 호환성을 위해 계속 사용할 수 있습니다', + deprecationItem3: '새 작업에는 Codex 또는 다른 활성 프로바이더를 사용하십시오', + setup: '설정', + auth: '인증', + daemon: '데몬', + unofficialTitle: '비공식 API - 본인 책임 하에 사용', + unofficialItem1: '리버스 엔지니어링된 API - 언제든지 중단될 수 있습니다', + unofficialItem2: '과도한 사용은 계정 제한을 유발할 수 있습니다', + unofficialItem3: 'CCS의 보증 또는 책임 없음', + yes: '예', + no: '아니요', + installed: '설치됨', + missing: '없음', + integration: '통합', + enabled: '활성화됨', + disabled: '비활성화됨', + github: 'GitHub', + connected: '연결됨', + notConnected: '연결되지 않음', + authenticate: '인증', + authenticating: '인증 중...', + status: '상태', + running: '실행 중', + stopped: '중지됨', + port: '포트', + stopping: '중지 중...', + stop: '중지', + starting: '시작 중...', + start: '시작', + installing: '설치 중...', + installCopilotApi: 'copilot-api 설치', + proxy: '프록시', + active: '활성', + inactive: '비활성', + }, + cursorPage: { + title: 'Cursor', + beta: '베타', + deprecated: '지원 중단', + subtitle: '레거시 Cursor 설정을 위한 지원 중단된 로컬 브리지', + unofficialTitle: '지원 중단된 레거시 브리지 - CLIProxy 기반 Cursor 사용 권장', + unofficialItem1: '지원되는 경로: CLIProxy 기반 Cursor 인증 및 계정 관리', + unofficialItem2: '이 리버스 엔지니어링된 로컬 브리지는 기존 설정용으로만 유지됩니다', + unofficialItem3: 'CCS는 이 레거시 경로에 대한 보증을 제공하지 않습니다', + supportedPathTitle: '지원되는 경로', + supportedPathDesc: + '새 설정에는 CLIProxy 기반 Cursor 인증 및 계정 관리를 사용하십시오. 이전 로컬 데몬 흐름에 여전히 의존하는 경우에만 아래의 레거시 브리지를 유지하십시오.', + startCliproxyAuth: 'CLIProxy Cursor 인증 시작', + openCliproxyCursor: 'CLIProxy Cursor 열기', + integration: '통합', + authentication: '인증', + daemon: '데몬', + enabled: '활성화됨', + disabled: '비활성화됨', + expired: '만료됨', + connected: '연결됨', + notConnected: '연결되지 않음', + running: '실행 중', + stopped: '중지됨', + actions: '레거시 작업', + disableIntegration: '통합 비활성화', + enableIntegration: '통합 활성화', + autoDetectAuth: '레거시 IDE 자동 감지', + manualAuthImport: '레거시 수동 가져오기', + stopDaemon: '데몬 중지', + startDaemon: '데몬 시작', + port: '포트', + configuration: 'Cursor 구성', + lastModified: '마지막 수정:', + neverSaved: '저장된 적 없음', + saving: '저장 중...', + save: '저장', + modelConfig: '모델 구성', + settings: '설정', + info: '정보', + presets: '프리셋', + presetsDesc: '사전 구성된 모델 매핑 적용', + modelMapping: '모델 매핑', + modelMappingDesc: '각 티어에 사용할 모델 구성', + defaultModel: '기본 모델', + defaultModelDesc: '특정 티어가 요청되지 않을 때 사용됩니다.', + opusModel: 'Opus (가장 강력)', + opusModelDesc: '복잡한 추론 및 최고 품질의 응답.', + sonnetModel: 'Sonnet (균형)', + sonnetModelDesc: '일반 코딩 및 일상적인 채팅 워크로드.', + haikuModel: 'Haiku (빠름)', + haikuModelDesc: '저지연 및 경량 요청 경로.', + runtimeSettings: '런타임 설정', + autoStartDaemon: '데몬 자동 시작', + autoStartDesc: '통합이 사용될 때 Cursor 데몬 자동 시작.', + ghostMode: '고스트 모드', + ghostModeDesc: '원격 측정을 줄이기 위해 x-ghost-mode 요청.', + provider: '프로바이더', + filePath: '파일 경로', + availableModels: '사용 가능한 모델', + loadingModels: '모델 로드 중...', + noModels: '아직 사용 가능한 모델 메타데이터가 없습니다. 데몬을 시작하고 새로 고치십시오.', + default: '기본값', + rawConfiguration: '원시 구성 (JSON)', + manualImportTitle: '수동 Cursor 인증 가져오기', + manualImportDesc: + '자동 감지를 사용할 수 없는 경우 Cursor 액세스 토큰과 머신 ID를 제공하십시오.', + accessToken: '액세스 토큰', + accessTokenPlaceholder: 'Cursor 액세스 토큰 붙여넣기', + machineId: '머신 ID', + machineIdPlaceholder: '32자 16진수 (하이픈 없는 UUID)', + cancel: '취소', + import: '가져오기', + selectModel: '모델 선택', + useDefaultModel: '기본 모델 사용', + availableModelCount: '사용 가능한 모델 ({{count}})', + invalidPort: '포트는 1에서 65535 사이의 정수여야 합니다', + defaultModelRequired: '기본 모델이 필요합니다', + savedConfig: 'Cursor 구성 및 모델 매핑이 저장되었습니다', + failedSaveConfig: '구성을 저장하지 못했습니다', + modelsLoadingWait: '모델이 아직 로드 중입니다. 프리셋을 적용하기 전에 기다리십시오.', + noModelsAvailable: + '아직 사용 가능한 모델이 없습니다. 먼저 데몬을 시작하고 새로 고치십시오.', + appliedCodexPreset: 'GPT-5.3 Codex 프리셋 적용됨', + appliedClaudePreset: 'Claude 4.6 프리셋 적용됨', + appliedGeminiPreset: 'Gemini 3 프리셋 적용됨', + integrationEnabled: 'Cursor 통합 활성화됨', + integrationDisabled: 'Cursor 통합 비활성화됨', + failedUpdateIntegration: '통합 상태 업데이트에 실패했습니다', + credentialsImported: 'Cursor 자격 증명을 가져왔습니다', + autoDetectFailed: '자동 감지 실패', + manualRequired: '토큰과 머신 ID가 필요합니다', + manualImportFailed: '수동 가져오기 실패', + failedStartDaemon: '데몬을 시작하지 못했습니다', + daemonStarted: '데몬이 시작되었습니다', + daemonStartedWithPid: '데몬이 시작되었습니다 (PID: {{pid}})', + failedStopDaemon: '데몬을 중지하지 못했습니다', + daemonStopped: '데몬이 중지되었습니다', + rawLoading: '원시 설정이 아직 로드 중입니다. 기다린 후 다시 시도하십시오.', + invalidJson: '잘못된 JSON', + rawSaved: '원시 설정이 저장되었습니다', + rawChanged: '원시 설정이 외부에서 변경되었습니다. 새로 고침 후 다시 시도하십시오.', + failedSaveRaw: '원시 설정을 저장하지 못했습니다', + savedAll: 'Cursor 구성이 저장되었습니다', + liveProbe: '라이브 프로브', + runLiveProbe: '라이브 프로브 실행', + rerunLiveProbe: '라이브 프로브 다시 실행', + probing: '프로브 실행 중...', + probeNotRun: '프로브가 아직 실행되지 않음', + probeLocalReadinessHint: + '로컬 준비 검사는 통과할 수 있지만 라이브 런타임 액세스는 여전히 실패할 수 있습니다. 전체 Cursor 경로를 확인하려면 라이브 프로브를 사용하십시오.', + probeStage: '단계', + probeHttpStatus: 'HTTP 상태', + probeDuration: '기간', + probeModel: '모델', + probeMessage: '메시지', + probeSucceeded: '프로브 성공', + probeFailed: '프로브 실패', + probeSaveFirst: '라이브 프로브를 실행하기 전에 Cursor 변경 사항을 저장하거나 폐기하십시오', + refreshStatus: 'Cursor 상태 새로 고침', + refreshConfiguration: 'Cursor 구성 새로 고침', + }, + droidPage: { + loadingDiagnostics: 'Droid 진단 로드 중...', + failedDiagnostics: 'Droid 진단을 로드하지 못했습니다.', + overview: '개요', + byok: 'BYOK', + docs: '문서', + runtimeInstall: '런타임 및 설치', + status: '상태', + detected: '감지됨', + notFound: '찾을 수 없음', + detectionSource: '감지 소스', + binaryPath: '바이너리 경로', + installDirectory: '설치 디렉터리', + version: '버전', + overridePath: '재정의 (CCS_DROID_PATH)', + configFiles: '구성 파일', + path: '경로', + resolved: '해결됨', + size: '크기', + lastModified: '마지막 수정', + parseWarning: '구문 분석 경고: {{value}}', + readWarning: '읽기 경고: {{value}}', + warnings: '경고', + byokSummary: 'BYOK 요약', + activeModelSelector: '활성 모델 선택기', + customModels: '사용자 정의 모델', + ccsManaged: 'CCS 관리', + userManaged: '사용자 관리', + malformedEntries: '형식이 잘못된 항목', + providers: '프로바이더', + none: '없음', + customModelsTitle: '사용자 정의 모델', + modelName: '이름 / 모델', + provider: '프로바이더', + baseUrl: 'Base URL', + noCustomModels: '사용자 정의 모델 없음', + docsAlignedNotes: '문서 정렬 노트', + factoryDocs: 'Factory 문서', + providerFactCheckDocs: '프로바이더 팩트 체크 문서', + providerValues: '프로바이더 값: {{value}}', + settingsHierarchy: '설정 계층: {{value}}', + settingsTitle: 'Droid BYOK 설정', + fixJsonBeforeQuickSettings: '빠른 설정 컨트롤을 사용하기 전에 JSON 구문을 수정하십시오.', + fixJsonBeforeReasoning: 'BYOK 추론 설정을 업데이트하기 전에 JSON 구문을 수정하십시오.', + unableUpdateReasoning: '선택한 BYOK 모델 추론 설정을 업데이트할 수 없습니다.', + fixJsonBeforeBudget: '사고 예산을 업데이트하기 전에 JSON 구문을 수정하십시오.', + anthropicOnlyBudget: '사고 예산은 Anthropic BYOK 모델에만 사용할 수 있습니다.', + invalidJson: '잘못된 JSON: {{value}}', + saved: 'Droid 설정이 저장되었습니다', + changedExternally: 'Droid 설정이 외부에서 변경되었습니다. 새로 고침 후 다시 시도하십시오.', + failedSave: 'Droid 설정을 저장하지 못했습니다', + }, + sharedPage: { + commands: '명령', + skills: '스킬', + agents: '에이전트', + plugins: '플러그인', + settings: '설정', + title: '공유 리소스', + subtitle: '계정 간에 공유되는 명령, 스킬, 에이전트, 플러그인 및 구성', + totalShared: '총 리소스', + visible: '표시됨', + markdownDetail: '마크다운 상세 보기', + registryDetail: '레지스트리 상세 보기', + maskedSettingsDetail: '마스킹된 설정 보기', + filterPrefix: '필터:', + configurationRequired: '구성이 필요합니다', + countsUnavailable: '개수 사용 불가', + retryCounts: '개수 재시도', + filterPlaceholder: '이름, 설명 또는 경로로 {{tab}} 필터링', + showing: '총 {{total}}개 {{tab}} 중 {{visible}}개 표시', + showingQuery: ' "{{query}}"에 대해', + refreshing: ' (새로 고침 중...)', + loadingShared: '공유 {{tab}} 로드 중...', + failedLoadShared: '공유 {{tab}}을(를) 로드하지 못했습니다', + retry: '재시도', + noSharedFound: + '공유 {{tab}}을(를) 찾을 수 없습니다. `ccs sync`를 실행하거나 공유 디렉터리에 항목을 추가하십시오.', + noPluginsFound: + '설치된 공유 플러그인이 없습니다. 실제 플러그인이 있을 때까지 플러그인 레지스트리 파일과 캐시 폴더는 숨겨집니다.', + noMatch: '"{{query}}"과(와) 일치하는 {{tab}}이(가) 없습니다.', + selectOne: '전체 내용을 보려면 {{tab}}을(를) 선택하십시오.', + pathLabel: '경로', + resolvedSource: '해결된 소스', + loadingMarkdown: '마크다운 콘텐츠 로드 중...', + loadingSettings: '설정 콘텐츠 로드 중...', + failedLoadContent: '콘텐츠를 로드하지 못했습니다', + retryContent: '콘텐츠 재시도', + noMarkdown: '사용 가능한 마크다운 콘텐츠가 없습니다.', + settingsTitle: 'settings.json', + settingsDescription: + '이 파일에는 모든 공유 모드 계정 간에 연결된 공유 설정이 포함되어 있습니다.', + settingsPath: '공유 설정 경로', + settingsActive: '활성', + settingsInactive: '찾을 수 없음', + resourcePolicies: '리소스 정책', + resourcePoliciesDescription: + '공유로 표시된 계정은 이 허브를 상속합니다. 프로필 로컬 계정은 별도의 명령, 스킬, 에이전트, 플러그인 및 설정을 유지합니다.', + sharedAccounts: '공유 {{count}}개', + profileLocalAccounts: '프로필 로컬 {{count}}개', + moreProfileLocalAccounts: '+{{count}}개 더', + }, + editAccountSharedResources: { + title: '공유 리소스 편집', + description: + '"{{name}}"이(가) CCS 공유 디렉터리에서 명령, 스킬 및 설정을 상속하는 방법을 구성합니다.', + resourceMode: '리소스 모드', + selectResourceMode: '리소스 모드 선택', + sharedOption: '공유', + sharedHint: '공유 디렉터리에서 명령, 스킬, 에이전트를 상속합니다.', + profileLocalOption: '프로필 로컬', + profileLocalHint: '계정의 비공개 디렉터리에서 격리된 리소스를 사용합니다.', + implicationTitle: '의미', + sharedImplication: '이 계정은 공유 리소스 허브의 모든 도구와 구성을 볼 수 있습니다.', + profileLocalImplication: + '이 계정은 공유 도구를 볼 수 없습니다. 보안 또는 테스트를 위해 완전히 격리된 상태로 유지됩니다.', + cancel: '취소', + save: '저장', + saving: '저장 중...', + }, + + // ======================================== + // Domain 1: Navigation / Layout / Shared + // ======================================== + heroSection: { + title: 'CCS Config', + subtitle: 'Claude Code Switch 대시보드', + }, + hubFooter: { + logs: '로그', + settings: '설정', + github: 'GitHub', + copyright: '© {{year}} kaitranntt', + }, + themeToggle: { + srLabel: '테마 전환', + }, + ccsLogo: { + alt: 'CCS 로고', + text: 'CCS Config', + }, + claudekitBadge: { + title: 'ClaudeKit 프레임워크 기반', + alt: 'ClaudeKit', + poweredBy: 'Powered by', + claudekit: 'ClaudeKit', + }, + codeEditor: { + revealSensitive: '민감한 값 표시', + maskSensitive: '민감한 값 마스킹', + valid: '유효한 {{language}}', + readOnly: '(읽기 전용)', + }, + commandBuilder: { + title: '명령 빌더', + searchPlaceholder: '명령을 입력하거나 선택...', + copy: '복사', + run: '실행', + cmdConfig: '구성 인터페이스 열기', + cmdCreateProfile: '새 프로필 생성', + cmdSwitchProfile: '프로필로 전환', + cmdDoctor: '시스템 헬스 확인', + cmdListProviders: '사용 가능한 CLIProxy 프로바이더 나열', + cmdAddProvider: 'CLIProxy 프로바이더 추가', + }, + confirmDialog: { + confirm: '확인', + cancel: '취소', + }, + connectionIndicator: { + connected: '연결됨', + connecting: '연결 중...', + disconnected: '연결 끊김', + reconnecting: '재연결 중...', + }, + docsLink: { + title: '문서 보기', + }, + githubLink: { + title: 'GitHub에서 이슈 보고', + }, + globalEnvIndicator: { + injectedCount_one: '런타임에 글로벌 환경 변수 {{count}}개가 주입됩니다', + injectedCount_other: '런타임에 글로벌 환경 변수 {{count}}개가 주입됩니다', + overriddenCount: '(프로필에 의해 {{count}}개 재정의됨)', + skippedLabel: '건너뜀 (프로필이 이미 정의함):', + configureInSettings: '설정에서 구성', + }, + localhostDisclaimer: { + remoteReadonlyAuthDisabledLong: + '이 CCS 인스턴스의 대시보드 인증이 현재 비활성화되어 있기 때문에 원격 대시보드 액세스는 읽기 전용입니다. CCS 호스트에서 다시 활성화하십시오. Docker 배포는 실행 중인 컨테이너 내부에서 수행해야 합니다.', + remoteReadonlyAuthDisabledShort: + '이 CCS 인스턴스에 대시보드 인증이 다시 활성화될 때까지 원격 대시보드는 읽기 전용입니다.', + remoteReadonlySetupLong: + '이 CCS 인스턴스에 대해 ccs config auth setup을 실행할 때까지 원격 대시보드 액세스는 읽기 전용입니다. Docker 배포는 컨테이너 내부에서 실행해야 합니다.', + remoteReadonlySetupShort: + '이 CCS 인스턴스에 인증이 구성될 때까지 원격 대시보드는 읽기 전용입니다.', + localLong: '이 대시보드는 로컬에서 실행됩니다. 모든 데이터는 사용자의 머신에 머무릅니다.', + localShort: '로컬 대시보드 - 데이터는 디바이스에 머무릅니다.', + dismiss: '면책 조항 해제', + }, + privacyToggle: { + modeOn: '개인 정보 보호 모드 켜짐 - 데이터를 표시하려면 클릭', + modeOff: '개인 정보 보호 모드 꺼짐 - 데이터를 숨기려면 클릭', + }, + projectSelectionDialog: { + title: 'Google Cloud 프로젝트 선택', + description: '{{provider}} 인증에 사용할 프로젝트를 선택하십시오.', + autoSelectCountdown: '({{count}}초 후 기본값 자동 선택)', + default: '기본값', + allProjects: '모든 프로젝트', + allProjectsDescription: '나열된 모든 프로젝트 {{count}}개 온보딩', + useDefault: '기본값 사용', + selecting: '선택 중...', + confirmSelection: '선택 확인', + codeCopied: '코드 복사됨', + copyVerificationCode: '검증 코드 복사', + }, + quickCommands: { + title: '빠른 명령', + startDefault: '기본값 시작', + startDefaultDesc: '기본 프로필로 Claude 실행', + glmProfile: 'GLM 프로필', + glmProfileDesc: 'GLM 모델로 전환', + healthCheck: '헬스 체크', + healthCheckDesc: '시스템 진단 실행', + delegateTask: '작업 위임', + delegateTaskDesc: 'GLM 프로필에 위임', + }, + quotaTooltip: { + loadingQuota: '쿼터 로드 중...', + failedLoadQuota: '쿼터를 로드하지 못했습니다', + modelQuotas: '모델 쿼터:', + rateLimits: '속도 제한:', + plan: '플랜: {{plan}}', + quotaSnapshots: '쿼터 스냅샷:', + unlimited: '무제한', + remaining: '{{remaining}}/{{entitlement}} 남음', + tier: '티어', + tierId: '티어 ID', + state: '상태', + credits: '크레딧', + modelQuotasLower: '모델 쿼터:', + allBucketsReport: '모든 버킷이 {{tokenType}} 보고', + requestsRemaining: '요청 {{count}}개 남음', + inputTokensRemaining: '입력 토큰 {{count}}개 남음', + outputTokensRemaining: '출력 토큰 {{count}}개 남음', + amountRemaining: '{{count}} 남음', + fiveHourLimit: '5시간 사용 한도', + weeklyLimit: '주간 사용 한도', + weeklyOpus: '주간 사용 (Opus)', + weeklySonnet: '주간 사용 (Sonnet)', + weeklyOAuthApps: '주간 사용 (OAuth 앱)', + weeklyCowork: '주간 사용 (Cowork)', + extraUsage: '추가 사용량', + premiumInteractions: '프리미엄 상호 작용', + chat: '채팅', + completions: '완료', + resets: '{{time}}에 재설정', + fiveHourResets: '{{time}}에 5시간 재설정', + weeklyResets: '{{time}}에 주간 재설정', + }, + utils: { + codeReview5h: '코드 리뷰 (5시간)', + codeReviewWeekly: '코드 리뷰 (주간)', + codeReview: '코드 리뷰', + codexAdditional5h: '{{name}} (5시간)', + codexAdditionalWeekly: '{{name}} (주간)', + codexAdditional: '{{name}}', + }, + sponsorButton: { + title: 'GitHub에서 이 프로젝트 후원', + sponsor: '후원', + }, + valueMetrics: { + apiCostSaved: '절약된 API 비용', + tokensSaved: '절약된 토큰', + queriesFaster: '쿼리 가속', + errorsReduced: '오류 감소', + vsLastMonth: '지난 달 대비', + throughCaching: '캐싱을 통해', + averageSpeedup: '평균 가속', + withRetryLogic: '재시도 로직 포함', + performanceMetrics: '성능 지표', + monthlySummary: '월간 요약', + totalSaved: '총 절약', + tokensProcessed: '처리된 토큰', + queriesHandled: '처리된 쿼리', + uptime: '가동 시간', + }, + updatesSpotlight: { + openUpdatesCenter: '업데이트 센터 열기', + }, + deviceCodeDialog: { + authorize: '{{provider}} 인증', + enterCodeAtPage: '인증 페이지에서 아래 코드를 입력하십시오.', + expiresIn: '({{time}} 후 만료)', + codeExpired: '(코드 만료됨)', + copied: '복사됨!', + copyCode: '코드 복사', + waitingForAuth: '인증 대기 중...', + openVerificationPage: '검증 페이지 열기', + openProviderPage: '{{provider}} 열기', + copyCodeAria: '검증 코드 복사', + codeCopiedAria: '코드 복사됨', + }, + settingsDialog: { + editProfile: '프로필 편집: {{name}}', + description: '이 프로필의 환경 변수 및 설정을 구성합니다.', + loadingSettings: '설정 로드 중...', + envTab: '환경 변수', + rawJsonTab: '원시 JSON', + generalTab: '일반', + noEnvVars: '구성된 환경 변수가 없습니다.', + noEnvVarsHint: 'settings.json 파일에 변수를 추가하십시오.', + loadingEditor: '편집기 로드 중...', + profileInfo: '프로필 정보', + profileInfoDesc: '이 구성 파일에 대한 세부 정보.', + path: '경로', + lastModified: '마지막 수정', + cancel: '취소', + saving: '저장 중...', + saveChanges: '변경 사항 저장', + conflictTitle: '파일이 외부에서 수정됨', + conflictDesc: + '이 설정 파일이 다른 프로세스에 의해 수정되었습니다. 변경 사항으로 덮어쓰시겠습니까, 폐기하시겠습니까?', + overwrite: '덮어쓰기', + invalidJson: '잘못된 JSON', + failedSave: '저장 실패', + }, + + // ======================================== + // Domain 2: Accounts / Auth + // ======================================== + setupWizard: { + title: '고급 변형 설정', + stepProviderDesc: '런타임 변형을 위한 프로바이더 선택', + stepAuthDesc: '프로바이더로 인증', + stepAccountDesc: '사용할 계정 선택', + stepVariantDesc: '선택 사항: 사용자 정의 런타임 변형 생성', + stepSuccessDesc: '설정 완료!', + authStep: { + authenticateWith: '계정을 추가하려면 {{provider}}로 인증하십시오', + authenticating: '인증 중...', + authenticateInBrowser: '브라우저에서 인증', + completeOAuth: '브라우저에서 OAuth 흐름을 완료하십시오...', + orUseTerminal: '또는 터미널 사용', + runCommandHint: '터미널에서 이 명령을 실행하십시오:', + back: '뒤로', + checking: '확인 중...', + refreshStatus: '상태 새로 고침', + }, + accountStep: { + selectAccount: '계정 선택 ({{count}})', + defaultAccount: '기본 계정', + or: '또는', + addNewAccount: '새 계정 추가', + addNewAccountDesc: '다른 계정으로 인증', + back: '뒤로', + }, + variantStep: { + back: '뒤로', + skip: '건너뛰기', + }, + successStep: { + title: '변형이 생성되었습니다!', + subtitle: '사용자 정의 변형을 사용할 준비가 되었습니다', + usage: '사용법:', + done: '완료', + }, + }, + accountSurfaceCard: { + business: '비즈', + free: '무료', + personal: '개인', + variant: '변형', + }, + accountIdentity: { + business: '비즈니스', + personal: '개인', + free: '무료', + team: '팀', + plus: 'Plus', + pro: 'Pro', + workspace: '워크스페이스 {{id}}', + }, + accountCardStats: { + notUsedYet: '아직 사용되지 않음', + }, + accountQuotaPanel: { + weekly: '주간', + loadingQuota: '쿼터 로드 중...', + }, + userMenu: { + signedInAs: '{{username}}(으)로 로그인됨', + }, + authMonitorLive: { + live: '실시간', + accountMonitor: '계정 모니터', + updated: '업데이트됨 {{time}}', + updatedNow: '방금 업데이트됨', + requestsLabel: '요청', + stats: '통계', + successRate: '성공률', + missingProjectId: '프로젝트 ID 누락', + noActivity: '활동 없음', + }, + providerCard: { + missingProjectIdAria: '프로젝트 ID 누락', + }, + loginPage: { + showPassword: '비밀번호 표시', + hidePassword: '비밀번호 숨기기', + }, + + // ======================================== + // Domain 3: CLIProxy / Provider Editor + // ======================================== + cliproxyStatsOverview: { + sessionStatistics: '세션 통계', + realTimeMetrics: '{{backend}}의 실시간 사용 지표', + offline: '오프라인', + running: '실행 중', + noActiveSession: '활성 세션 없음', + noActiveSessionHint: + '실시간 통계를 보려면 ccs gemini, ccs codex 또는 ccs agy를 사용하여 CLIProxy 세션을 시작하십시오.', + failedLoadStats: '통계를 로드하지 못했습니다', + totalRequests: '총 요청', + successCount: '성공 {{count}}개', + successRate: '성공률', + totalTokens: '총 토큰', + estimatedCost: '~${{cost}} 추정', + modelsUsed: '사용된 모델', + modelUsageDistribution: '모델 사용 분포', + requestCount: '요청 {{count}}개', + }, + cliproxyTable: { + name: '이름', + provider: '프로바이더', + model: '모델', + account: '계정', + status: '상태', + default: '기본값', + actions: '작업', + }, + cliproxyTabs: { + overview: '개요', + variants: '변형', + aiProviders: 'AI 프로바이더', + controlPanel: '제어판', + }, + cliproxyHeader: { + ccsLevelAccountManagement: 'CCS 레벨 계정 관리', + cliproxyNotAvailable: 'CLIProxy를 사용할 수 없음', + cliproxyControlPanel: 'CLIProxy 제어판', + noVariants: 'CLIProxy 변형을 찾을 수 없습니다.', + addAccountToStart: '시작하려면 계정을 추가하십시오', + }, + routingGuidance: { + roundRobin: '라운드 로빈은 사용량을 분산합니다.', + fillFirst: '먼저 채우기는 필요할 때까지 백업 계정을 차갑게 유지합니다.', + routingStrategy: '라우팅 전략', + optionalRouting: '선택적 라우팅', + sessionAffinity: '세션 어피니티', + sessionAffinityOn: '켜짐', + sessionAffinityOff: '꺼짐', + sessionAffinityEnabled: '활성화됨', + sessionAffinityDisabled: '비활성화됨', + enableSessionAffinity: '세션 어피니티 활성화', + disableSessionAffinity: '세션 어피니티 비활성화', + sessionAffinityUnavailable: '세션 어피니티 사용 불가', + localOnly: '로컬 전용', + localOnlySetting: '로컬 전용 설정', + ttlBadge: 'TTL {{ttl}}', + sessionAffinityDescription: + '가능한 경우 한 대화를 동일한 계정에 고정합니다. CLIProxy는 클라이언트가 보낼 때 명시적 세션 또는 스레드 식별자를 선호한 다음, 안정적인 키를 추론해야 할 때 요청 메타데이터 또는 시작 프롬프트 기록으로 폴백합니다.', + sessionRecognitionTitle: '세션 인식', + sessionRecognitionDescription: + 'CCS는 여기서 보편적인 우선순위를 약속하지 않습니다. 실제로 업스트림 백엔드는 명시적 세션 또는 스레드 ID를 먼저 선호한 다음, 메타데이터 필드로 폴백하고 최종적으로 시작 프롬프트 기록 기반 해시로 폴백합니다.', + }, + extendedContext: { + extendedContext: '확장 컨텍스트', + }, + cliproxyConfig: { + unsavedChanges: '저장되지 않은 변경 사항', + original: '원본', + modified: '수정됨', + reviewChanges: '변경 사항 검토', + loadingEditor: '편집기 로드 중...', + }, + providerEditor: { + provider: '프로바이더', + filePath: '파일 경로', + lastModified: '마지막 수정', + defaultTarget: '기본 대상', + quickUsage: '빠른 사용', + modelMapping: '모델 매핑', + status: '상태', + loadingSettings: '설정 로드 중...', + loadingEditor: '편집기 로드 중...', + accounts: '계정', + addAccount: '계정 추가', + noAccountsConnected: '연결된 계정 없음', + addAccountToStart: '시작하려면 계정을 추가하십시오', + gcpProjectIdReadonly: 'GCP 프로젝트 ID (읽기 전용)', + projectIdNA: '프로젝트 ID: N/A', + missingProjectId: '프로젝트 ID 누락', + missingProjectIdHint: + '이로 인해 오류가 발생할 수 있습니다. 프로젝트 ID를 가져오려면 계정을 제거하고 다시 추가하십시오.', + useIncognito: '시크릿 사용', + aliases: '별칭', + current: '현재', + currentValue: '현재 값', + composite: '복합', + defaultLabel: '기본값', + requiredSetup: '필수 설정', + connectorName: '커넥터 이름', + proxyUrl: '프록시 URL', + proxyUrlSet: '프록시 URL 설정됨', + excludedModels: '제외된 모델', + headers: '헤더', + secret: '시크릿', + prefix: '접두사', + modelMappings: '모델 매핑', + baseUri: 'Base URL', + apiKeys: 'API 키', + presets: '사전 구성된 모델 매핑 적용', + createVariant: 'CLIProxy 변형 생성', + agyDenylist: + 'Antigravity 거부 목록: Claude Opus 4.5 및 Claude Sonnet 4.5는 지원 중단되었습니다.', + }, + providerEditorAccountItem: { + modelsUsed: '사용된 모델', + }, + bulkActionBar: { + applyPreset: '프리셋 적용', + }, + modelConfigSection: { + defaultModel: '기본 모델', + }, + rawEditorSection: { + rawConfig: '원시 구성', + }, + providerEditorHeader: { + connectorName: '커넥터 이름', + }, + aiProvidersFamilyRail: { + current: '현재', + }, + aiProvidersEntryCard: { + apiKeys: 'API 키', + }, + aiProvidersEntryDialog: { + connectorName: '커넥터 이름', + baseUri: 'Base URL', + proxyUrl: '프록시 URL', + secret: '시크릿', + prefix: '접두사', + excludedModels: '제외된 모델', + headers: '헤더', + modelMappings: '모델 매핑', + requiredSetup: '필수 설정', + optionalRouting: '선택적 라우팅', + }, + + // ======================================== + // Domain 4: Compatible CLI Tabs + // ======================================== + codex: { + controlCenter: '제어 센터', + overview: '개요', + docs: '문서', + nativeCodexRuntime: '네이티브 Codex 런타임', + ccsCodexProvider: 'Cliproxy 단축키 / 관리 브리지', + codexDocs: 'Codex 문서', + howCodexWorks: 'CCS에서 Codex 작동 방식', + supportedFlows: '지원되는 흐름', + twoSupportedPaths: '지원되는 두 가지 경로:', + nativeLabel: '네이티브:', + nativeDesc: 'Codex는 CCS v1의 일급 런타임 전용 대상입니다.', + nativeConfigLabel: '네이티브 구성:', + nativeConfigDesc: 'ccs-codex 및 ccsx는 저장된 기본값으로 네이티브 Codex를 시작합니다.', + transientOverridesLabel: '일시적 재정의:', + transientOverridesDesc: + 'ccsxp는 네이티브 Codex에 머물면서 cliproxy 프로바이더 재정의를 앞에 추가합니다; ccs codex --target codex는 명시적 CCS 관리 브리지로 유지됩니다.', + cliproxyDefaultLabel: 'CLIProxy 기본값:', + cliproxyDefaultDesc: + '단순한 codex가 CLIProxy를 사용하도록 하려면, model_provider = "cliproxy"로 설정하고 아래 레시피를 추가하십시오.', + ccsBridge: 'CCS 브리지', + apiProfilesDefault: 'API 프로필은 계속 Claude 또는 Droid를 기본으로 합니다.', + runtimeInstall: '런타임 설치', + detected: '감지됨', + notFound: '찾을 수 없음', + detectionSource: '감지 소스', + binaryPath: '바이너리 경로', + installDirectory: '설치 디렉터리', + versionLabel: '버전', + nativeAliases: '네이티브 별칭', + ccsProviderShortcut: 'Cliproxy 단축키', + configOverrideSupport: '--config 재정의 지원', + available: '사용 가능', + missing: '없음', + cliproxyNativeCodex: 'CLIProxy 기반 네이티브 Codex', + builtInLabel: '내장:', + builtInCcsxpDesc: + 'cliproxy 프로바이더 단축키를 사용하는 네이티브 Codex에는 ccsxp를 사용하십시오.', + managedBridgeLabel: '관리 브리지:', + managedBridgeDesc: + '더 엄격한 CCS 관리 라우트를 명시적으로 원할 때 ccs codex --target codex를 사용하십시오.', + nativeRecipeLabel: '네이티브:', + nativeRecipeDesc: 'codex로 CLIProxy를 직접 사용하려면 아래 레시피를 구성하십시오.', + saveProviderNamedCliproxy: + '위의 base URL과 환경 변수 키로 cliproxy라는 이름의 프로바이더를 저장하십시오.', + inTopLevelSetDefault: '최상위 설정에서 기본 프로바이더를 cliproxy로 설정하십시오.', + exportCliproxyApiKey: + '네이티브 Codex를 시작하기 전에 셸에서 CLIPROXY_API_KEY를 내보내십시오.', + noConfigOverrides: + '이 Codex 빌드는 여전히 일반 네이티브 경로를 사용할 수 있지만, 감지된 Codex 바이너리가 --config 재정의를 노출할 때까지 ccsxp 및 명시적 CCS 관리 Codex 브리지는 사용할 수 없습니다.', + configFile: '구성 파일', + path: '경로', + resolved: '해결됨', + size: '크기', + lastModified: '마지막 수정', + tomlWarning: 'TOML 경고', + readWarning: '읽기 경고', + currentUserLayerSummary: '현재 사용자 레이어 요약', + activeProfile: '활성 프로필', + notSet: '설정되지 않음', + providersCount: '프로바이더: {{count}}', + profilesCount: '프로필: {{count}}', + enabledFeaturesCount: '활성화된 기능: {{count}}', + mcpServersCount: 'MCP 서버: {{count}}', + userLayerKeysPresent: '사용자 레이어 키 존재', + recommendedSetupFlow: '권장 설정 흐름', + fastestPath: '가장 빠른 경로', + officialChannels: '공식 채널', + codexCli: 'Codex CLI', + openNativeCodex: '네이티브 Codex 열기', + runBuiltInCodex: 'cliproxy 단축키로 네이티브 Codex 실행', + runBuiltInCodexExplicit: 'CCS 관리 Codex 브리지를 명시적으로 실행', + openCodexDashboard: 'Codex 대시보드 열기', + nativeShortAlias: '네이티브 짧은 별칭', + ccsCodexShortcut: 'Cliproxy 단축키', + explicitProviderRoute: '관리 브리지 라우트', + status: '상태', + profiles: '프로필', + createNewProfile: '새 프로필 생성', + createNewProvider: '새 프로바이더 생성', + createNewMcpServer: '새 MCP 서버 생성', + defaultProvider: '기본 프로바이더', + useDefault: '기본값 사용', + useGlobalProvider: '글로벌 프로바이더 사용', + useProviderDefault: '프로바이더 기본값 사용', + quickFillWarning: '빠른 채우기 전용. 저장하기 전에 검토하십시오.', + thisFileUpstreamOwned: '이 파일은 Codex CLI에 의해 업스트림 소유됩니다.', + notes: '노트', + approvalPolicy: '승인 정책', + sandboxMode: '샌드박스 모드', + reasoningEffort: '추론 강도', + useGlobalEffort: '글로벌 강도 사용', + reasoningEffortCapitalized: '추론 강도', + thinkingBudgetTokens: '사고 예산 토큰', + modelContextWindow: '모델 컨텍스트 윈도우', + autoCompactTokenLimit: '자동 압축 토큰 한도', + toolOutputTokenLimit: '도구 출력 토큰 한도', + webSearch: '웹 검색', + personality: '개성', + model: '모델', + rawOnly: '원시 전용', + trusted: '신뢰됨', + untrusted: '신뢰되지 않음', + noProjectTrustEntries: '저장된 명시적 프로젝트 신뢰 항목이 없습니다.', + codexNativeRecipe: '저장된 네이티브 Codex 레시피', + runtimeVsProvider: '런타임 vs 프로바이더', + honorsSavedNativeConfig: '저장된 네이티브 사용자 구성을 따름', + usesTransientOverrides: '일시적 재정의 사용', + unavailableNoConfig: '사용 불가 (Codex 빌드에 --config 지원 부족).', + gptContextCap: 'GPT-5.4 컨텍스트 상한', + usageLimitCost: '272K 초과 사용 한도 비용', + longContextOverride: '긴 컨텍스트 재정의', + counts2x: '2배 카운트', + normalUsageWindow: '정상 사용 윈도우', + useCodexDefault: 'Codex 기본값 사용', + stdio: 'stdio', + streamableHttp: 'streamable-http', + responses: 'responses', + defaultTargetCli: '기본 대상 CLI', + executionChain: '실행 체인', + targetPath: '현재 대상 경로', + userConfig: '사용자 구성', + configYaml: 'config.yaml', + flow: '흐름', + docsTab: '문서', + yes: '예', + no: '아니요', + warningsTitle: '경고', + features: '기능', + featuresDesc: 'CCS가 안전하게 관리할 수 있는 지원되는 Codex 기능 플래그를 전환합니다.', + configOnlyFlags: '기존 구성 전용 플래그', + configOnlyFlagsDesc: + '이러한 기능 키는 이미 `config.toml`에 존재하므로 CCS는 전체 카탈로그 범위를 주장하지 않고 표시할 수 있습니다.', + existing: '기존', + nonBooleanForm: '비-부울 형식으로 저장되었습니다. 편집하려면 원시 TOML을 사용하십시오.', + discoveredFromFile: 'CCS 내장 카탈로그가 아닌 현재 파일에서 발견되었습니다.', + featureMultiAgentLabel: '멀티 에이전트', + featureMultiAgentDesc: '서브 에이전트 협업 도구를 활성화합니다.', + featureUnifiedExecLabel: '통합 실행', + featureUnifiedExecDesc: 'PTY 기반 통합 실행 도구를 사용합니다.', + featureShellSnapshotLabel: '셸 스냅샷', + featureShellSnapshotDesc: '셸 환경 스냅샷을 재사용합니다.', + featureApplyPatchLabel: '패치 적용', + featureApplyPatchDesc: '자유 형식 apply_patch 편집을 활성화합니다.', + featureJsReplLabel: 'JS REPL', + featureJsReplDesc: 'Node 기반 JavaScript REPL을 활성화합니다.', + featureRuntimeMetricsLabel: '런타임 메트릭', + featureRuntimeMetricsDesc: 'Codex 런타임 메트릭을 수집합니다.', + featurePreventIdleSleepLabel: '유휴 절전 방지', + featurePreventIdleSleepDesc: '활성 상태에서 머신을 깨어 있게 유지합니다.', + featureFastModeLabel: '빠른 모드', + featureFastModeDesc: '빠른 서비스 티어 경로를 허용합니다.', + featureAppsLabel: '앱', + featureAppsDesc: 'ChatGPT 앱 및 커넥터 지원을 활성화합니다.', + featureSmartApprovalsLabel: '스마트 승인', + featureSmartApprovalsDesc: '가디언 흐름을 통해 적격 승인을 라우팅합니다.', + }, + droidSettings: { + quickControls: '빠른 제어', + reasoningControls: '추론 제어', + thinkingBudget: '사고 예산', + anthropicOnly: 'Anthropic 모델만', + byokCustomModels: 'BYOK 사용자 정의 모델', + }, + rawJsonSettingsEditor: { + title: '원시 설정 편집기', + }, + copilotConfigForm: { + copilotConfiguration: 'Copilot 구성', + deprecatedModels: '지원 중단된 Copilot 모델이 감지되었습니다', + failedLoadStatus: '상태를 로드하지 못했습니다', + useWithClaudeCode: 'GitHub Copilot 구독을 Claude Code와 함께 사용', + githubCopilotControls: 'GitHub Copilot이 업스트림에서 프롬프트/컨텍스트 한도를 제어합니다.', + provider: '프로바이더', + filePath: '파일 경로', + status: '상태', + enabled: '활성화됨', + disabled: '비활성화됨', + loadingEditor: '편집기 로드 중...', + modelMapping: '모델 매핑', + quickUsage: '빠른 사용', + noPremiumUsage: '프리미엄 사용량 개수 없음', + }, + copilotPresets: { + gpt5Codex: 'GPT-5.3 Codex', + claude46: 'Claude 4.6', + gemini3: 'Gemini 3', + }, + + // ======================================== + // Domain 5: Logs / Monitoring / Health / Analytics + // ======================================== + healthCard: { + allSystemsNominal: '모든 시스템 정상', + machineChecks: '머신 검사', + }, + analyticsCards: { + cacheCost: '캐시 비용', + hitRate: '적중률', + inputOutputRatio: '입력/출력 비율', + noCacheData: '사용 가능한 캐시 데이터가 없습니다', + noModelData: '사용 가능한 모델 데이터가 없습니다', + noSessionData: '사용 가능한 세션 데이터가 없습니다', + noTokenData: '사용 가능한 토큰 데이터가 없습니다', + totalCost: '총 비용', + totalTokens: '총 토큰', + usageInsights: '사용 인사이트', + }, + dateRangeFilter: { + pickADate: '날짜 선택', + }, + logsConfig: { + level: '수준', + message: '메시지', + source: '소스', + time: '시간', + proc: '프로세스', + open: '열기', + run: '실행', + refreshEntries: '항목 새로 고침', + }, + logsDetailPanel: { + details: '상세', + }, + logsFilters: { + filters: '필터', + }, + logsOverviewCards: { + overview: '개요', + }, + logsPageSkeleton: { + loadingLogs: '로그 로드 중...', + }, + monitoringErrorLogs: { + logContent: '로그 내용', + }, + analyticsPages: { + chartsGrid: '차트', + costByModel: '모델별 비용', + }, + + // ======================================== + // Domain 6: Hooks / Toasts / Error Transport + // ======================================== + toasts: { + profileCreated: '프로필이 성공적으로 생성되었습니다', + profileUpdated: '프로필이 성공적으로 업데이트되었습니다', + profileDeleted: '프로필이 성공적으로 삭제되었습니다', + orphanProfilesComplete: '고아 프로필 등록이 완료되었습니다', + profileCopied: '프로필이 성공적으로 복사되었습니다', + profileImported: '프로필을 성공적으로 가져왔습니다', + authRequired: '{{provider}} 인증이 필요합니다', + authSuccess: '{{provider}} 인증 성공!', + authFailed: '{{provider}} 인증 실패', + deviceCodeExpired: '디바이스 코드가 만료되었습니다. 다시 시도하십시오.', + codeCopied: '코드가 클립보드에 복사되었습니다', + failedCopy: '코드 복사에 실패했습니다', + configSaved: '구성이 성공적으로 저장되었습니다', + configSaveFailed: '저장 실패: {{error}}', + invalidYaml: '잘못된 YAML을 저장할 수 없습니다', + configUpdatedExternally: '구성이 외부에서 업데이트되었습니다', + settingsFileUpdated: '설정 파일이 업데이트되었습니다', + accountsUpdated: '계정이 업데이트되었습니다', + noProfilesToSync: '동기화할 프로필이 없습니다', + syncFailed: '동기화 실패: {{error}}', + sessionAffinityUpdated: '세션 어피니티 {{state}}.', + providerAuthSuccess: '{{provider}} 인증 성공', + providerDeviceCodeInCallback: + '프로바이더가 콜백 모드에서 디바이스 코드 흐름을 반환했습니다', + providerAuthTimeout: '인증 시간이 초과되었습니다. 다시 시도하십시오.', + providerAccountRegistrationFailed: '인증된 계정을 등록할 수 없습니다', + providerLostStatusEndpoint: '인증 상태 엔드포인트와의 연결이 끊겼습니다', + providerUnknown: '알 수 없는 프로바이더: {{provider}}', + providerStartOAuthFailed: 'OAuth 시작에 실패했습니다', + providerCallbackFailed: '콜백 제출에 실패했습니다', + providerSubmitCallbackFailed: '콜백 제출에 실패했습니다', + loggingConfigSaved: '로깅 구성이 저장되었습니다.', + loggingConfigSaveFailed: '로깅 구성을 저장하지 못했습니다.', + unifiedConfigUpdated: '구성이 성공적으로 업데이트되었습니다', + migrationPreviewComplete: '마이그레이션 미리보기가 완료되었습니다', + migrationComplete: '마이그레이션이 성공적으로 완료되었습니다', + migrationFailed: '마이그레이션 실패', + rollbackComplete: '롤백이 성공적으로 완료되었습니다', + rollbackFailed: '롤백 실패', + defaultAccountSet: '기본 계정이 "{{name}}"(으)로 설정되었습니다', + defaultAccountReset: '기본 계정이 CCS로 재설정되었습니다', + accountDeleted: '"{{name}}" 계정이 삭제되었습니다', + contextUpdated: '"{{name}}" 컨텍스트가 {{summary}}(으)로 업데이트되었습니다', + legacyConfirmError: + '"{{name}}" 계정에 명시적 확인이 필요합니다. 이 계정에서 기록 동기화 편집을 사용하십시오.', + legacyConfirmFailed: '레거시 계정 "{{name}}" 확인 실패: {{error}}', + legacyConfirmSuccess_one: '레거시 계정 {{count}}개 확인됨', + legacyConfirmSuccess_other: '레거시 계정 {{count}}개 확인됨', + legacyConfirmPartial: + '레거시 계정 {{updated}}개를 확인했지만 {{failed}}개의 업데이트가 실패했습니다. 계정 상태를 새로 고쳤습니다.', + legacyConfirmAllFailed: + '레거시 계정 {{failed}}개를 확인하지 못했습니다. 계정 상태를 새로 고쳤습니다.', + noLegacyAccounts: '확인이 필요한 레거시 계정이 없습니다', + routingStrategySet: '라우팅 전략이 {{strategy}}(으)로 설정되었습니다', + variantCreated: '변형이 성공적으로 생성되었습니다', + variantUpdated: '변형이 성공적으로 업데이트되었습니다', + variantDeleted: '변형이 성공적으로 삭제되었습니다', + defaultAccountUpdated: '기본 계정이 업데이트되었습니다', + accountRemoved: '계정이 제거되었습니다', + accountPaused: '계정이 일시 중지되었습니다', + accountResumed: '계정이 재개되었습니다', + accountAdded: '{{provider}}에 대한 계정이 추가되었습니다', + kiroImported: 'Kiro 계정을 가져왔습니다: {{name}}', + kiroTokenImported: 'Kiro 토큰을 가져왔습니다', + modelUpdated: '모델이 업데이트되었습니다', + presetSaved: '프리셋 "{{name}}"이(가) 저장되었습니다', + presetDeleted: '프리셋이 삭제되었습니다', + cliproxyAlreadyRunning: 'CLIProxy가 이미 실행 중이었습니다', + cliproxyStarted: 'CLIProxy가 성공적으로 시작되었습니다', + cliproxyStartFailed: 'CLIProxy 시작에 실패했습니다', + cliproxyStopped: 'CLIProxy가 중지되었습니다', + cliproxyStopFailed: 'CLIProxy 중지에 실패했습니다', + presetApplied: '"{{name}}" 프리셋이 적용되었습니다', + presetAppliedCustom: '사용자 정의 프리셋이 적용되었습니다', + settingsSavedWithAdjustments: '모델 조정과 함께 설정이 저장되었습니다', + settingsSaved: '설정이 저장되었습니다', + failedSaveSettings: '설정을 저장하지 못했습니다', + codexRefreshFailed: 'Codex 스냅샷을 새로 고치지 못했습니다. 원시 편집은 유지되었습니다.', + codexRefreshError: 'Codex 스냅샷을 새로 고치지 못했습니다.', + codexFixToml: '저장하기 전에 TOML을 수정하십시오.', + codexSaved: 'Codex config.toml이 저장되었습니다.', + codexChangedExternally: + 'config.toml이 외부에서 변경되었습니다. 새로 고침 후 다시 시도하십시오.', + codexSaveFailed: 'Codex config.toml을 저장하지 못했습니다.', + codexUpdateFailed: 'Codex 구성을 업데이트하지 못했습니다.', + noOrphanProfiles: '고아 프로필 설정을 찾을 수 없습니다', + profilesRegistered: '프로필 {{count}}개 등록됨{{skipped}}', + destinationEmpty: '대상 프로필 이름은 비어 있을 수 없습니다', + profileExportDownloaded: '프로필 내보내기가 다운로드되었습니다', + profileImportFailed: '프로필 번들을 가져오지 못했습니다', + }, + providerConfig: { + defaultDeviceCodeInstruction: '브라우저에서 인증을 완료하십시오.', + trackLabel: '트랙', + sectionCoreLabel: '코어 / 원래 백엔드', + sectionCoreHint: '기본, 항상 사용 가능한 프로바이더 트랙', + sectionPlusLabel: 'Plus 추가 / 커뮤니티 유지 관리', + sectionPlusHint: '여전히 지원되지만 현재 기본 백엔드에서 분리됨', + plusTrackNote: '해당 트랙이 커뮤니티가 유지 관리하는 동안 선택적 Plus 백엔드가 필요합니다.', + }, + + // ======================================== + // Domain 7: Profiles / Settings / Pages + // ======================================== + profileEditorSections: { + imageAnalysis: '이미지 분석', + loadingImageSettings: '이미지 설정 로드 중...', + skipPermissionPrompts: '시작 시 권한 프롬프트 건너뛰기', + useNativeImageReading: '네이티브 이미지 읽기 사용', + skipTransformer: '트랜스포머 건너뛰기', + friendlyUi: '친숙한 UI', + info: '정보', + }, + imageAnalysisStatus: { + sectionTitle: '이미지', + openSettings: '설정 열기', + useNativeImageReading: '네이티브 이미지 읽기 사용', + refreshingPreview: '미리보기 새로 고침 중', + savedStatus: '저장된 상태', + livePreview: '실시간 미리보기', + disabledGlobally: '전역적으로 비활성화됨', + targetBypassesHook: '{{target}}이(가) 후크를 우회합니다', + nativeImageReading: '네이티브 이미지 읽기', + setupNeeded: '설정 필요', + needsAuth: '인증 필요', + needsProxy: '프록시 필요', + nativeFallback: '네이티브 폴백', + transformerReady: '트랜스포머 준비됨', + badgeDisabled: '비활성화됨', + badgeBypassed: '우회됨', + badgeNative: '네이티브', + badgeSetup: '설정', + badgeAuth: '인증', + badgeProxy: '프록시', + badgeReady: '준비됨', + capabilityVerified: '확인됨', + capabilityUnknown: '알 수 없음', + toggleSummaryNativeCapable: + '{{model}}이(가) 이미지를 지원하는 것으로 보입니다. CCS는 여기서 트랜스포머를 우회합니다.', + toggleSummaryNativeModel: 'CCS는 {{model}}에 대해 네이티브 읽기를 선호합니다.', + toggleSummaryNativeDefault: 'CCS는 이 프로필에 대해 네이티브 이미지 읽기를 선호합니다.', + toggleSummaryNativeFileAccess: '이 프로필은 현재 네이티브 파일 액세스를 유지합니다.', + toggleSummaryInactiveTarget: + '{{target}}이(가) 선택된 동안 저장된 Claude 측 이미지 라우팅이 비활성 상태입니다.', + toggleSummaryTransformerRoute: '트랜스포머 라우트: {{backend}}{{modelSuffix}}.', + noteDisabledGlobally: 'CCS 설정에서 이미지가 전역적으로 비활성화되어 있습니다.', + noteTargetBypassesHook: '현재 대상 {{target}}이(가) Claude Read 후크를 우회합니다.', + notePersistHook: '여기서 트랜스포머 라우팅이 실행되기 전에 프로필 후크를 유지하십시오.', + targetLabel: { + claude: 'Claude Code', + droid: 'Factory Droid', + codex: 'Codex CLI', + }, + }, + openrouterBadge: { + new: '신규', + integration: 'OpenRouter 통합', + }, + openrouterBanner: { + accessModels: 'OpenRouter를 통해 {{count}}+ 모델 액세스', + add: '추가', + }, + openrouterModelPicker: { + searchModels: '모델 검색', + newestModels: '최신 모델', + }, + openrouterPromoCard: { + title: 'OpenRouter', + description: '하나의 API 엔드포인트에서 수백 개의 모델에 액세스하십시오.', + }, + profileCard: { + profile: '프로필', + openRouter: 'OpenRouter 프로필', + claudeCode: 'Claude Code', + claudeCodeDefault: 'Claude Code (기본값)', + factoryDroid: 'Factory Droid', + codexCli: 'Codex CLI', + ccsProfile: 'CCS 프로필', + }, + profileDeck: { + profiles: '프로필', + failedToLoad: '프로필 로드 실패: {{message}}', + noProfiles: '구성된 프로필이 없습니다. 시작하려면 첫 번째 프로필을 생성하십시오.', + }, + profilesTable: { + name: '이름', + provider: '프로바이더', + model: '모델', + target: '대상', + lastModified: '마지막 수정', + actions: '작업', + edit: '편집', + }, + profileCreateDialog: { + createProfile: '프로필 생성', + appliedModelToTiers: '"{{model}}"을(를) 모든 모델 티어에 적용했습니다', + profileCreated: '프로필 "{{name}}"이(가) 생성되었습니다', + failedCreate: '프로필 생성에 실패했습니다', + chooseProviderHint: + '프로바이더 프리셋을 선택하거나 사용자 정의 API 엔드포인트를 구성하십시오.', + basicInformation: '기본 정보', + modelConfiguration: '모델 구성', + usedInCli: 'CLI에서 사용:', + apiBaseUrl: 'API Base URL', + baseUrlPlaceholder: 'https://api.example.com/v1', + prefilledFromPreset: + '{{name}}에서 미리 채워졌습니다. 필요에 따라 사용자 정의할 수 있습니다.', + optionalForPreset: + '{{name}}에 대해 선택 사항입니다. 네이티브 Anthropic 인증을 사용하려면 비워두십시오.', + endpointHint: 'OpenAI 호환 및 Anthropic 요청을 수락하는 엔드포인트', + optional: '(선택)', + apiKeyOptionalPlaceholder: '선택 사항 - 인증이 활성화된 경우에만', + apiKeyPlaceholder: 'sk-...', + apiKeyOptionalHint: '로컬 엔드포인트에 인증이 활성화된 경우에만 필요합니다', + defaultTargetCli: '기본 대상 CLI', + modelMapping: '모델 매핑', + modelMappingDesc: + 'Claude Code 티어 (Opus/Sonnet/Haiku)를 프로바이더가 지원하는 모델에 매핑합니다.', + searchModelsPlaceholder: '검색하려면 입력하십시오 (예: opus, sonnet, gpt-4o)...', + noModelsFound: '"{{query}}"에 대한 모델을 찾을 수 없습니다', + loadingModels: '모델 로드 중...', + defaultModel: '기본 모델', + sonnetMapping: 'Sonnet 매핑', + opusMapping: 'Opus 매핑', + haikuMapping: 'Haiku 매핑', + sonnetMappingPlaceholder: '예: gpt-4o, claude-sonnet-4', + opusMappingPlaceholder: '예: o1, claude-opus-4.5', + haikuMappingPlaceholder: '예: gpt-4o-mini, claude-3.5-haiku', + free: '무료', + }, + profileDialogLegacy: { + editProfile: '프로필 편집', + }, + supportEntryCard: { + actionRequired: '작업 필요', + }, + settingsPage: { + title: '설정', + loading: '로드 중...', + failedLoad: '설정을 로드하지 못했습니다.', + tabs: { + web: '웹', + env: '환경 변수', + think: '사고', + proxy: '프록시', + auth: '인증', + backup: '백업', + channels: '채널', + imageAnalysis: '이미지', + }, + websearchSection: { + title: '웹 검색', + description: 'CLI 기반 웹 검색 구성.', + }, + thinkingSection: { + title: '사고', + description: '지원되는 모델에 대해 확장 사고/추론을 구성합니다.', + directOverride: '직접 재정의', + youType: '입력:', + ccsAdds: 'CCS 추가:', + executionChain: '실행 체인', + primaryBackends: '주요 백엔드', + legacyCliFallbacks: '레거시 CLI 폴백', + managedPayload: '관리 페이로드', + sharedTargetMetadata: '공유 대상 메타데이터', + ideTargetMetadata: 'IDE 대상 메타데이터', + ideSettingsPath: 'IDE 설정 경로', + ideHost: 'IDE 호스트', + resolvedBinding: '해결된 바인딩', + bindingName: '바인딩 이름', + inSync: '동기화됨', + currentTargetPath: '현재 대상 경로', + warnings: '경고', + notes: '노트', + workspacePresets: '워크스페이스 프리셋', + draft: '초안', + advanced: '고급', + recommended: '권장 설정 흐름', + configureModelFirst: '먼저 모델을 구성하십시오', + }, + proxySection: { + title: '프록시', + loadingImageSettings: '이미지 설정 로드 중...', + }, + channelsSection: { + title: '공식 채널', + description: '공식 릴리스 채널을 보고 관리합니다.', + }, + imageAnalysisSection: { + title: '이미지 분석', + description: '이미지 분석 설정을 구성합니다.', + loading: '이미지 설정 로드 중...', + }, + browserSection: { + title: '브라우저', + description: 'CCS에서 관리되는 브라우저 자동화의 기본 설정 표면.', + primaryTitle: '설정 > 브라우저는 기본 브라우저 설정 표면입니다.', + primaryDescription: + '여기에서 Claude Browser Attach 및 Codex Browser Tools를 구성한 다음 아래 안내를 사용하여 각 레인을 시작하거나 확인하십시오.', + readiness: '준비 상태', + nextStep: '다음 단계', + technicalDetails: '기술 세부 정보', + diagnostics: '진단', + evalMode: { + label: 'browser_eval 액세스', + options: { + disabled: '비활성화됨', + readonly: '읽기 전용', + readwrite: '읽기/쓰기', + }, + }, + actions: { + saveClaude: 'Claude 설정 저장', + saveCodex: 'Codex 설정 저장', + testConnection: '연결 테스트', + copyLaunchCommand: '시작 명령 복사', + }, + messages: { + statusRefreshed: '브라우저 상태가 새로 고쳐졌습니다', + launchCommandCopied: '시작 명령이 복사되었습니다', + }, + claude: { + title: 'Claude Browser Attach', + description: '원격 디버깅이 활성화된 관리 Chrome 세션에 Claude 대상 시작을 연결합니다.', + enabledLabel: 'Claude Browser Attach 활성화', + enabledDescription: + '활성화되면, CCS는 Claude 대상 시작을 위해 관리되는 브라우저 MCP 런타임을 준비합니다.', + userDataDir: 'Chrome 사용자 데이터 디렉터리', + userDataDirHint: + '연결 모드 상태가 일상 브라우저와 격리되도록 전용 Chrome 프로필 디렉터리를 사용하십시오.', + devtoolsPort: 'DevTools 포트', + devtoolsPortHint: '연결 모드에서 Chrome을 시작할 때 동일한 포트를 사용하십시오.', + devtoolsPortInvalid: '1에서 65535 사이의 유효한 포트를 입력하십시오.', + effectivePath: '유효 연결 경로', + recommendedPath: '권장 경로', + managedRuntime: '관리 브라우저 런타임', + evalModeHint: + 'Claude Browser Attach에 대한 browser_eval 액세스를 제어합니다. 읽기 전용은 검사를 허용하고, 읽기/쓰기는 페이지 측 변형도 허용합니다.', + overrideMessage: + '{{source}}에서 현재 환경 재정의가 활성 상태입니다. 해당 재정의가 제거되면 이 대시보드가 진실의 출처로 유지됩니다.', + launchGuidance: '시작 안내', + launchGuidanceHint: + '원격 디버깅이 활성화된 Chrome을 시작한 다음, 필요한 경우 연결 테스트를 다시 실행하십시오.', + }, + codex: { + title: 'Codex Browser Tools', + description: 'Codex 대상 시작을 위한 관리 Playwright MCP 재정의 경로를 제어합니다.', + enabledLabel: 'Codex Browser Tools 활성화', + enabledDescription: + 'Codex 브라우저 도구의 일급 설정 표면으로 브라우저 페이지를 만들려면 이 기능을 켜두십시오.', + serverName: '관리 서버 이름', + overrideSupport: '구성 재정의 지원', + overrideSupported: '지원됨', + overrideUnsupported: '지원되지 않음', + binary: '감지된 Codex 바이너리', + notDetected: '감지되지 않음', + evalModeHint: + '브라우저 설정 패리티를 위해 저장되었습니다. Phase 1에서는 browser_eval 적용이 주로 Claude Browser Attach에 적용됩니다.', + }, + }, + }, + codexPage: { + title: 'Codex', + controlCenter: '제어 센터', + overview: '개요', + docs: '문서', + nativeRuntime: '네이티브 런타임', + ccsProvider: 'CCS 프로바이더', + setup: '설정', + }, + apiPage: { + title: 'API 프로필', + subtitle: 'API 프로필 및 엔드포인트를 관리합니다.', + }, + claudeExtensionPage: { + title: 'Claude 확장', + subtitle: 'Claude 확장 통합 설정.', + claudeAuth: 'Claude 인증', + status: '상태', + targetMetadata: 'IDE 대상 메타데이터', + }, + sharedPageV2: { + title: '공유', + subtitle: '공유 데이터 관리.', + }, + homePageV2: { + title: '홈', + logsMoved: '로그가 전용 워크스페이스로 이동되었습니다', + profiles: '프로필', + cliproxy: 'CLIProxy', + accounts: '계정', + health: '헬스', + }, + analyticsPageV2: { + title: '분석', + subtitle: '사용량 분석 및 인사이트.', + }, + logsPageV2: { + title: '로그', + subtitle: '시스템 로그를 보고 관리합니다.', + }, + healthPageV2: { + title: '헬스', + subtitle: '시스템 헬스 모니터링.', + }, + aiProvidersPage: { + title: 'AI 프로바이더', + subtitle: 'AI 프로바이더 구성을 관리합니다.', + unableToLoad: 'AI 프로바이더를 로드할 수 없습니다', + }, + }, + }, } as const; if (!i18n.isInitialized) { diff --git a/ui/src/lib/locales.ts b/ui/src/lib/locales.ts index c9f82d5e..087ad075 100644 --- a/ui/src/lib/locales.ts +++ b/ui/src/lib/locales.ts @@ -1,6 +1,6 @@ export const LOCALE_STORAGE_KEY = 'ccs-ui-locale'; -export const SUPPORTED_LOCALES = ['en', 'zh-CN', 'vi', 'ja'] as const; +export const SUPPORTED_LOCALES = ['en', 'zh-CN', 'vi', 'ja', 'ko'] as const; export type AppLocale = (typeof SUPPORTED_LOCALES)[number]; @@ -10,6 +10,7 @@ export function isSupportedLocale(locale: string): locale is AppLocale { export function normalizeLocale(locale: string | null | undefined): AppLocale { if (!locale) return 'en'; + if (locale.toLowerCase().startsWith('ko')) return 'ko'; if (locale.toLowerCase().startsWith('ja')) return 'ja'; if (locale.toLowerCase().startsWith('zh')) return 'zh-CN'; if (locale.toLowerCase().startsWith('vi')) return 'vi'; diff --git a/ui/tests/unit/ui/i18n/language-switcher.test.tsx b/ui/tests/unit/ui/i18n/language-switcher.test.tsx index d8618b21..9c8e6643 100644 --- a/ui/tests/unit/ui/i18n/language-switcher.test.tsx +++ b/ui/tests/unit/ui/i18n/language-switcher.test.tsx @@ -96,6 +96,7 @@ describe('Dashboard i18n', () => { it.each([ { locale: 'vi', label: 'Vietnamese', browserLocale: 'vi-VN' }, { locale: 'ja', label: 'Japanese', browserLocale: 'ja-JP' }, + { locale: 'ko', label: 'Korean', browserLocale: 'ko-KR' }, ])( 'supports $locale locale in switcher and persistence', async ({ locale, label, browserLocale }) => {