Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions PureMac/Views/Components/EmptyStateView.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import SwiftUI

struct EmptyStateView: View {
let title: String
let title: LocalizedStringKey
let systemImage: String
let description: String
let description: LocalizedStringKey
var action: (() -> Void)?
var actionLabel: String?
var actionLabel: LocalizedStringKey?

init(_ title: String, systemImage: String, description: String, action: (() -> Void)? = nil, actionLabel: String? = nil) {
init(_ title: LocalizedStringKey, systemImage: String, description: LocalizedStringKey, action: (() -> Void)? = nil, actionLabel: LocalizedStringKey? = nil) {
self.title = title
self.systemImage = systemImage
self.description = description
Expand All @@ -29,7 +29,7 @@ struct EmptyStateView: View {
.multilineTextAlignment(.center)
.frame(maxWidth: 300)
if let action, let label = actionLabel {
Button(label, action: action)
Button(action: action) { Text(label) }
.buttonStyle(.borderedProminent)
.padding(.top, 4)
}
Expand Down
29 changes: 20 additions & 9 deletions PureMac/Views/MainWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,23 @@ struct MainWindow: View {
let smartSize = appState.categoryResults[.smartScan]?.totalSize ?? appState.totalJunkSize
let smartBadge = smartSize > 0 ? ByteCountFormatter.string(fromByteCount: smartSize, countStyle: .file) : nil
var items: [SidebarItem] = [
SidebarItem(section: .cleaning(.smartScan), label: CleaningCategory.smartScan.rawValue, icon: CleaningCategory.smartScan.icon, badge: smartBadge, group: "Home"),
SidebarItem(section: .apps, label: "Installed Apps", icon: "square.grid.2x2", badge: "\(appState.installedApps.count)", group: "Applications"),
SidebarItem(section: .orphans, label: "Orphaned Files", icon: "doc.questionmark", badge: appState.orphanedFiles.count > 0 ? "\(appState.orphanedFiles.count)" : nil, group: "Applications"),
SidebarItem(section: .cleaning(.smartScan), label: LocalizedStringKey(CleaningCategory.smartScan.rawValue), icon: CleaningCategory.smartScan.icon, badge: smartBadge, group: .home),
SidebarItem(section: .apps, label: "Installed Apps", icon: "square.grid.2x2", badge: "\(appState.installedApps.count)", group: .applications),
SidebarItem(section: .orphans, label: "Orphaned Files", icon: "doc.questionmark", badge: appState.orphanedFiles.count > 0 ? "\(appState.orphanedFiles.count)" : nil, group: .applications),
]
for category in CleaningCategory.scannable {
let size = appState.categoryResults[category]?.totalSize ?? 0
let badge = size > 0 ? ByteCountFormatter.string(fromByteCount: size, countStyle: .file) : nil
items.append(SidebarItem(section: .cleaning(category), label: category.rawValue, icon: category.icon, badge: badge, group: "Cleaning"))
items.append(SidebarItem(section: .cleaning(category), label: LocalizedStringKey(category.rawValue), icon: category.icon, badge: badge, group: .cleaning))
}
return items
}

private var sidebar: some View {
List(selection: $selectedSection) {
let grouped = Dictionary(grouping: allSidebarItems, by: \.group)
let order = ["Home", "Applications", "Cleaning"]
ForEach(order, id: \.self) { group in
Section(group) {
ForEach(SidebarGroup.allCases, id: \.self) { group in
Section(group.title) {
ForEach(grouped[group] ?? [], id: \.section) { item in
HStack {
Label(item.label, systemImage: item.icon)
Expand Down Expand Up @@ -81,10 +80,22 @@ struct MainWindow: View {
}
}

private enum SidebarGroup: Hashable, CaseIterable {
case home, applications, cleaning

var title: LocalizedStringKey {
switch self {
case .home: return "Home"
case .applications: return "Applications"
case .cleaning: return "Cleaning"
}
}
}

private struct SidebarItem {
let section: AppSection
let label: String
let label: LocalizedStringKey
let icon: String
let badge: String?
let group: String
let group: SidebarGroup
}
136 changes: 136 additions & 0 deletions PureMac/ar.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* Full Disk Access Banner */
"Full Disk Access Required" = "يلزم منح الوصول الكامل إلى القرص";
"PureMac needs Full Disk Access to scan Trash, Mail, Desktop, Documents, and Homebrew cache." = "يحتاج PureMac إلى الوصول الكامل للقرص لفحص سلة المهملات والبريد وسطح المكتب والمستندات وذاكرة التخزين المؤقت لـ Homebrew.";
"Open Settings" = "فتح الإعدادات";

/* Top Bar */
"Macintosh HD" = "Macintosh HD";
"%@ free" = "%@ متاحة";
"Auto-clean: " = "التنظيف التلقائي: ";

/* Sidebar */
"CLEANING" = "التنظيف";
"Last cleaned: %@" = "آخر تنظيف: %@";
"Home" = "الرئيسية";
"Applications" = "التطبيقات";
"Cleaning" = "التنظيف";
"Installed Apps" = "التطبيقات المثبّتة";
"Orphaned Files" = "الملفات اليتيمة";
"Select a category from the sidebar to get started." = "اختر فئة من الشريط الجانبي للبدء.";

/* Smart Scan */
"Smart Scan" = "الفحص الذكي";
"Click Scan to start" = "انقر على فحص للبدء";
"Total" = "الإجمالي";
"Used" = "المستخدمة";
"Free" = "المتاحة";
"Purgeable" = "قابلة للتحرير";
"junk found" = "ملفات غير مرغوبة";
"Your Mac is clean!" = "جهاز Mac نظيف!";
"freed up" = "تم تحريرها";
"Cleaning..." = "جارٍ التنظيف...";
"Scanning..." = "جارٍ الفحص...";
"%lld/%lld items" = "%lld/%lld عنصر";

/* Category Detail */
"All Clean!" = "كل شيء نظيف!";
"No junk files found in this category." = "لا توجد ملفات غير مرغوبة في هذه الفئة.";
"Not scanned yet" = "لم يتم الفحص بعد";
"Click Scan to analyze this category" = "انقر على فحص لتحليل هذه الفئة";
"%lld of %lld selected" = "%lld من %lld محدد";
"Select All" = "تحديد الكل";
"Deselect All" = "إلغاء تحديد الكل";
"%lld items" = "%lld عنصر";

/* Buttons */
"Scan" = "فحص";
"Re-scan" = "إعادة الفحص";
"Scan Again" = "فحص مرة أخرى";
"Done" = "تم";
"Clean (%@)" = "تنظيف (%@)";
"Clean %lld items (%@)" = "تنظيف %lld عنصر (%@)";

/* Settings - Schedule */
"Schedule" = "الجدولة";
"Automatic Cleaning" = "التنظيف التلقائي";
"Automatically scan and clean your Mac on a schedule" = "فحص جهاز Mac وتنظيفه تلقائيًا وفق جدول زمني";
"Scan Interval" = "الفاصل الزمني للفحص";
"Automation" = "الأتمتة";
"Auto-clean after scan" = "التنظيف التلقائي بعد الفحص";
"Minimum junk size to trigger clean:" = "الحد الأدنى لحجم الملفات لبدء التنظيف:";
"50 MB" = "50 ميغابايت";
"100 MB" = "100 ميغابايت";
"250 MB" = "250 ميغابايت";
"500 MB" = "500 ميغابايت";
"1 GB" = "1 غيغابايت";
"Auto-purge purgeable space" = "تحرير المساحة القابلة للإزالة تلقائيًا";
"Show notification on completion" = "إظهار إشعار عند الانتهاء";
"Status" = "الحالة";
"Last run" = "آخر تشغيل";
"Next run" = "التشغيل التالي";
"Never" = "أبدًا";
"Not scheduled" = "لم تُجدول";

/* Settings - General */
"General" = "عام";
"App Behavior" = "سلوك التطبيق";
"Launch at login" = "التشغيل عند تسجيل الدخول";
"Show in Dock" = "إظهار في Dock";
"Show menu bar icon" = "إظهار أيقونة في شريط القوائم";
"Safety" = "الأمان";
"PureMac will never delete system-critical files. Only caches, logs, temporary files, and user-selected items are removed." = "لن يحذف PureMac أبدًا ملفات النظام الأساسية. لا تُزال سوى ذاكرة التخزين المؤقت والسجلات والملفات المؤقتة والعناصر التي يحددها المستخدم.";

/* Settings - About */
"About" = "حول";
"Version 1.0.0" = "الإصدار 1.0.0";
"A free, open-source Mac cleaning utility.\nKeep your Mac fast, clean, and optimized." = "أداة مجانية ومفتوحة المصدر لتنظيف الـ Mac.\nحافظ على سرعة جهازك ونظافته وكفاءته.";
"GitHub Repository" = "مستودع GitHub";
"MIT License" = "رخصة MIT";

/* Cleaning Categories */
"System Junk" = "ملفات النظام غير المرغوبة";
"User Cache" = "ذاكرة التخزين المؤقت للمستخدم";
"AI Apps" = "تطبيقات الذكاء الاصطناعي";
"Mail Files" = "ملفات البريد";
"Trash Bins" = "سلة المهملات";
"Large & Old Files" = "الملفات الكبيرة والقديمة";
"Purgeable Space" = "المساحة القابلة للإزالة";
"Xcode Junk" = "ملفات Xcode غير المرغوبة";
"Brew Cache" = "ذاكرة التخزين المؤقت لـ Brew";

/* Category Descriptions */
"Scan everything at once" = "فحص كل شيء مرة واحدة";
"System caches, logs, and temporary files" = "ذاكرة التخزين المؤقت للنظام والسجلات والملفات المؤقتة";
"Application caches and browser data" = "ذاكرة التخزين المؤقت للتطبيقات وبيانات المتصفح";
"Logs, caches, and temporary files from local AI apps" = "السجلات وذاكرة التخزين المؤقت والملفات المؤقتة لتطبيقات الذكاء الاصطناعي المحلية";
"Downloaded mail attachments" = "مرفقات البريد التي تم تنزيلها";
"Files in your Trash" = "الملفات الموجودة في سلة المهملات";
"Files over 100 MB or older than 1 year" = "الملفات التي يزيد حجمها عن 100 ميغابايت أو الأقدم من سنة";
"APFS purgeable disk space" = "مساحة القرص القابلة للإزالة في APFS";
"Derived data, archives, and simulators" = "البيانات المشتقة والأرشيفات والمحاكيات";
"Homebrew download cache" = "ذاكرة التخزين المؤقت لتنزيلات Homebrew";

/* Schedule Intervals */
"Every Hour" = "كل ساعة";
"Every 3 Hours" = "كل 3 ساعات";
"Every 6 Hours" = "كل 6 ساعات";
"Every 12 Hours" = "كل 12 ساعة";
"Daily" = "يوميًا";
"Weekly" = "أسبوعيًا";
"Every 2 Weeks" = "كل أسبوعين";
"Monthly" = "شهريًا";

/* Notifications */
"Found %@ of junk files." = "تم العثور على %@ من الملفات غير المرغوبة.";

/* Node Cache */
"Node Cache" = "ذاكرة التخزين المؤقت لـ Node";
"npm, yarn, and pnpm download caches" = "ذاكرة التخزين المؤقت لتنزيلات npm وyarn وpnpm";
"npm cache" = "ذاكرة التخزين المؤقت لـ npm";
"yarn classic cache" = "ذاكرة التخزين المؤقت لـ yarn الكلاسيكي";
"pnpm content-addressable store" = "مخزن المحتوى المُعنوَن لـ pnpm";

/* Docker Cache */
"Docker Cache" = "ذاكرة التخزين المؤقت لـ Docker";
"Docker images, containers, and build cache" = "صور Docker والحاويات وذاكرة التخزين المؤقت للبناء";
"Reclaimable (run `docker system prune -af`)" = "قابلة للاسترداد (شغّل `docker system prune -af`)";
6 changes: 6 additions & 0 deletions PureMac/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
/* Sidebar */
"CLEANING" = "CLEANING";
"Last cleaned: %@" = "Last cleaned: %@";
"Home" = "Home";
"Applications" = "Applications";
"Cleaning" = "Cleaning";
"Installed Apps" = "Installed Apps";
"Orphaned Files" = "Orphaned Files";
"Select a category from the sidebar to get started." = "Select a category from the sidebar to get started.";

/* Smart Scan */
"Smart Scan" = "Smart Scan";
Expand Down
6 changes: 6 additions & 0 deletions PureMac/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
/* Sidebar */
"CLEANING" = "LIMPIEZA";
"Last cleaned: %@" = "Última limpieza: %@";
"Home" = "Inicio";
"Applications" = "Aplicaciones";
"Cleaning" = "Limpieza";
"Installed Apps" = "Apps instaladas";
"Orphaned Files" = "Archivos huérfanos";
"Select a category from the sidebar to get started." = "Selecciona una categoría en la barra lateral para comenzar.";

/* Smart Scan */
"Smart Scan" = "Análisis inteligente";
Expand Down
6 changes: 6 additions & 0 deletions PureMac/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
/* Sidebar */
"CLEANING" = "クリーニング";
"Last cleaned: %@" = "最終クリーン: %@";
"Home" = "ホーム";
"Applications" = "アプリケーション";
"Cleaning" = "クリーニング";
"Installed Apps" = "インストール済みアプリ";
"Orphaned Files" = "孤立ファイル";
"Select a category from the sidebar to get started." = "サイドバーからカテゴリを選択して始めてください。";

/* Smart Scan */
"Smart Scan" = "スマートスキャン";
Expand Down
6 changes: 6 additions & 0 deletions PureMac/zh-Hans.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
/* Sidebar */
"CLEANING" = "清理";
"Last cleaned: %@" = "上次清理:%@";
"Home" = "主页";
"Applications" = "应用程序";
"Cleaning" = "清理";
"Installed Apps" = "已安装应用";
"Orphaned Files" = "孤立文件";
"Select a category from the sidebar to get started." = "从侧边栏选择一个类别开始。";

/* Smart Scan */
"Smart Scan" = "智能扫描";
Expand Down
6 changes: 6 additions & 0 deletions PureMac/zh-Hant.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
/* Sidebar */
"CLEANING" = "清理";
"Last cleaned: %@" = "上次清理:%@";
"Home" = "首頁";
"Applications" = "應用程式";
"Cleaning" = "清理";
"Installed Apps" = "已安裝應用程式";
"Orphaned Files" = "孤立檔案";
"Select a category from the sidebar to get started." = "從側邊欄選擇一個類別開始。";

/* Smart Scan */
"Smart Scan" = "智慧掃描";
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

<p align="center">
<b>English</b> |
<a href="docs/README.ar.md">العربية</a> |
<a href="docs/README.es.md">Español</a> |
<a href="docs/README.ja.md">日本語</a> |
<a href="docs/README.zh-Hans.md">简体中文</a> |
Expand Down
Loading
Loading