diff --git a/Sources/MacCleanKit/CleanupStrings.swift b/Sources/MacCleanKit/CleanupStrings.swift index a3e9ea6..141c456 100644 --- a/Sources/MacCleanKit/CleanupStrings.swift +++ b/Sources/MacCleanKit/CleanupStrings.swift @@ -21,6 +21,7 @@ public enum CleanupStrings { case .es: return "\(selectedText) de \(totalText) \(total == 1 ? "elemento seleccionado" : "elementos seleccionados")" case .ptBR: return "\(selectedText) de \(totalText) \(total == 1 ? "item" : "itens") \(selected == 1 ? "selecionado" : "selecionados")" case .ja: return "\(selectedText) / \(totalText) 項目を選択済み" + case .ko: return "\(totalText)개 항목 중 \(selectedText)개 선택됨" case .ru: return "Выбрано \(selectedText) из \(totalText) \(L10n.russianPlural(total, one: "объекта", few: "объектов", many: "объектов"))" case .zhHans: return "已选择 \(selectedText) / \(totalText) 项" @@ -38,6 +39,7 @@ public enum CleanupStrings { case .es: return "¿Limpiar \(number) \(count == 1 ? "elemento" : "elementos")?" case .ptBR: return "Limpar \(number) \(count == 1 ? "item" : "itens")?" case .ja: return "\(number) 項目をクリーンアップしますか?" + case .ko: return "\(number)개 항목을 정리할까요?" case .ru: return "Очистить \(number) \(L10n.russianPlural(count, one: "объект", few: "объекта", many: "объектов"))?" case .zhHans: return "清理 \(number) 项?" @@ -55,6 +57,7 @@ public enum CleanupStrings { case .es: return "\(number) \(count == 1 ? "elemento" : "elementos")" case .ptBR: return "\(number) \(count == 1 ? "item" : "itens")" case .ja: return "\(number) 項目" + case .ko: return "\(number)개 항목" case .ru: return "\(number) \(L10n.russianPlural(count, one: "объект", few: "объекта", many: "объектов"))" case .zhHans: return "\(number) 项" diff --git a/Sources/MacCleanKit/Constants.swift b/Sources/MacCleanKit/Constants.swift index 42e77b1..d201a1d 100644 --- a/Sources/MacCleanKit/Constants.swift +++ b/Sources/MacCleanKit/Constants.swift @@ -202,6 +202,7 @@ public enum MCConstants { "es.lproj", "es-ES.lproj", "es_ES.lproj", "es-MX.lproj", "es_MX.lproj", "es-419.lproj", "es_419.lproj", "es-US.lproj", "es_US.lproj", "Spanish.lproj", "pt.lproj", "pt-BR.lproj", "pt_BR.lproj", "Portuguese.lproj", "Portuguese (Brazil).lproj", "Brazilian Portuguese.lproj", + "ko.lproj", "ko-KR.lproj", "ko_KR.lproj", "Korean.lproj", "it.lproj", "it-IT.lproj", "it_IT.lproj", "it-CH.lproj", "it_CH.lproj", "Italian.lproj", "ja.lproj", "ja-JP.lproj", "ja_JP.lproj", "Japanese.lproj", ] @@ -238,5 +239,5 @@ public enum MCConstants { // plugin was tried (commit history) but doesn't work under multi-arch // `swift build --arch arm64 --arch x86_64` because xcbuild doesn't // execute plugins. - public static let appVersion = "1.28.4" + public static let appVersion = "1.28.5" } diff --git a/Sources/MacCleanKit/Localization.swift b/Sources/MacCleanKit/Localization.swift index 6265243..4735f81 100644 --- a/Sources/MacCleanKit/Localization.swift +++ b/Sources/MacCleanKit/Localization.swift @@ -9,6 +9,7 @@ public enum AppLanguage: String, CaseIterable, Identifiable, Sendable { case de = "de" case es = "es" case ptBR = "pt-BR" + case ko = "ko" case fr = "fr" case it = "it" case ja = "ja" @@ -34,6 +35,8 @@ public enum AppLanguage: String, CaseIterable, Identifiable, Sendable { "es" case .ptBR: "pt-BR" + case .ko: + "ko" case .fr: "fr" case .it: @@ -54,7 +57,7 @@ public enum AppLanguage: String, CaseIterable, Identifiable, Sendable { public var resolved: AppLanguage { switch self { case .system: Self.systemPreferred - case .de, .es, .ptBR, .fr, .it, .ja, .ru, .zhHans, .zhHant, .en: self + case .de, .es, .ptBR, .fr, .it, .ja, .ko, .ru, .zhHans, .zhHant, .en: self } } @@ -69,6 +72,7 @@ public enum AppLanguage: String, CaseIterable, Identifiable, Sendable { case "de": return .de case "es": return .es case "pt": return .ptBR + case "ko": return .ko case "fr": return .fr case "it": return .it case "ja": return .ja @@ -93,6 +97,7 @@ public enum AppLanguage: String, CaseIterable, Identifiable, Sendable { case .de: "Deutsch" case .es: "Español" case .ptBR: "Português (Brasil)" + case .ko: "한국어" case .fr: "Français" case .it: "Italiano" case .ja: "日本語" @@ -149,6 +154,7 @@ public enum L10n { case .de: germanFallbacks[zhHans] ?? english() case .es: spanishFallbacks[zhHans] ?? english() case .ptBR: brazilianPortugueseFallbacks[zhHans] ?? english() + case .ko: koreanFallbacks[zhHans] ?? english() case .fr: frenchFallbacks[zhHans] ?? english() case .it: italianFallbacks[zhHans] ?? english() case .ja: japaneseFallbacks[zhHans] ?? english() @@ -166,6 +172,7 @@ public enum L10n { case .de: germanFallbacks[zhHans] ?? english() case .es: spanishFallbacks[zhHans] ?? english() case .ptBR: brazilianPortugueseFallbacks[zhHans] ?? english() + case .ko: koreanFallbacks[zhHans] ?? english() case .fr: frenchFallbacks[zhHans] ?? english() case .it: italianFallbacks[zhHans] ?? english() case .ja: japaneseFallbacks[zhHans] ?? english() @@ -185,6 +192,8 @@ public enum L10n { spanishFallbacks[zhHans] ?? englishFallbacks[zhHans] ?? zhHans case .ptBR: brazilianPortugueseFallbacks[zhHans] ?? englishFallbacks[zhHans] ?? zhHans + case .ko: + koreanFallbacks[zhHans] ?? englishFallbacks[zhHans] ?? zhHans case .fr: frenchFallbacks[zhHans] ?? englishFallbacks[zhHans] ?? zhHans case .it: @@ -916,6 +925,705 @@ public enum L10n { "响应格式不正确": "resposta malformada", ] + private static let koreanFallbacks: [String: String] = [ + "%ld 项": "%ld개 항목", + "1 - 3 个月": "1~3개월", + "12 个月": "12개월", + "3 - 6 个月": "3~6개월", + "3 个月": "3개월", + "30 天内不再显示": "30일 동안 숨기기", + "6 个月": "6개월", + "6 个月 - 1 年": "6개월 - 1년", + "AI 工具缓存": "AI 도구 캐시", + "AI 编码工具的缓存(Claude、Codex);不含历史与会话。": "AI 코딩 도구(Claude, Codex)의 캐시입니다. 기록 및 세션은 제외됩니다.", + "CPU": "CPU", + "Chrome 正在运行,因此未删除任何内容。请在 Chrome 中通过“窗口 > 扩展程序”移除此扩展。": "Chrome이 열려 있어 아무것도 삭제하지 않았습니다. Chrome에서 창 > 확장 프로그램으로 이동해 확장 프로그램을 제거하세요.", + "Chrome、Brave、Edge、Arc、Firefox 和 Safari 的扩展。名称与已知广告软件家族相符的会标为可疑。": "Chrome, Brave, Edge, Arc, Firefox 및 Safari의 확장 프로그램입니다. 알려진 애드웨어 계열과 일치하는 이름은 의심됨으로 표시됩니다.", + "DerivedData 和 Previews 会在下次构建时重建,Device Support 会在连接设备时重新复制。Archives 和模拟器数据无法重新生成;如需旧构建或崩溃符号请保留。": "DerivedData와 Previews는 다음 빌드 때 다시 생성되고 Device Support는 기기를 연결하면 다시 복사됩니다. 아카이브와 시뮬레이터 데이터는 다시 생성할 수 없으므로 이전 빌드나 충돌 분석용 심볼이 필요하면 보관하세요.", + "Docker 和 Xcode 模拟器占用的空间。只显示在这台 Mac 上找到的工具,且不会自动勾选任何项目。": "Docker 및 Xcode 시뮬레이터가 사용하는 공간입니다. 이 Mac에 있는 도구만 표시되며 아무것도 미리 선택되지 않습니다.", + "Firefox 正在运行,因此未删除任何内容。请在 Firefox 中通过“工具 > 附加组件和主题”移除此扩展。": "Firefox가 열려 있어 아무것도 삭제하지 않았습니다. Firefox에서 도구 > 부가 기능 및 테마로 이동해 확장 프로그램을 제거하세요.", + "GPU 使用率": "GPU 사용량", + "GitHub 返回了无法识别的响应。": "GitHub에서 예상치 못한 응답을 받았습니다.", + "Homebrew 返回了无法识别的响应。": "Homebrew에서 예상치 못한 응답을 받았습니다.", + "IDE 与编辑器缓存": "IDE 및 편집기 캐시", + "Internet 插件": "인터넷 플러그인", + "Mac Sai 无法确认此扩展的文件夹可以安全移除,因此未删除任何内容。": "Mac Sai가 이 확장 프로그램의 폴더를 안전하게 제거할 수 있는지 확인할 수 없어 아무것도 삭제하지 않았습니다.", + "PDF": "PDF", + "Safari 扩展": "Safari 확장 프로그램", + "Safari 扩展不能在本应用内开启、关闭或删除,以免破坏宿主应用的签名。请在 Safari 设置中管理它们。": "여기에서는 Safari 확장 프로그램을 켜거나 끄거나 삭제할 수 없습니다. 그러면 호스트 앱의 서명이 손상될 수 있습니다. Safari 설정에서 관리하세요.", + "Safari 扩展随 App 一起安装,由 macOS 管理,因此此列表只读。将改为打开“设置”。": "Safari 확장 프로그램은 앱과 함께 제공되고 macOS에서 관리되므로 이 목록은 읽기 전용입니다. 대신 설정이 열립니다.", + "Spotlight 没有应用的使用记录": "Spotlight에 앱 사용 기록이 없습니다", + "Spotlight 的整个搜索索引会被清除并重建。数小时内 Spotlight 搜索可能返回空结果(主目录越大耗时越久),系统搜索和智能文件夹也会受影响。": "Spotlight의 전체 검색 색인이 지워지고 다시 생성됩니다. 몇 시간 동안 Spotlight 검색 결과가 비어 있을 수 있으며(홈 폴더가 클수록 더 오래 걸림), 시스템 검색과 스마트 폴더도 영향을 받습니다.", + "URL Scheme": "URL 스킴", + "Xcode 垃圾": "Xcode 불필요한 파일", + "Xcode 模拟器": "Xcode 시뮬레이터", + "iOS 设备备份": "iOS 기기 백업", + "iPhone 和 iPad 的本地备份。": "iPhone 및 iPad의 로컬 백업입니다.", + "macOS 的“哪类文件由哪个应用打开”数据库会被清除并重建。完成前(通常数小时),双击文件可能失败或打开错误应用,默认应用设置可能重置,Spotlight 启动应用也可能不可用。重启可加快恢复。": "\"어떤 앱이 어떤 파일 형식을 여는지\"에 대한 macOS의 데이터베이스가 지워지고 다시 생성됩니다. 완료될 때까지(보통 몇 시간) 파일을 두 번 클릭하면 실패하거나 잘못된 앱이 열릴 수 있고, 기본 앱 설정이 재설정될 수 있으며, Spotlight를 통한 앱 실행이 작동하지 않을 수 있습니다. 재시동하면 더 빨리 복구됩니다.", + "macOS 诊断日志。": "macOS 진단 로그입니다.", + "macOS 诊断日志。仅在排查过去的问题时有用;macOS 会继续写入新日志。": "macOS 진단 로그입니다. 과거 문제를 조사할 때만 유용하며 macOS는 계속 새 로그를 작성합니다.", + "npm、Cargo、pip、Homebrew、Gradle 的可重建缓存。": "npm, Cargo, pip, Homebrew 및 Gradle에서 재생성 가능한 캐시입니다.", + "{browser} 正在运行,因此未删除任何内容。请在 {browser} 的地址栏中打开 {url} 来移除此扩展。": "{browser} 앱이 열려 있어 아무것도 삭제하지 않았습니다. 주소 표시줄에서 {url}을(를) 열어 {browser}에서 확장 프로그램을 제거하세요.", + "~/Library/Logs/MacClean/operations.log — 30 天后自动清理": "~/Library/Logs/MacClean/operations.log: 30일 후 자동으로 정리됨", + "“邮件”应用的搜索索引会从头重建。重建完成前,邮件搜索和未读数可能不准确(大型邮箱通常需 10–30 分钟)。": "Mail 앱의 검색 색인이 처음부터 다시 작성됩니다. 재구축이 완료될 때까지 메일 검색 및 읽지 않은 메일 수가 정확하지 않을 수 있습니다(대용량 사서함은 보통 10~30분).", + "一切就绪!": "모든 준비가 완료되었습니다!", + "一键清理": "원클릭 정리", + "上一级": "상위 폴더", + "上次打开": "마지막으로 연 날짜", + "下一步": "다음", + "下载": "다운로드", + "下载和构建缓存。npm、Cargo、pip、Homebrew 和 Gradle 会在下次安装或构建时重新下载所需内容。": "다운로드 및 빌드 캐시입니다. npm, Cargo, pip, Homebrew 및 Gradle은 다음 설치나 빌드 때 필요한 파일을 다시 다운로드합니다.", + "下载文件夹中超过一周的磁盘映像,通常是已运行过的安装程序。如需要可重新下载。": "다운로드 폴더에 있는 일주일 이상 된 디스크 이미지로, 보통 이미 실행한 설치 프로그램입니다. 필요하면 다시 다운로드할 수 있습니다.", + "不会自动勾选。": "아무것도 자동으로 선택되지 않습니다.", + "不再提示": "다시 묻지 않기", + "不可写": "쓸 수 없음", + "不可用的模拟器": "사용할 수 없는 시뮬레이터", + "不能排除整个 /Volumes。": "/Volumes 전체를 제외할 수 없습니다.", + "不能排除整个主目录。": "전체 홈 폴더를 제외할 수는 없습니다.", + "主题": "테마", + "仅临时和缓存文件夹。Claude 和 Codex 会按需重新生成;绝不包含历史、记忆和会话。": "임시 및 캐시 폴더만 해당됩니다. Claude와 Codex가 필요할 때 다시 생성하며, 기록, 메모리 및 세션은 절대 포함되지 않습니다.", + "仅显示图标": "아이콘만", + "仅显示错误": "오류만", + "仅移除 macOS 已标记可清理的 Time Machine 本地快照;不会删除你主动需要的内容。": "macOS가 이미 정리 대상으로 표시한 Time Machine 로컬 스냅샷만 제거합니다. 사용자에게 필요한 항목은 삭제되지 않습니다.", + "仅编辑器缓存。Cursor 和 Antigravity 下次启动时会重新生成;你的设置和扩展不受影响。": "편집기 캐시만 해당됩니다. Cursor와 Antigravity가 다음 실행 시 다시 생성하며, 설정과 확장 프로그램은 영향을 받지 않습니다.", + "仍要运行": "계속 실행", + "从大到小": "큰 파일 먼저", + "从小到大": "작은 파일 먼저", + "从应用中移除这台 Mac 无法运行的 CPU 代码。会直接修改应用;只有重新安装才能撤销。": "앱에서 이 Mac이 실행할 수 없는 CPU 코드를 삭제합니다. 설치된 앱을 직접 변경하므로 다시 설치해야만 되돌릴 수 있습니다.", + "代码": "코드", + "代码编辑器的缓存(Cursor、Antigravity 等)。": "Cursor 및 Antigravity와 같은 코드 편집기의 캐시입니다.", + "代码项目中的依赖和构建文件夹。": "코드 프로젝트의 종속성 및 빌드 폴더입니다.", + "以后再说": "나중에", + "以已不再安装的应用命名的支持文件夹(每行的名称就是该应用的 ID)。以后重新安装该应用会从头开始。": "더 이상 설치되어 있지 않은 앱의 지원 폴더입니다. 각 행의 이름은 해당 앱의 ID입니다. 나중에 앱을 다시 설치하면 초기 상태로 시작합니다.", + "以开源方式让你的 Mac 保持干净、快速和安全。": "Mac을 깨끗하고 빠르며 안전하게 유지하는 오픈 소스 방법입니다.", + "优化": "최적화", + "优化你的 Mac": "Mac 최적화", + "会产生几分钟磁盘活动。该操作为只读,无论结果如何都不会更改磁盘内容。": "몇 분 동안 디스크 작업이 발생합니다. 읽기 전용 작업이므로 결과와 관계없이 디스크 내용은 변경되지 않습니다.", + "会删除本地 Time Machine 快照以释放空间。远程或备份盘上的快照不受影响,你仍可从 Time Machine 备份恢复。": "디스크 공간을 확보하기 위해 로컬 Time Machine 스냅샷을 삭제합니다. 원격 또는 백업 드라이브의 스냅샷은 영향을 받지 않으며, Time Machine 백업에서 계속 복원할 수 있습니다.", + "会自动重建": "자동으로 다시 생성됨", + "你不使用的语言翻译。移除会修改应用包;如需恢复请重新安装应用。": "사용하지 않는 언어의 번역입니다. 제거하면 앱 번들이 변경되며, 복원하려면 앱을 다시 설치하세요.", + "你的 Mac 很干净!": "Mac이 깨끗해졌습니다!", + "你的浏览历史和跟踪数据。清理后无法恢复;Cookie 和登录会话会保留。": "방문 기록 및 추적 데이터입니다. 정리 후에는 복원할 수 없으며, 쿠키와 로그인 세션은 유지됩니다.", + "你自己的文件,仅按大小挑选。这里没有任何东西天生就是垃圾;请逐个检查。": "크기만으로 선별한 사용자의 파일입니다. 여기 있는 항목은 원래 불필요한 파일이 아니므로 하나씩 확인하세요.", + "你选择的项目已在废纸篓中——需要时可以恢复。若要彻底删除,请打开“废纸篓”模块并清空。": "선택한 항목은 휴지통에 있으므로 필요하면 복구할 수 있습니다. 완전히 삭제하려면 휴지통 모듈을 열고 비우세요.", + "使用渐进式 SHA-256 哈希检测\n查找重复文件": "단계적 SHA-256 해시 검사로\n중복 파일을 찾습니다", + "保留": "유지", + "修复 Finder 的文件类型与应用打开方式数据库": "Finder의 파일 유형과 앱 연결 데이터베이스 복구", + "偏好设置面板": "환경설정 패널", + "充电中": "충전 중", + "全部": "모두", + "全部展开": "모두 펼치기", + "全部折叠": "모두 접기", + "关于": "정보", + "关于此扩展": "이 확장 프로그램 정보", + "其他": "기타", + "内存": "메모리", + "内存使用率": "메모리 사용량", + "内存压力过高": "메모리 압력이 높음", + "内容已更改": "내용이 변경됨", + "内置": "내장", + "出于安全考虑,已拒绝移除此项目。": "안전상의 이유로 이 항목을 제거하지 않았습니다.", + "分区": "섹션", + "切换后会立即应用到主界面和菜单栏小组件。": "변경 사항은 기본 창과 메뉴 막대 위젯에 즉시 적용됩니다.", + "刚刚": "지금 막", + "删除完成": "삭제됨", + "删除所选模拟器项目…": "선택한 시뮬레이터 항목 삭제…", + "删除此关联(自动备份当前版本)": "연결 제거(자동 백업 생성됨)", + "删除运行时会先关闭正在使用它的模拟器,这些模拟器之后将不可用。": "런타임을 삭제하면 먼저 이를 사용하는 모든 시뮬레이터가 종료되고 해당 시뮬레이터를 사용할 수 없게 됩니다.", + "删除重复项": "중복 제거", + "刷新": "새로고침", + "刷新 DNS 缓存": "DNS 캐시 비우기", + "前往“隐私与安全性 → 完全磁盘访问权限”": "개인정보 보호 및 보안 → 전체 디스크 접근 권한으로 이동", + "加速": "속도", + "加速邮件": "Mail 속도 향상", + "包管理器缓存": "패키지 관리자 캐시", + "匹配已知恶意软件特征。如果它属于你有意安装的软件,请先检查路径。": "알려진 악성코드 서명과 일치합니다. 의도적으로 설치한 소프트웨어라면 먼저 경로를 확인하세요.", + "占用空间最多的文件。": "가장 많은 공간을 차지하는 파일입니다.", + "占用资源": "리소스 사용 현황", + "卷": "볼륨", + "卷可能保存着数据库等数据,Mac Sai 不会清理它们。如需删除,请使用 Docker Desktop 或 Docker 命令行。": "볼륨에는 데이터베이스 등 영구 데이터가 있을 수 있으므로 Mac Sai는 볼륨을 정리하지 않습니다. 제거하려면 Docker Desktop 또는 docker 명령을 사용하세요.", + "卸载": "제거", + "卸载…": "제거…", + "卸载器": "제거 프로그램", + "压缩包": "압축 파일", + "原位置已有文件,已跳过:%ld": "원래 위치에 파일이 있어 건너뜀: %ld", + "发现新版本": "업데이트 가능", + "发现的垃圾": "불필요한 파일 발견됨", + "发生未知错误": "알 수 없는 오류가 발생했습니다", + "发行说明": "릴리스 노트", + "取消": "취소", + "受保护的系统应用——无法移除": "보호된 시스템 앱: 제거할 수 없음", + "受保护路径": "보호된 경로", + "受保护,无法退出": "보호됨: 강제 종료할 수 없음", + "受限": "제한적", + "只能排除主目录或 /Volumes 下的文件夹。": "홈 폴더 또는 /Volumes 아래의 폴더만 제외할 수 있습니다.", + "可回收": "확보 가능", + "可安全移除": "안전하게 제거 가능", + "可用磁盘空间": "여유 디스크 공간", + "可疑": "의심됨", + "可能带来持续数小时的影响——将打开确认窗口": "몇 시간 동안 영향이 있을 수 있음: 확인 창이 열립니다", + "可视化磁盘使用情况": "디스크 사용량 시각화", + "可视化磁盘空间使用情况": "디스크 공간 사용량 시각화", + "合并": "통합", + "合并所选副本?": "선택한 사본을 통합하시겠습니까?", + "同一文件的相同副本。": "동일한 파일의 동일한 복사본입니다.", + "名称与已知广告软件家族相符。这只是提示,并非确认。": "이름이 알려진 애드웨어 계열과 일치합니다. 확인된 탐지가 아니라 참고용 표시일 뿐입니다.", + "后台": "백그라운드", + "启动代理": "Launch Agent", + "启动守护进程": "Launch Daemon", + "回收 Docker 空间": "Docker 공간 확보", + "图片": "이미지", + "在 Chrome、Brave、Edge、Arc、Firefox 或 Safari 中未找到扩展": "Chrome, Brave, Edge, Arc, Firefox 또는 Safari에서 확장 프로그램을 찾을 수 없습니다", + "在 Finder 中显示": "Finder에서 보기", + "在 Finder 中查看配置文件": "Finder에서 구성 보기", + "在 GitHub 上浏览代码库": "GitHub에서 코드베이스 찾아보기", + "在屏幕顶部实时显示 CPU、内存、磁盘、电池和网络状态。点击可展开浮窗。": "메뉴 막대에 CPU, 메모리, 디스크, 배터리 및 네트워크 상태를 실시간으로 표시합니다. 클릭하면 팝오버가 열립니다.", + "在监控位置检测到新的可执行文件": "모니터링 중인 위치에서 새 실행 파일이 감지되었습니다", + "在磁盘上发现的已知恶意文件。": "디스크에서 발견된 알려진 악성 파일입니다.", + "在系统设置中打开": "시스템 설정에서 열기", + "在系统设置中打开类别": "시스템 설정에서 카테고리 열기", + "在设置中打开": "설정에서 열기", + "复制": "복사", + "复制全部": "모두 복사", + "复制升级命令": "업그레이드 명령 복사", + "复制路径": "경로 복사", + "外观": "모양", + "大型个人目录可能需要几分钟扫描": "홈 폴더가 크면 검사에 몇 분이 걸릴 수 있습니다", + "大小": "크기", + "大文件": "대용량 파일", + "大文件与旧文件": "크고 오래된 파일", + "失效的登录项": "유효하지 않은 로그인 항목", + "失败或孤立下载留下的文件。": "실패했거나 중단된 다운로드가 남긴 파일입니다.", + "失败或被放弃的下载留下的文件。如仍需要,请重新下载。": "실패했거나 중단된 다운로드가 남긴 파일입니다. 아직 필요하면 파일을 다시 다운로드하세요.", + "好": "확인", + "如果 {browser} 已关闭,扩展文件夹会移到废纸篓。如果它正在运行,则不会删除任何内容,并会告诉你在哪里移除。如果你开启了 {browser} 同步,它可能会重新安装此扩展。": "{browser} 앱이 닫혀 있으면 확장 프로그램 폴더를 휴지통으로 이동합니다. 열려 있으면 아무것도 삭제하지 않고 제거 방법을 안내합니다. {browser} 동기화를 사용 중이면 확장 프로그램이 다시 설치될 수 있습니다.", + "存储空间严重不足": "저장 공간이 매우 부족함", + "安全擦除": "보안 삭제", + "安全擦除文件,使其无法恢复": "파일을 복구할 수 없도록 안전하게 삭제", + "安装包": "설치 프로그램", + "完全磁盘访问权限": "전체 디스크 접근 권한", + "完成": "완료", + "完整日志:~/Library/Logs/MacClean/operations.log": "전체 로그: ~/Library/Logs/MacClean/operations.log", + "实时系统状态": "실시간 시스템 상태", + "容器": "컨테이너", + "将当前内容复制到剪贴板,可粘贴到 GitHub issue 中": "현재 내용을 클립보드에 복사해 GitHub 이슈에 붙여넣을 수 있습니다", + "将文件拖放到此处进行粉碎": "파쇄할 파일을 여기에 드롭하세요", + "将模块渐变背景替换为中性的深色背景,以提升可读性。": "모듈의 그라데이션 배경을 중립적인 어두운 색으로 바꿔 가독성을 높입니다.", + "尚未排除任何文件夹。": "아직 제외된 폴더가 없습니다.", + "屏幕录制": "화면 녹화", + "展开": "펼치기", + "已不在这台 Mac 上的账户的整个个人文件夹。请逐个核对名称:暂时离线的网络账户看起来完全一样。": "이 Mac에서 삭제된 계정의 홈 폴더 전체입니다. 일시적으로 오프라인인 네트워크 계정도 동일하게 표시되므로 각 이름을 확인하세요.", + "已不存在": "이미 없음", + "已从废纸篓清空:%ld": "휴지통에서 이미 삭제됨: %ld", + "已保存的 Wi-Fi": "저장된 Wi-Fi", + "已停止": "중지됨", + "已停用": "꺼짐", + "已删除应用留下的支持文件。": "삭제한 앱의 지원 파일입니다.", + "已删除应用的残留文件": "삭제된 앱의 남은 부분", + "已删除用户数据": "삭제된 사용자", + "已发现文件": "파일 발견", + "已取消——未授予管理员权限。": "취소됨: 관리자 권한이 부여되지 않았습니다.", + "已启用": "켜짐", + "已在废纸篓中。清倒是永久性的,无法撤销。": "이미 휴지통에 있습니다. 비우기는 영구적이며 취소할 수 없습니다.", + "已复制": "복사됨", + "已将扩展移到废纸篓。": "확장 프로그램이 휴지통으로 이동되었습니다.", + "已恢复:%ld": "복원됨: %ld", + "已找到 Docker,但它没有响应。请先启动 Docker Desktop,然后点“刷新”。": "Docker가 설치되어 있지만 응답하지 않습니다. Docker Desktop을 시작한 다음 새로고침을 클릭하세요.", + "已是最新": "최신 상태", + "已清理": "정리됨", + "已移到废纸篓": "휴지통으로 이동됨", + "已移除用户账户留下的数据。": "제거된 사용자 계정이 남긴 데이터입니다.", + "已连接": "연결됨", + "已选择": "선택됨", + "已选择待清理": "정리 대상으로 선택됨", + "已防护": "보호됨", + "干净": "깨끗함", + "平衡": "균형", + "应用": "앱", + "应用临时文件。每个应用下次启动时会自动重新生成。": "앱 임시 파일입니다. 각 앱의 다음 실행 시 자동으로 다시 생성됩니다.", + "应用临时文件,下次启动会重新生成。": "앱 임시 파일입니다. 다음 실행 시 다시 생성됩니다.", + "应用为排查问题写下的诊断记录。应用不会回读旧日志,运行时会写新的日志。": "문제 해결을 위해 앱이 작성한 진단 텍스트입니다. 앱은 이전 로그를 다시 읽지 않으며 실행 시 새 로그를 시작합니다.", + "应用二进制中未使用的 CPU 架构切片。": "앱 바이너리에 포함된 사용하지 않는 CPU 아키텍처입니다.", + "应用内未使用的本地化语言资源。": "앱에 포함된 사용하지 않는 현지화 파일입니다.", + "应用写入的诊断日志。": "앱에서 작성한 진단 로그입니다.", + "应用包中未找到通用 Mach-O 二进制文件": "번들에서 유니버설 Mach-O 바이너리를 찾을 수 없음", + "应用在一周多以前下载的安装包。安装程序运行后就不再需要,需要时可重新下载。": "앱이 일주일 이상 전에 다운로드한 설치 패키지입니다. 실행이 끝난 설치 프로그램은 더 이상 필요하지 않으며 다시 다운로드할 수 있습니다.", + "应用已打开": "앱이 열려 있음", + "应用更新": "앱 업데이트", + "应用权限": "앱 권한", + "应用程序": "앱", + "废纸篓": "휴지통", + "废纸篓为空": "휴지통이 비어 있습니다", + "建议": "권장 사항", + "开发者磁盘占用": "개발용 저장 공간", + "开始使用": "시작하기", + "强制退出": "강제 종료", + "强制退出前会要求确认": "강제 종료 전에 확인을 요청합니다", + "当前位于废纸篓中的项目。": "현재 휴지통에 있는 항목입니다.", + "彻底移除应用": "앱을 완전히 제거", + "彻底移除应用及其残留文件": "앱과 남은 파일을 완전히 제거", + "待清理": "정리 가능", + "很久没打开过的你自己的文件。旧并不代表不需要;请逐个检查。": "오랫동안 열지 않은 사용자의 파일입니다. 오래되었다고 불필요한 것은 아니므로 하나씩 확인하세요.", + "忘记": "삭제", + "忘记所选": "선택한 네트워크 삭제", + "忘记所选网络?": "선택한 네트워크를 삭제하시겠습니까?", + "快速": "빠름", + "性能": "성능", + "恢复": "복원", + "恢复完成": "복원 완료", + "恢复这次清理?": "이 정리를 되돌리시겠습니까?", + "恢复默认": "기본값으로 재설정", + "恶意软件": "악성코드", + "恶意软件扫描": "악성코드 검사", + "恶意软件清理": "악성코드 제거", + "所有应用均为最新": "모든 앱이 최신 상태입니다", + "所选副本会保留在原位并转为克隆,仅释放重复占用的空间,不删除任何文件。": "선택한 복사본은 클론으로 그 자리에 유지됩니다. 중복된 공간만 확보되며 아무것도 삭제되지 않습니다.", + "所选副本会被移到废纸篓,每组保留一个原件。": "선택한 복사본은 휴지통으로 이동되고, 원본은 그룹별로 하나씩 보관됩니다.", + "打开 Safari 设置": "Safari 설정 열기", + "打开活动日志,查看每个错误并复制详情用于反馈问题": "활동 로그를 열어 모든 오류를 확인하고 문제 신고용 세부정보를 복사하세요", + "打开系统设置": "시스템 설정 열기", + "打开设置": "설정 열기", + "执行 macOS 内置的每日、每周和每月维护任务": "macOS에 내장된 일일, 주간, 월간 유지 관리 루틴을 실행합니다.", + "扩展": "확장 프로그램", + "扫描": "검사", + "扫描 Mac 中的垃圾文件、恶意威胁\n和性能问题": "Mac의 불필요한 파일, 악성코드 위협,\n성능 문제를 검사합니다", + "扫描完成——没有需要清理的内容": "검사 완료: 정리할 항목이 없습니다", + "扫描病毒、广告软件和其他威胁": "바이러스, 애드웨어 및 기타 위협 검사", + "把最近一次清理整批恢复到原位置。已清空废纸篓或原路径已有文件的项会被跳过。": "정리 작업 전체를 한 번의 클릭으로 되돌립니다. 이미 휴지통에서 비워졌거나 원래 위치에 새 파일이 있는 항목은 건너뜁니다.", + "折叠": "접기", + "报告问题": "문제 신고", + "指向已不存在应用的登录项。": "더 이상 존재하지 않는 앱을 가리키는 로그인 항목입니다.", + "指向已不存在应用的登录项,因此无法启动任何东西。": "더 이상 존재하지 않는 앱을 가리키므로 아무것도 실행할 수 없는 로그인 항목입니다.", + "按上次打开时间列出应用,并按占用空间排序。一键转到卸载器。": "최근에 열지 않은 앱을 차지하는 공간 순으로 나열합니다. 한 번의 클릭으로 제거 프로그램에 보낼 수 있습니다.", + "按名称": "이름", + "按应用查看持有哪些隐私权限。这是只读列表——按钮会打开系统设置。本应用无法关闭权限。": "각 앱에 어떤 개인정보 보호 권한이 있는지 확인합니다. 이 목록은 읽기 전용이며 버튼을 누르면 시스템 설정이 열립니다. Mac Sai는 권한을 직접 해제할 수 없습니다.", + "损坏或孤立的偏好设置文件。": "손상되었거나 연결이 끊긴 환경설정 파일입니다.", + "损坏的偏好设置": "손상된 환경설정", + "排序": "정렬", + "排序方式": "정렬 기준", + "排除": "제외", + "排除文件夹": "제외된 폴더", + "提交错误报告和功能请求": "버그 보고서 및 기능 요청", + "搜索应用...": "앱 검색...", + "搜索文件类型或应用...": "파일 형식 또는 앱 검색...", + "搜索语言": "언어 검색", + "支持 Mac Sai": "Mac Sai 후원", + "支持文件": "지원 파일", + "文件": "파일", + "文件夹": "폴더", + "文件打开方式": "파일 연결", + "文件粉碎": "파일 파쇄", + "文档": "문서", + "文档版本": "문서 버전", + "文档的旧自动保存版本。当前版本会保留,但清理后无法再浏览旧版本。": "문서의 이전 자동 저장된 개정판입니다. 현재 버전은 그대로 유지되지만 이전 버전은 정리 후에 탐색할 수 없습니다.", + "无法写入 plist": "plist를 쓸 수 없습니다", + "无法列出哪些应用持有哪些权限。仍可通过下方按钮打开系统设置。": "앱별 권한을 표시할 수 없습니다. 아래 버튼으로 시스템 설정을 열 수는 있습니다.", + "无法判断哪些应用未被使用。请检查 Spotlight 索引是否已开启。": "Mac Sai가 사용하지 않는 앱을 확인할 수 없습니다. Spotlight 색인이 켜져 있는지 확인하세요.", + "无法恢复:%ld": "복원할 수 없습니다: %ld", + "无法更新已保存的 Wi-Fi 网络。": "저장된 Wi-Fi 네트워크를 업데이트할 수 없습니다.", + "无法添加该文件夹。": "해당 폴더를 추가할 수 없습니다.", + "无法移到废纸篓:": "휴지통으로 이동할 수 없음: ", + "无法读取 Safari 扩展列表。请在 Safari 设置 > 扩展中查看。": "Safari 확장 프로그램 목록을 읽을 수 없습니다. Safari 설정 > 확장 프로그램에서 확인하세요.", + "无法读取 plist": "plist를 읽을 수 없습니다", + "无法读取权限数据库": "권한 데이터베이스를 읽을 수 없습니다", + "无法读取的设置文件,或其应用已不再安装。这台 Mac 上没有任何东西在使用它们。": "읽을 수 없거나 앱이 더 이상 설치되어 있지 않은 설정 파일입니다. 이 Mac에서 이 파일을 사용하는 항목은 없습니다.", + "无法退出受保护的进程。": "이 프로세스는 보호되어 종료할 수 없습니다.", + "无线接口名称无效,已中止操作。": "Wi-Fi 인터페이스 이름이 잘못되어 작업이 취소되었습니다.", + "日志为空。尚未执行过清理。": "로그가 비어 있습니다. 아직 정리를 실행하지 않았습니다.", + "旧文件": "오래된 파일", + "旧更新文件": "오래된 업데이트", + "旧版运行时": "이전 런타임", + "旧的自动保存文档版本。": "이전에 자동 저장된 문서 개정판입니다.", + "时间": "기간", + "显示宿主应用": "호스트 앱 보기", + "智能扫描": "스마트 검사", + "更改权限只能在系统设置中完成。": "권한은 시스템 설정에서만 변경할 수 있습니다.", + "更新": "업데이트", + "更新后遗留的安装包。": "업데이트 후 남은 설치 패키지입니다.", + "更新日志和历史版本": "변경 로그 및 이전 버전", + "曾经挂载但已不再需要的磁盘映像。": "한때 마운트했지만 더 이상 필요 없는 디스크 이미지입니다.", + "曾被换出的应用回到前台时可能需要片刻恢复。": "메모리가 디스크로 옮겨진 앱은 다시 활성화되는 데 잠시 걸릴 수 있습니다.", + "最近 1 个月": "지난 1개월", + "最近清理": "최근 정리", + "最近项目列表和其他隐私痕迹。": "최근 항목 목록 및 기타 개인정보 흔적입니다.", + "最近项目列表和类似痕迹。应用的“最近打开”菜单将会清空。": "최근 항목 목록 및 유사한 사용 기록입니다. 앱의 최근 항목 열기 메뉴가 비워집니다.", + "未下载完成的文件。": "일부만 다운로드된 파일입니다.", + "未使用": "미사용", + "未使用的应用": "사용하지 않는 앱", + "未使用的磁盘映像": "사용하지 않는 디스크 이미지", + "未保存的工作可能会丢失。": "저장하지 않은 작업은 손실될 수 있습니다.", + "未列出任何 Safari 扩展": "Safari 확장 프로그램이 없습니다", + "未列出任何应用。": "나열된 앱이 없습니다.", + "未发现垃圾": "불필요한 파일이 없습니다", + "未发现垃圾、威胁或性能问题": "불필요한 파일, 위협 또는 성능 문제가 발견되지 않았습니다", + "未发现隐私痕迹": "개인정보 흔적이 없습니다", + "未在应用包中找到辅助组件": "앱 번들에서 도우미를 찾을 수 없음", + "未完成下载": "완료되지 않은 다운로드", + "未完成下载的部分文件和超过一天的临时文件。下载仍在进行时请勿清理。": "완료되지 않은 다운로드의 부분 파일과 하루 이상 된 임시 파일입니다. 다운로드가 진행 중이면 정리하지 마세요.", + "未找到 Docker": "Docker를 찾을 수 없습니다", + "未找到 Docker 命令行工具。请确认已安装 Docker Desktop。": "Docker CLI를 찾을 수 없습니다. Docker Desktop이 설치되어 있는지 확인하세요.", + "未找到 Wi-Fi 硬件。": "Wi-Fi 하드웨어를 찾을 수 없습니다.", + "未找到关联文件": "관련 파일이 없습니다", + "未找到大文件或旧文件": "크거나 오래된 파일이 없습니다", + "未找到第三方扩展、插件或偏好设置面板。": "타사 확장 프로그램, 플러그인 또는 환경설정 패널이 없습니다.", + "未找到邮件索引——邮件可能使用了不同的版本目录。": "Mail 색인을 찾을 수 없습니다. Mail이 다른 버전 폴더를 사용하고 있을 수 있습니다.", + "未找到重复文件": "중복 파일이 없습니다", + "未找到附件": "첨부 파일이 없습니다", + "未找到项目": "항목을 찾을 수 없습니다", + "未找到项目垃圾": "프로젝트 불필요한 파일이 없습니다", + "未检测到威胁": "탐지된 위협 없음", + "未注册": "등록되지 않음", + "未知": "알 수 없음", + "未知应用": "알 수 없는 앱", + "未知日期": "날짜를 알 수 없음", + "未知错误": "알 수 없는 오류", + "未能完成": "실패", + "未选择任何项目": "아무것도 선택되지 않았습니다", + "权限总览": "권한 개요", + "构建缓存": "빌드 캐시", + "查找大于 50 MB 且最近未访问的文件": "최근에 열지 않은 50MB 이상의 파일 찾기", + "查找并移除系统缓存、日志、\n语言文件和其他垃圾": "시스템 캐시, 로그, 언어 파일 등\n불필요한 파일을 찾아 삭제합니다", + "查找来自邮件、Outlook 和 Spark 的缓存邮件附件": "Mail, Outlook, Spark에서 캐시된 이메일 첨부 파일 찾기", + "查找重复文件": "중복 파일 찾기", + "查看占用 CPU 和内存的应用并强制退出": "CPU와 메모리를 많이 사용하는 앱을 확인하고 강제 종료", + "查看发布页": "릴리스 보기", + "查看日志": "로그 보기", + "查看第三方偏好设置面板、Internet 插件和 Safari 扩展。用户安装的面板和插件可移到废纸篓。": "타사 환경설정 패널, 인터넷 플러그인 및 Safari 확장 프로그램을 검토합니다. 사용자가 설치한 패널과 플러그인은 휴지통으로 이동할 수 있습니다.", + "标记为“保留”的行受保护,只会删除勾选的副本。": "유지로 표시된 행은 보호되며, 선택한 사본만 삭제됩니다.", + "检查可用的应用更新": "사용 가능한 앱 업데이트 확인", + "检查启动磁盘的文件系统完整性": "시동 디스크의 파일 시스템 무결성 확인", + "检查更新": "업데이트 확인", + "检测并移除威胁": "위협 탐지 및 제거", + "模式": "모드", + "正在分析应用支持目录...": "Application Support 분석 중...", + "正在分析系统...": "시스템 분석 중...", + "正在分析结果...": "결과 분석 중...", + "正在分析附件...": "첨부 파일 분석 중...", + "正在加载项目...": "항목 로드 중...", + "正在卸载…": "제거 중…", + "正在发现已安装应用...": "설치된 앱을 찾는 중...", + "正在完成...": "마무리 중...", + "正在完成扫描...": "검사를 마무리하는 중...", + "正在并行哈希候选文件...": "후보 파일을 병렬로 해싱하는 중...", + "正在开始清理...": "정리 시작 중...", + "正在恢复默认…": "재설정 중…", + "正在扫描 Apple Mail...": "Apple Mail 검사 중...", + "正在扫描 Chrome 数据...": "Chrome 데이터 검사 중...", + "正在扫描 Firefox 数据...": "Firefox 데이터 검사 중...", + "正在扫描 Outlook...": "Outlook 검사 중...", + "正在扫描 Safari 数据...": "Safari 데이터 검사 중...", + "正在扫描 Spark...": "Spark 검사 중...", + "正在扫描...": "검사 중...", + "正在扫描个人目录...": "홈 폴더 검사 중...", + "正在扫描启动守护进程...": "Launch Daemon 검사 중...", + "正在扫描用户废纸篓...": "사용자 휴지통 검사 중...", + "正在扫描用户缓存...": "사용자 캐시 검색 중...", + "正在扫描磁盘...": "디스크 검사 중...", + "正在扫描磁盘…": "디스크 검사 중…", + "正在扫描系统日志...": "시스템 로그 검사 중...", + "正在扫描缓存...": "캐시 검사 중...", + "正在按大小分组文件...": "파일을 크기별로 그룹화하는 중...", + "正在整理结果...": "결과 정리 중...", + "正在查找关联文件...": "관련 파일을 찾는 중...", + "正在查找扩展…": "확장 프로그램을 찾는 중…", + "正在查找未使用的应用…": "사용하지 않는 앱을 찾는 중…", + "正在查找项目…": "프로젝트를 찾는 중…", + "正在检查…": "확인 중…", + "正在检查偏好设置...": "환경설정 확인 중...", + "正在检查启动代理...": "Launch Agent 확인 중...", + "正在检查外接驱动器...": "외부 드라이브를 확인하는 중...", + "正在检查已知恶意软件特征...": "알려진 악성코드 서명을 확인하는 중...", + "正在检查文件大小...": "파일 크기를 확인하는 중...", + "正在检查更新...": "업데이트 확인 중...", + "正在检查浏览器扩展...": "브라우저 확장 프로그램을 확인하는 중...", + "正在检查登录项...": "로그인 항목을 확인하는 중...", + "正在检查系统痕迹...": "시스템 흔적을 확인하는 중...", + "正在检查访问日期...": "접근 날짜 확인 중...", + "正在检查语言文件...": "언어 파일을 확인하는 중...", + "正在检测已安装语言…": "설치된 언어를 감지하는 중…", + "正在清理你的 Mac...": "Mac 정리 중...", + "正在粉碎文件...": "파일을 파쇄하는 중...", + "正在计算大小...": "크기 계산 중...", + "正在计算文件夹大小…": "폴더 크기 계산 중…", + "正在读取已保存的网络…": "저장된 네트워크를 읽는 중…", + "正在读取扩展…": "확장 프로그램 읽는 중…", + "正在读取权限…": "권한 읽는 중…", + "正在读取进程…": "프로세스 읽는 중…", + "此扩展内置于 {browser},无法移除。": "이 확장 프로그램은 {browser}에 내장되어 있어 제거할 수 없습니다.", + "此扩展由管理策略安装,删除文件夹后 {browser} 会重新安装它。如果你不认识它,请在系统设置中搜索“描述文件”或“设备管理”,并移除你不认识的描述文件。": "이 확장 프로그램은 관리 정책으로 설치되었으므로 폴더를 삭제해도 {browser} 앱이 다시 설치합니다. 모르는 확장 프로그램이면 시스템 설정에서 프로필 또는 기기 관리를 검색하고 모르는 프로필을 모두 제거하세요.", + "此操作不可撤销,不会进入废纸篓。": "이 작업은 영구적입니다. 휴지통으로 이동하지 않습니다.", + "残留下载文件": "남은 다운로드 파일", + "每一项都会放回原位置。原位置已有的文件绝不会被覆盖。": "각 항목은 원래 위치로 돌아갑니다. 이미 해당 위치에 있는 파일은 덮어쓰지 않습니다.", + "每组都会保留一个副本,且永远不会被移除。": "각 그룹에서 사본 하나는 항상 보관되며 절대 제거되지 않습니다.", + "永久删除": "영구 삭제", + "永久删除所选模拟器项目?": "선택한 시뮬레이터 항목을 영구적으로 삭제하시겠습니까?", + "永久清理": "영구 삭제", + "永久清理所选 Docker 项目?": "선택한 Docker 항목을 영구 삭제하시겠습니까?", + "没有可显示的应用": "표시할 앱이 없습니다", + "没有可用的备份": "사용 가능한 백업이 없습니다", + "没有已保存的 Wi-Fi 网络": "저장된 Wi-Fi 네트워크가 없습니다", + "没有找到匹配的结果": "일치하는 결과가 없습니다", + "没有找到项目": "항목이 없습니다", + "没有符合条件的应用": "이 기간에 사용하지 않은 앱이 없습니다", + "没有自定义的文件打开方式": "사용자 정의 파일 연결 없음", + "没有订阅,没有广告,没有追踪。Mac Sai 是我和几位志愿者在业余时间做的。如果它帮你省下了买清理软件的钱,请我喝杯咖啡,让它对所有人继续免费。": "구독, 광고, 추적이 없습니다. 몇몇 자원봉사자와 함께 저녁과 주말에 Mac Sai를 개발합니다. 유료 정리 앱을 구입할 비용을 아꼈다면, 커피 한 잔의 후원으로 모두에게 무료로 제공하는 데 힘을 보태 주세요.", + "没有记录到错误。": "기록된 오류가 없습니다.", + "活动日志": "활동 로그", + "派生数据、归档和模拟器缓存。": "파생 데이터, 아카이브 및 시뮬레이터 캐시입니다.", + "浅色": "라이트", + "浏览历史和跟踪数据;Cookie 与会话会保留。": "방문 기록 및 추적 데이터입니다. 쿠키와 세션은 유지됩니다.", + "浏览器和其他网络应用会在下次请求时重新解析主机名,影响通常只有毫秒级。": "브라우저와 기타 네트워크 앱이 다음 요청 시 호스트 이름을 다시 확인하며, 영향은 보통 밀리초 수준입니다.", + "浏览器扩展": "브라우저 확장 프로그램", + "浏览器隐私": "브라우저 개인정보 보호", + "深度": "심층", + "深色": "다크", + "添加文件夹…": "폴더 추가…", + "清理": "정리", + "清理会删除悬空的构建缓存。下次构建可能会变慢。": "정리하면 연결되지 않은 빌드 캐시가 삭제됩니다. 다음 빌드가 더 느려질 수 있습니다.", + "清理会永久删除所有已停止的容器及其中的数据。正在运行的容器不受影响。": "정리하면 중지된 모든 컨테이너와 그 안의 데이터가 영구 삭제됩니다. 실행 중인 컨테이너는 영향을 받지 않습니다.", + "清理前请检查": "정리 전 검토", + "清理历史": "정리 기록", + "清理只会删除悬空(无标签)镜像,带标签的镜像会保留。": "태그가 없는 이미지만 삭제되며, 태그가 있는 이미지는 유지됩니다.", + "清理完成": "정리 완료", + "清理所选 Docker 项目…": "선택한 Docker 항목 정리…", + "清理所选项目": "선택 항목 정리", + "清理未使用的 Docker 镜像、已停止的容器和构建缓存": "사용하지 않는 Docker 이미지, 중지된 컨테이너 및 빌드 캐시 삭제", + "清理浏览器数据、历史记录、Cookie 和系统痕迹": "브라우저 데이터, 방문 기록, 쿠키 및 시스템 흔적 정리", + "清理缓存、日志和临时文件": "캐시, 로그 및 임시 파일 정리", + "清理非活动内存,为当前应用释放更多空间": "비활성 메모리를 정리해 실행 중인 앱에 더 많은 공간 확보", + "清空废纸篓": "휴지통 비우기", + "清空废纸篓?": "휴지통을 비우시겠습니까?", + "清空所有废纸篓位置,包括外接驱动器": "외장 드라이브를 포함한 모든 휴지통 위치 비우기", + "清除": "지우기", + "清除历史": "기록 지우기", + "清除本地 DNS 缓存并强制重新解析": "로컬 DNS 캐시를 지우고 새로 조회하도록 강제", + "清除清理历史?": "정리 기록을 지우시겠습니까?", + "清除缓存、偏好设置和保存的状态,保留应用本身。": "캐시, 환경설정 및 저장된 상태를 지웁니다. 앱은 설치된 상태로 유지됩니다.", + "源代码": "소스 코드", + "点击“扫描”以可视化磁盘使用情况": "검사를 클릭하여 디스크 사용량을 시각화하세요", + "点击“智能扫描”即可一键清理 Mac,也可以在侧边栏探索各个模块。": "스마트 검사를 클릭해 한 번에 Mac을 정리하거나 사이드바에서 개별 모듈을 살펴보세요.", + "点击上方按钮检查更新": "업데이트를 확인하려면 위의 버튼을 클릭하세요", + "版本历史": "버전 기록", + "用户": "사용자", + "用户日志文件": "사용자 로그 파일", + "用户缓存文件": "사용자 캐시 파일", + "由 macOS 管理的缓存,会自动重建。": "macOS가 관리하는 캐시입니다. 자동으로 다시 생성됩니다.", + "由 macOS 自行管理的缓存,需要时会自动重建。": "macOS가 관리하는 캐시입니다. 필요할 때 자동으로 다시 생성됩니다.", + "由策略安装": "정책에 따라 설치됨", + "电池": "배터리", + "电池循环次数较高": "배터리 사이클 수가 높음", + "电池温度": "배터리 온도", + "界面语言": "인터페이스 언어", + "登录时启动": "로그인 시 실행", + "登录项": "로그인 항목", + "相机": "카메라", + "磁盘": "디스크", + "磁盘映像": "디스크 이미지", + "移到废纸篓": "휴지통으로 이동", + "移到废纸篓?": "휴지통으로 이동하시겠습니까?", + "移除": "제거", + "移除不再使用的已保存网络,减少被追踪的可能。需要管理员权限。": "더 이상 사용하지 않는 저장된 네트워크를 제거해 위치 추적 가능성을 줄입니다. 관리자 권한이 필요합니다.", + "移除扩展?": "확장 프로그램을 삭제하시겠습니까?", + "移除背景颜色": "배경색 제거", + "稍后": "나중에", + "空间透视": "디스크 사용 현황", + "第三方": "타사", + "筛选": "필터", + "粉碎": "파쇄", + "精简 Time Machine 快照": "Time Machine 스냅샷 줄이기", + "精简后应用包无法再通过 codesign --verify": "축소 후 번들이 codesign --verify 검증을 통과하지 못함", + "系统": "시스템", + "系统垃圾": "시스템 불필요한 파일", + "系统日志文件": "시스템 로그 파일", + "系统缓存文件": "시스템 캐시 파일", + "系统隐私": "시스템 개인정보 보호", + "组件状态:": "위젯 상태:", + "继续": "계속", + "维护": "유지보수", + "缩减本地 Time Machine 快照以回收磁盘空间": "로컬 Time Machine 스냅샷 크기를 줄여 디스크 공간 확보", + "自动化": "자동화", + "自动检查更新": "자동으로 업데이트 확인", + "菜单栏显示": "메뉴 막대 표시", + "表格": "스프레드시트", + "视频": "비디오", + "设置": "설정", + "设置…": "설정…", + "该任务没有可执行的系统命令": "이 작업에는 실행할 시스템 명령이 없습니다", + "该路径已被现有排除项覆盖。": "해당 경로는 이미 기존 제외에 포함되어 있습니다.", + "该进程已不再运行。": "해당 프로세스는 더 이상 실행되지 않습니다.", + "详情": "세부정보", + "语言": "언어", + "语言文件": "언어 파일", + "语言清理": "언어 정리", + "请从侧边栏选择一个模块": "사이드바에서 모듈을 선택하세요", + "支持者": "후원자", + "感谢你们让 Mac Sai 保持免费:{names}。": "Mac Sai를 무료로 유지해 주셔서 감사합니다: {names}", + "支持 Mac Sai 的会员会列在这里。来做第一个吧。": "Mac Sai를 무료로 유지해 주는 멤버가 여기에 표시됩니다. 첫 번째 멤버가 되어 보세요.", + "成为会员,或请开发者喝杯咖啡": "멤버 가입 또는 개발자에게 커피 한 잔 사기", + "请我喝杯咖啡": "커피 한 잔 후원하기", + "请至少勾选一个要清理的项目": "정리할 항목을 하나 이상 선택하세요", + "请选择你的项目文件夹,而不是系统文件夹或资源库。": "시스템 폴더나 라이브러리가 아닌 프로젝트 폴더를 선택하세요.", + "请选择绝对路径。": "절대 경로를 선택하세요.", + "请重新扫描,勾选要移除的项目,然后点击“清理”。": "다시 검사하고 제거할 항목을 선택한 다음 정리를 클릭하세요.", + "谢谢你。正因为有你,它才能一直免费。": "감사합니다. 당신이 바로 이 앱이 무료로 유지되는 이유입니다.", + "超时,已停止": "시간 초과로 중지됨", + "超过 1 年": "1년 이상", + "超过 30 天的 iPhone 和 iPad 本地备份。如果这是设备唯一的备份,请保留或先备份到 iCloud。": "30일이 지난 iPhone 및 iPad 로컬 백업입니다. 기기의 유일한 백업이라면 보관하거나 먼저 iCloud에 백업하세요.", + "跟随系统": "시스템", + "跨卷": "다른 볼륨", + "跳过此版本": "이 버전 건너뛰기", + "输入的二进制文件不是通用 Mach-O": "입력 바이너리가 유니버설 Mach-O가 아님", + "运行 docker system prune,删除未使用的镜像、已停止的容器、未使用的网络和构建缓存。此操作不可撤销(不会进入废纸篓)。正在运行的容器、使用中的镜像和命名卷不受影响,磁盘映像 Docker.raw 也不会被直接删除。": "docker system prune을 실행하여 사용하지 않는 이미지, 중지된 컨테이너, 사용하지 않는 네트워크 및 빌드 캐시를 삭제합니다. 휴지통으로 이동하지 않으므로 되돌릴 수 없습니다. 실행 중인 컨테이너, 사용 중인 이미지 및 이름 있는 볼륨은 유지하며 Docker.raw 디스크 이미지를 직접 삭제하지 않습니다.", + "运行中": "실행 중", + "运行安全任务": "안전한 작업 실행", + "运行时间": "가동 시간", + "运行此任务": "이 작업 실행", + "运行系统维护任务,让 Mac 保持健康": "시스템 유지 관리 작업을 실행하여 Mac을 건강하게 유지하세요", + "运行维护脚本": "유지보수 스크립트 실행", + "返回": "뒤로", + "返回起点": "처음으로 돌아가기", + "还原": "복원", + "还原版本": "버전 복원", + "还没有可恢复的清理记录": "되돌릴 정리 기록이 없습니다", + "这只会忘掉恢复记录,废纸篓里的文件不会被动。之后就不能一键恢复这些清理了。": "복원 기록만 지웁니다. 휴지통의 파일은 그대로 있지만 이 정리 작업들을 더 이상 한 번의 클릭으로 복원할 수 없습니다.", + "这台 Mac": "이 Mac", + "这台 Mac 上没有找到 Docker 或 Xcode 模拟器。": "이 Mac에서 Docker 또는 Xcode 시뮬레이터를 찾을 수 없습니다.", + "这次清理太大,只能恢复前 %ld 项。其余 %ld 项仍在废纸篓中,可在访达里手动放回。": "이 정리 항목은 너무 커서 전체를 추적할 수 없습니다. 처음 %ld개 항목만 복원할 수 있습니다. 나머지 %ld개는 아직 휴지통에 있으므로 Finder에서 다시 넣을 수 있습니다.", + "这次清理,你没花一分钱。": "이번 정리에는 비용이 전혀 들지 않았습니다.", + "进度": "진행상황", + "退出": "종료", + "退出监视器": "모니터 종료", + "选中的项目会移到废纸篓,如有需要仍可恢复。": "선택한 항목은 휴지통으로 이동되며 필요한 경우 복구할 수 있습니다.", + "选择一个应用以查看相关文件": "관련 파일을 보려면 앱을 선택하세요", + "选择应用图标旁显示的紧凑数值。GPU 或电池温度不可用时显示 --。": "앱 아이콘 옆에 표시할 간단한 값을 선택하세요. GPU 또는 배터리 센서를 사용할 수 없으면 --로 표시됩니다.", + "选择文件": "파일 선택", + "选择要从清理中排除的文件夹。": "정리에서 제외할 폴더를 선택하세요.", + "选择项目文件夹(例如 ~/Code),查找 node_modules、venv、target、build 等可重建目录。": "프로젝트 폴더(예: ~/Code)를 선택하여 node_modules, venv, target, build 등 다시 생성할 수 있는 폴더를 찾으세요.", + "逐字节完全相同的副本。每个需要的文件请至少保留一份。": "바이트 단위로 동일한 복사본입니다. 필요한 각 파일의 복사본을 하나 이상 보관하세요.", + "通常没有可见影响——这些脚本与 macOS 夜间自动运行的维护脚本相同。": "눈에 띄는 영향은 없습니다. macOS가 밤마다 자동으로 실행하는 것과 같은 스크립트입니다.", + "通用": "일반", + "通用二进制": "범용 바이너리", + "通过精简低优先级本地快照回收可清除磁盘空间": "우선순위가 낮은 로컬 스냅샷을 줄여 제거 가능한 디스크 공간을 확보합니다.", + "邮件保存在磁盘上的附件副本。IMAP 和 Exchange 账户可从服务器重新下载,POP 账户不行。": "Mail이 디스크에 저장한 첨부 파일의 사본입니다. IMAP 및 Exchange 계정은 서버에서 다시 다운로드할 수 있지만 POP 계정은 불가능합니다.", + "邮件索引已移除。邮件将在下次启动时重建。": "Mail 색인이 제거되었습니다. Mail이 다음 실행 시 다시 생성합니다.", + "邮件附件": "Mail 첨부 파일", + "邮件附件的缓存副本。": "Mail 첨부 파일의 캐시된 사본입니다.", + "部分可恢复": "일부 복원 가능", + "释放内存": "RAM 확보", + "释放可清除空间": "제거 가능한 공간 확보", + "释放空间": "여유 공간 확보", + "重复文件": "중복 파일", + "重复文件检测会使用 SHA-256 哈希每个候选文件。\n大型个人目录可能需要 5–15 分钟。": "중복 검사 시 모든 후보 파일의 SHA-256 해시를 계산합니다.\n홈 폴더가 크면 5~15분 정도 걸릴 수 있습니다.", + "重建 Spotlight 搜索索引,提高搜索准确性": "검색 정확도를 높이기 위해 Spotlight 검색 색인 재생성", + "重建 Spotlight 索引": "Spotlight 색인 재생성", + "重建“邮件”数据库索引,以修复搜索和性能问题": "검색 및 성능 문제를 해결하기 위해 Mail 데이터베이스 색인 재생성", + "重建启动服务": "Launch Services 재구축", + "重新扫描": "다시 검사", + "重新扫描启动项": "시작 항목 다시 검사", + "重新检查": "다시 확인", + "重新读取已保存的网络": "저장된 네트워크 다시 로드", + "重新读取扩展列表": "확장 프로그램 목록 새로고침", + "重新读取权限列表": "권한 목록 새로고침", + "重试": "재시도", + "错误": "오류", + "镜像": "이미지", + "长时间未打开的文件。": "오랫동안 열지 않은 파일입니다.", + "防护": "보호", + "隐私清理": "개인 정보 보호", + "需要在“系统设置 → 登录项”中批准": "시스템 설정 → 로그인 항목에서 승인 필요", + "需要在“系统设置 → 通用 → 登录项”中批准": "시스템 설정 → 일반 → 로그인 항목에서 승인 필요", + "需要完全磁盘访问权限": "전체 디스크 접근 권한 필요", + "需要完全磁盘访问权限才能列出应用": "앱을 나열하려면 전체 디스크 접근 권한이 필요합니다", + "非 APFS 卷": "APFS 볼륨이 아님", + "非普通文件": "일반 파일이 아님", + "音频": "오디오", + "项目中已安装的依赖和构建产物。运行项目的安装或构建命令即可找回;之后第一次构建会更慢。": "프로젝트 내에 설치된 종속성과 빌드 결과물입니다. 프로젝트의 설치 또는 빌드 명령으로 다시 생성할 수 있으며, 이후 첫 빌드는 더 오래 걸립니다.", + "项目垃圾": "프로젝트 불필요한 파일", + "验证启动磁盘": "시동 디스크 확인", + "高级": "고급", + "麦克风": "마이크", + "清理权限": "정리 권한", + "允许 Mac Sai 扫描邮件、浏览器数据和其他受保护的文件夹。在系统设置中添加 Mac Sai 并开启权限,然后重新启动应用并重新扫描。": "Mac Sai가 Mail, 브라우저 데이터 및 기타 보호된 폴더를 검사할 수 있도록 허용합니다. 시스템 설정에서 Mac Sai를 추가하고 권한을 켠 다음 앱을 다시 시작하고 다시 검사하세요.", + "打开完全磁盘访问设置": "전체 디스크 접근 권한 설정 열기", + "管理员确认": "관리자 승인", + "移动受保护的项目时,macOS 可能仍会要求密码或触控 ID。完全磁盘访问权限不能代替管理员确认。Mac Sai 不保存您的密码,也不能提前批准所有操作。": "보호된 항목을 이동할 때 macOS가 여전히 암호나 Touch ID를 요청할 수 있습니다. 전체 디스크 접근 권한은 관리자 승인을 대신하지 않습니다. Mac Sai는 암호를 저장하지 않으며 모든 작업을 미리 승인할 수도 없습니다.", + "批量移到废纸篓": "그룹 단위로 휴지통으로 이동", + "清理会将选中的项目分组交给 macOS,减少逐项请求。系统决定是否需要再次确认。取消后,当前组会先完成;已移动的项目仍会显示在清理历史中。": "정리 시 선택한 항목을 그룹으로 묶어 macOS에 전달하므로 개별 요청이 줄어듭니다. 추가 승인이 필요한지는 시스템이 결정합니다. 취소하면 현재 그룹이 먼저 완료되며, 이미 이동된 항목은 정리 기록에 계속 표시됩니다.", + "权限": "권한", + "另一项清理仍在进行中。": "다른 정리 작업이 아직 진행 중입니다.", + "准备清理时文件已更改,请重新扫描。": "정리를 준비하는 동안 항목이 변경되었습니다. 다시 검사하세요.", + "无法确认项目在废纸篓中的位置,请检查访达。": "휴지통에서 항목의 위치를 확인할 수 없습니다. Finder에서 확인하세요.", + "macOS 未将此项目移到废纸篓。请检查权限并重新扫描。": "macOS가 이 항목을 휴지통으로 이동하지 않았습니다. 권한을 확인하고 다시 검사하세요.", + "符号链接改变了清理路径。请在访达中检查。": "심볼릭 링크로 인해 정리 경로가 변경되었습니다. Finder에서 항목을 확인하세요.", + "符号链接已跳过。": "심볼릭 링크를 건너뛰었습니다.", + "取消后会先完成当前一组。": "취소하면 현재 그룹이 먼저 완료됩니다.", + "清理已停止": "정리 중지됨", + "已处理": "처리됨", + "选中的文件夹与其内容计为一项。已经消失的文件会被跳过。": "선택한 폴더와 그 내용은 하나의 항목으로 계산됩니다. 이미 사라진 파일은 건너뜁니다.", + "部分项目未能清理": "일부 항목을 정리하지 못함", + "以上仅显示已完成的操作。移到废纸篓的项目可从清理历史恢复。请重新扫描以查看剩余或重新生成的文件。": "위에는 완료된 작업만 표시됩니다. 휴지통으로 이동한 항목은 정리 기록에서 복원할 수 있습니다. 남아 있거나 다시 생성된 파일을 확인하려면 다시 검사하세요.", + "请逐项检查并选择可能的威胁和社区报告的文件。此复选框只能取消该类别中已选中的项目。": "가능한 위협과 커뮤니티에서 신고한 파일은 하나씩 확인하고 선택하세요. 이 체크박스로는 이 카테고리에서 선택된 항목의 선택 해제만 할 수 있습니다.", + "全选": "모두 선택", + "取消全选": "모두 선택 해제", + "选择安全项目": "안전한 항목 선택", + "选择所有允许自动勾选的项目。需要手动检查的类别和可能的威胁保持不选。": "자동 선택이 허용된 모든 항목을 선택합니다. 직접 확인해야 하는 카테고리와 가능한 위협은 선택되지 않은 상태로 유지됩니다.", + "仅保留安全的临时文件、缓存、日志和残留文件。不选择个人数据、废纸篓或应用修改。": "안전한 임시 파일, 캐시, 로그 및 남은 파일만 선택된 상태로 유지합니다. 개인 데이터, 휴지통 및 앱 수정은 제외됩니다.", + "选中的文件会移到废纸篓,如有需要仍可恢复。": "선택한 파일은 휴지통으로 이동되며 필요한 경우 복구할 수 있습니다.", + "废纸篓中选中的项目将永久删除,无法恢复。": "휴지통에서 선택한 항목은 영구적으로 삭제되며 복구할 수 없습니다.", + "应用中未使用的架构将被移除。恢复可能需要重新安装应用。": "앱에서 사용하지 않는 아키텍처가 제거됩니다. 복원하려면 앱을 다시 설치해야 할 수 있습니다.", + "无法开启登录时启动:{message}": "로그인 시 실행을 켤 수 없음: {message}", + "无法关闭登录时启动:{message}": "로그인 시 실행을 끌 수 없음: {message}", + "提醒": "알림", + "内存压力提醒": "메모리 압력 알림", + "内存压力持续偏高时通知你。": "메모리 압력이 계속 높으면 알려 줍니다.", + "交换空间提醒": "스왑 사용량 알림", + "交换空间超过所选大小时通知一次,降到明显低于该值后才会再次提醒。": "스왑이 선택한 크기를 넘으면 한 번 알리고, 그보다 확실히 낮아진 후에만 다시 알립니다.", + "不提醒": "꺼짐", + "提醒由菜单栏小组件发送,需要保持开启。": "알림은 메뉴 막대 위젯이 보내므로 위젯이 켜져 있어야 합니다.", + "交换空间 {size}": "스왑 {size}", + "交换空间使用过高": "스왑 사용량이 높음", + "你的 Mac 正在使用 {used} 交换空间,超过了你设置的 {limit} 提醒值。退出不用的应用可以减轻内存压力。": "Mac이 스왑을 {used} 사용하고 있어 설정한 알림 기준 {limit}을(를) 초과했습니다. 사용하지 않는 앱을 종료하면 메모리 압력이 줄어듭니다.", + "Base 资源、Mac Sai 的界面语言以及你的 Mac 在“语言与地区”中设置的语言会始终保留。已勾选的语言会保留;未勾选的语言文件可由“系统垃圾”移除。": "Base 리소스, Mac Sai의 인터페이스 언어, Mac의 언어 및 지역에서 설정한 언어는 항상 유지됩니다. 선택한 언어는 유지되며, 선택하지 않은 언어 파일은 시스템 불필요한 파일에서 제거될 수 있습니다.", + "可能的威胁": "가능한 위협", + "Apple XProtect 特征:{name}": "Apple XProtect 서명: {name}", + "在 Apple 的 Safari 扩展黑名单中:{name}": "Apple의 Safari 확장 프로그램 차단 목록에 있음: {name}", + "名称与已知家族相符:{name}": "이름이 알려진 악성코드 계열과 일치: {name}", + "启动代理会运行“{name}”": "Launch Agent가 “{name}”을(를) 실행함", + "标记原因": "표시된 이유", + "没有可直接移除的威胁": "Mac Sai가 제거할 수 있는 위협 없음", + "已发现,但需要管理员才能移除": "발견되었지만 제거하려면 관리자 권한이 필요함", + "这些项目位于 Mac Sai 无法修改的系统文件夹中。请在 Finder 中显示每一项,然后输入管理员密码将其移到废纸篓。": "이 항목은 Mac Sai가 수정할 수 없는 시스템 폴더에 있습니다. 각 항목을 Finder에서 보고 관리자 암호를 입력해 휴지통으로 이동하세요.", + "Apple XProtect {version}:{count} 个哈希值,{blocked} 个被屏蔽的 Safari 扩展": "Apple XProtect {version}: 해시 {count}개, 차단된 Safari 확장 프로그램 {blocked}개", + "未在这台 Mac 上找到 Apple XProtect 数据": "이 Mac에서 Apple XProtect 데이터를 찾을 수 없음", + "在黑名单上或由社区报告、但也可能是你有意安装的软件的项目。": "차단 목록과 일치하거나 커뮤니티에서 신고했지만 의도적으로 설치한 소프트웨어일 수도 있는 항목입니다.", + "不会预先勾选。黑名单可能也涵盖曾经正当的软件的旧版本,社区报告也未经厂商确认,删除前请逐个核对。": "미리 선택되지 않습니다. 차단 목록에는 한때 정상이었던 소프트웨어의 이전 버전이 포함될 수 있고 커뮤니티 신고는 제조사가 확인한 것이 아니므로, 제거하기 전에 각 항목을 확인하세요.", + "正在比对 XProtect 和 MalwareBazaar 哈希值...": "XProtect 및 MalwareBazaar 해시 대조 중...", + "已报告至 MalwareBazaar:{name}": "MalwareBazaar에 신고됨: {name}", + "MalwareBazaar:未启用(可在设置中添加免费的 Auth-Key)": "MalwareBazaar: 꺼짐(설정에서 무료 Auth-Key를 추가하세요)", + "MalwareBazaar:{count} 个哈希值,更新于 {date}": "MalwareBazaar: 해시 {count}개, {date} 업데이트됨", + "恶意软件数据库": "악성코드 데이터베이스", + "版本 {version}:{hashes} 个哈希值,{blocked} 个被屏蔽的 Safari 扩展。由 macOS 自动更新。": "버전 {version}: 해시 {hashes}개, 차단된 Safari 확장 프로그램 {blocked}개. macOS가 자동으로 최신 상태로 유지합니다.", + "可选。按下“立即更新”时,使用你免费的 abuse.ch Auth-Key 下载最近报告的 macOS 恶意软件样本哈希值。每次请求只发送你的 Auth-Key 和查询内容,绝不发送文件哈希值或路径。如果某个哈希与已签名的文件匹配,macOS 会向 Apple 查询其签名证书是否已被吊销。匹配项不会预先勾选。": "선택 사항입니다. 지금 업데이트를 누르면 무료 abuse.ch Auth-Key를 사용해 최근 신고된 macOS 악성코드 샘플의 해시를 다운로드합니다. 각 요청에는 Auth-Key와 조회 내용만 전송되며 파일 해시나 경로는 절대 전송되지 않습니다. 해시가 서명된 파일과 일치하면 macOS가 Apple에 해당 서명 인증서가 폐기되었는지 확인합니다. 일치 항목은 미리 선택되지 않습니다.", + "abuse.ch Auth-Key": "abuse.ch의 Auth-Key", + "保存密钥": "키 저장", + "移除密钥和哈希值": "키 및 해시 제거", + "立即更新": "지금 업데이트", + "获取免费密钥": "무료 키 받기", + "正在更新…": "업데이트 중…", + "密钥已保存在你的钥匙串中。": "키가 키체인에 저장되었습니다.", + "无法将密钥保存到钥匙串。": "키를 키체인에 저장할 수 없습니다.", + "无法移除密钥或哈希值。": "키 또는 해시를 제거할 수 없습니다.", + "Auth-Key 被拒绝。请在 auth.abuse.ch 检查。": "Auth-Key가 거부되었습니다. auth.abuse.ch에서 확인하세요.", + "尚未下载哈希值。": "아직 다운로드한 해시가 없습니다.", + "已更新:新增 {added} 个,共 {total} 个哈希值。": "업데이트됨: 새 해시 {added}개, 총 {total}개.", + "部分查询失败:{list}": "일부 조회 실패: {list}", + "更新失败:{list}": "업데이트 실패: {list}", + "无法保存下载的哈希列表。": "다운로드한 해시 목록을 저장할 수 없습니다.", + "服务器要求重定向,已拒绝": "서버가 리디렉션을 요청하여 거부함", + "响应过大": "응답이 너무 큼", + "响应格式不正确": "응답 형식이 올바르지 않음", + ] + /// Small fallback table for values that are assembled dynamically or flow /// through model properties. Most UI strings use the three-argument overload /// so every supported translation lives beside the original expression. diff --git a/Tests/MacCleanKitTests/BatchCleanupLocalizationTests.swift b/Tests/MacCleanKitTests/BatchCleanupLocalizationTests.swift index 1a4f3a0..080c1d1 100644 --- a/Tests/MacCleanKitTests/BatchCleanupLocalizationTests.swift +++ b/Tests/MacCleanKitTests/BatchCleanupLocalizationTests.swift @@ -31,7 +31,7 @@ final class BatchCleanupLocalizationTests: AppLanguageTestCase { ] // These phrases are written identically in both Chinese scripts. let sameInTraditional: Set = ["清理已停止", "完成", "清理完成"] - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .zhHant] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .zhHant] { AppLanguage.current = language for key in keys { let value = L10n.tr(key, "MISSING_CLEANUP_TRANSLATION", "RU") diff --git a/Tests/MacCleanKitTests/CleanupLocalizationTests.swift b/Tests/MacCleanKitTests/CleanupLocalizationTests.swift index 0aeb024..7717dff 100644 --- a/Tests/MacCleanKitTests/CleanupLocalizationTests.swift +++ b/Tests/MacCleanKitTests/CleanupLocalizationTests.swift @@ -14,7 +14,7 @@ final class CleanupLocalizationTests: AppLanguageTestCase { ] func testStaticCleanupCopyIsTranslatedForEveryDictionaryBackedLanguage() { - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .zhHant] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .zhHant] { AppLanguage.current = language for key in staticKeys { let value = L10n.tr(key, "UNTRANSLATED", "Russian") @@ -29,7 +29,7 @@ final class CleanupLocalizationTests: AppLanguageTestCase { AppLanguage.current = .en let english = [CleanupStrings.selectionSummary(selected: 2, total: 21), CleanupStrings.confirmationTitle(count: 2), CleanupStrings.itemCount(2)] - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru, .zhHans, .zhHant] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru, .zhHans, .zhHant] { AppLanguage.current = language let localized = [CleanupStrings.selectionSummary(selected: 2, total: 21), CleanupStrings.confirmationTitle(count: 2), CleanupStrings.itemCount(2)] diff --git a/Tests/MacCleanKitTests/HealthAlertsTests.swift b/Tests/MacCleanKitTests/HealthAlertsTests.swift index 5ec0548..96dabf4 100644 --- a/Tests/MacCleanKitTests/HealthAlertsTests.swift +++ b/Tests/MacCleanKitTests/HealthAlertsTests.swift @@ -84,7 +84,7 @@ final class HealthAlertLocalizationTests: AppLanguageTestCase { let english = allStrings() AppLanguage.current = .zhHans let simplified = allStrings() - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko] { AppLanguage.current = language for (index, translated) in allStrings().enumerated() where index != swapLine { XCTAssertNotEqual(translated, english[index], "\(language): \(english[index])") @@ -97,7 +97,7 @@ final class HealthAlertLocalizationTests: AppLanguageTestCase { } func testPlaceholdersAreFilledInEveryLanguage() { - for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ru, .zhHans, .zhHant] { + for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ko, .ru, .zhHans, .zhHant] { AppLanguage.current = language let body = HealthAlertStrings.swapAlertBody(used: 6_800_000_000, threshold: 4_000_000_000) XCTAssertFalse(body.contains("{"), "\(language): \(body)") diff --git a/Tests/MacCleanKitTests/LocalizationTests.swift b/Tests/MacCleanKitTests/LocalizationTests.swift index da1cf3c..d84c5b6 100644 --- a/Tests/MacCleanKitTests/LocalizationTests.swift +++ b/Tests/MacCleanKitTests/LocalizationTests.swift @@ -31,12 +31,49 @@ final class LocalizationTests: AppLanguageTestCase { } } + func testKoreanLanguageSelectionAndRegionalIdentifiers() { + XCTAssertTrue(AppLanguage.allCases.contains(.ko)) + XCTAssertEqual(AppLanguage.ko.rawValue, "ko") + XCTAssertEqual(AppLanguage.ko.pickerLabel, "한국어") + XCTAssertEqual(AppLanguage.ko.localeIdentifier, "ko") + for identifier in ["ko", "ko-KR", "ko_KR", "KO-kr"] { + XCTAssertEqual(AppLanguage.preferredLanguage(for: identifier), .ko, identifier) + } + } + + func testKoreanTranslationOverloadsAndFallbacks() { + AppLanguage.current = .ko + XCTAssertEqual(L10n.tr("设置", "Settings"), "설정") + XCTAssertEqual(L10n.tr("设置", "Settings", "Настройки"), "설정") + XCTAssertEqual(L10n.tr("设置"), "설정") + XCTAssertEqual(MaintenanceTask.freeUpRAM.title, "RAM 확보") + XCTAssertEqual(ScanCategory.userCaches.displayName, "사용자 캐시 파일") + XCTAssertEqual(FileListSort.sizeDescending.label, "큰 파일 먼저") + XCTAssertEqual(L10n.tr("未翻译", "New feature"), "New feature") + XCTAssertEqual(L10n.tr("未翻译", "New feature", "Russian"), "New feature") + XCTAssertEqual(L10n.tr("未翻译"), "未翻译") + for count in [1, 2] { + let english = "\(count) threat\(count == 1 ? "" : "s") found" + XCTAssertEqual(L10n.tr("发现 \(count) 个威胁", english), english) + XCTAssertEqual(L10n.tr("发现 \(count) 个威胁", english, "Russian"), english) + } + } + func testBrazilianPortugueseLanguageResourcesCannotBeOfferedForCleanup() { for folder in ["pt.lproj", "pt-BR.lproj", "pt_BR.lproj", "Portuguese.lproj", "Portuguese (Brazil).lproj", "Brazilian Portuguese.lproj"] { XCTAssertTrue(LanguagePreferences.alwaysKept.contains(folder), folder) } } + func testKoreanLanguageResourcesCannotBeOfferedForCleanup() { + let original = LanguagePreferences.discoveredLproj + defer { LanguagePreferences.discoveredLproj = original } + let folders: Set = ["ko.lproj", "ko-KR.lproj", "ko_KR.lproj", "Korean.lproj"] + LanguagePreferences.discoveredLproj = folders + XCTAssertTrue(folders.isSubset(of: LanguagePreferences.alwaysKept)) + XCTAssertTrue(LanguagePreferences.selectableLanguages().isEmpty) + } + func testGermanLanguageSelectionAndRegionalIdentifiers() { XCTAssertTrue(AppLanguage.allCases.contains(.de)) XCTAssertEqual(AppLanguage.de.pickerLabel, "Deutsch") @@ -264,7 +301,7 @@ final class LocalizationTests: AppLanguageTestCase { ("清除", "Clear", "Очистить"), ("这只会忘掉恢复记录,废纸篓里的文件不会被动。之后就不能一键恢复这些清理了。", "This only forgets the restore list. Nothing in the Trash is touched, but these cleans can no longer be restored in one click.", "Это"), ] - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko] { AppLanguage.current = language for (zh, en, ru) in strings { let value = L10n.tr(zh, en, ru) @@ -380,6 +417,7 @@ final class LocalizationTests: AppLanguageTestCase { .es: "Invítame a un café", .ptBR: "Me pague um café", .ja: "コーヒーをおごる", + .ko: "커피 한 잔 후원하기", .zhHant: "請我喝杯咖啡", .ru: "Угостить кофе", ] @@ -401,7 +439,7 @@ final class LocalizationTests: AppLanguageTestCase { let sameAsSimplified: Set = [ "容器", "卷", "大小", "取消", "永久清理", "清理完成", "未能完成", "已停止", ] - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru] { AppLanguage.current = language for (index, value) in DiskHogsText.all.enumerated() where !sameAsEnglish.contains(english[index]) || language == .ru { XCTAssertNotEqual(value, english[index], "\(language) is missing: \(english[index])") @@ -431,7 +469,7 @@ final class LocalizationTests: AppLanguageTestCase { ("正在查找项目…", "Finding projects…", "Поиск проектов…"), ("正在计算文件夹大小…", "Measuring folders…", "Подсчёт размера папок…"), ] - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .zhHant, .ru] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .zhHant, .ru] { AppLanguage.current = language for s in strings { let text = L10n.tr(s.zh, s.en, s.ru) @@ -475,7 +513,7 @@ final class LocalizationTests: AppLanguageTestCase { let sameInTraditional: Set = ["未知"] for (zh, english) in strings { - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko] { AppLanguage.current = language XCTAssertNotEqual(L10n.tr(zh, english), english, "\(language) is missing \"\(english)\"") } diff --git a/Tests/MacCleanKitTests/SupportersTests.swift b/Tests/MacCleanKitTests/SupportersTests.swift index c924320..ef3a478 100644 --- a/Tests/MacCleanKitTests/SupportersTests.swift +++ b/Tests/MacCleanKitTests/SupportersTests.swift @@ -64,7 +64,7 @@ final class SupporterStringsTests: AppLanguageTestCase { let english = allStrings() AppLanguage.current = .zhHans let simplified = allStrings() - for language in [AppLanguage.de, .fr, .it, .ru, .ja, .ptBR, .es] { + for language in [AppLanguage.de, .fr, .it, .ru, .ko, .ja, .ptBR, .es] { AppLanguage.current = language for (index, translated) in allStrings().enumerated() { XCTAssertNotEqual(translated, english[index], "\(language): \(english[index])") @@ -77,7 +77,7 @@ final class SupporterStringsTests: AppLanguageTestCase { } func testPlaceholderIsFilledInEveryLanguage() { - for language in [AppLanguage.en, .de, .fr, .it, .ru, .zhHans, .zhHant, .ja, .ptBR, .es] { + for language in [AppLanguage.en, .de, .fr, .it, .ru, .zhHans, .zhHant, .ko, .ja, .ptBR, .es] { AppLanguage.current = language let caption = SupporterStrings.caption(for: ["Ada"]) XCTAssertTrue(caption.contains("Ada"), "\(language): \(caption)") diff --git a/Tests/MacCleanTests/BrowserExtensionsLocalizationTests.swift b/Tests/MacCleanTests/BrowserExtensionsLocalizationTests.swift index c583688..0b733f3 100644 --- a/Tests/MacCleanTests/BrowserExtensionsLocalizationTests.swift +++ b/Tests/MacCleanTests/BrowserExtensionsLocalizationTests.swift @@ -56,7 +56,7 @@ final class BrowserExtensionsLocalizationTests: EnglishAppLanguageTestCase { AppLanguage.current = .zhHans let simplified = allStrings() - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru] { AppLanguage.current = language for (index, value) in allStrings().enumerated() { XCTAssertNotEqual(value, english[index], "\(language) is untranslated: \(english[index])") @@ -70,7 +70,7 @@ final class BrowserExtensionsLocalizationTests: EnglishAppLanguageTestCase { } func testNoEmDashesOrUnfilledPlaceholders() { - for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ru, .zhHans, .zhHant] { + for language in [AppLanguage.en, .de, .fr, .it, .es, .ptBR, .ja, .ko, .ru, .zhHans, .zhHant] { AppLanguage.current = language for value in allStrings() { XCTAssertFalse(value.contains("\u{2014}"), "\(language) has an em dash: \(value)") diff --git a/Tests/MacCleanTests/LaunchAtLoginErrorLocalizationTests.swift b/Tests/MacCleanTests/LaunchAtLoginErrorLocalizationTests.swift index fd2b9ec..15b3810 100644 --- a/Tests/MacCleanTests/LaunchAtLoginErrorLocalizationTests.swift +++ b/Tests/MacCleanTests/LaunchAtLoginErrorLocalizationTests.swift @@ -26,6 +26,7 @@ final class LaunchAtLoginErrorLocalizationTests: EnglishAppLanguageTestCase { (.ptBR, "Não foi possível ativar a abertura ao iniciar sessão: MSG", "Não foi possível desativar a abertura ao iniciar sessão: MSG"), (.ja, "ログイン時に起動をオンにできませんでした:MSG", "ログイン時に起動をオフにできませんでした:MSG"), + (.ko, "로그인 시 실행을 켤 수 없음: MSG", "로그인 시 실행을 끌 수 없음: MSG"), (.ru, "Не удалось включить запуск при входе: MSG", "Не удалось отключить запуск при входе: MSG"), (.zhHans, "无法开启登录时启动:MSG", "无法关闭登录时启动:MSG"), (.zhHant, "無法開啟登入時啟動:MSG", "無法關閉登入時啟動:MSG"), diff --git a/Tests/MacCleanTests/MalwareLocalizationTests.swift b/Tests/MacCleanTests/MalwareLocalizationTests.swift index 8be3beb..33d3a41 100644 --- a/Tests/MacCleanTests/MalwareLocalizationTests.swift +++ b/Tests/MacCleanTests/MalwareLocalizationTests.swift @@ -61,7 +61,7 @@ final class MalwareLocalizationTests: EnglishAppLanguageTestCase { AppLanguage.current = .zhHans let simplified = allStrings() - for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ru] { + for language in [AppLanguage.de, .fr, .it, .es, .ptBR, .ja, .ko, .ru] { AppLanguage.current = language for (index, value) in allStrings().enumerated() { XCTAssertNotEqual(value, english[index], "\(language) is untranslated: \(english[index])") diff --git a/VERSION b/VERSION index 15b13fd..82a5f3b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.28.4 +1.28.5 diff --git a/scripts/build-dmg.sh b/scripts/build-dmg.sh index 9372bdf..00d5ad7 100755 --- a/scripts/build-dmg.sh +++ b/scripts/build-dmg.sh @@ -110,6 +110,7 @@ cat > "${APP_BUNDLE}/Contents/Info.plist" << PLIST es pt-BR ja + ko CFBundleExecutable MacClean @@ -189,6 +190,7 @@ cat > "${MENU_APP}/Contents/Info.plist" << MENU_PLIST es pt-BR ja + ko CFBundleExecutable MacCleanMenu