diff --git a/PureMac/Views/Components/EmptyStateView.swift b/PureMac/Views/Components/EmptyStateView.swift index a21241a..bbfad6d 100644 --- a/PureMac/Views/Components/EmptyStateView.swift +++ b/PureMac/Views/Components/EmptyStateView.swift @@ -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 @@ -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) } diff --git a/PureMac/Views/MainWindow.swift b/PureMac/Views/MainWindow.swift index d01b42c..071eb52 100644 --- a/PureMac/Views/MainWindow.swift +++ b/PureMac/Views/MainWindow.swift @@ -25,14 +25,14 @@ 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 } @@ -40,9 +40,8 @@ struct MainWindow: View { 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) @@ -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 } diff --git a/PureMac/ar.lproj/Localizable.strings b/PureMac/ar.lproj/Localizable.strings new file mode 100644 index 0000000..f25edfa --- /dev/null +++ b/PureMac/ar.lproj/Localizable.strings @@ -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`)"; diff --git a/PureMac/en.lproj/Localizable.strings b/PureMac/en.lproj/Localizable.strings index 37ee79e..d54fd1e 100644 --- a/PureMac/en.lproj/Localizable.strings +++ b/PureMac/en.lproj/Localizable.strings @@ -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"; diff --git a/PureMac/es.lproj/Localizable.strings b/PureMac/es.lproj/Localizable.strings index 03b7a56..b188f86 100644 --- a/PureMac/es.lproj/Localizable.strings +++ b/PureMac/es.lproj/Localizable.strings @@ -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"; diff --git a/PureMac/ja.lproj/Localizable.strings b/PureMac/ja.lproj/Localizable.strings index 7bf567c..23023af 100644 --- a/PureMac/ja.lproj/Localizable.strings +++ b/PureMac/ja.lproj/Localizable.strings @@ -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" = "スマートスキャン"; diff --git a/PureMac/zh-Hans.lproj/Localizable.strings b/PureMac/zh-Hans.lproj/Localizable.strings index c9c030b..ad39d9e 100644 --- a/PureMac/zh-Hans.lproj/Localizable.strings +++ b/PureMac/zh-Hans.lproj/Localizable.strings @@ -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" = "智能扫描"; diff --git a/PureMac/zh-Hant.lproj/Localizable.strings b/PureMac/zh-Hant.lproj/Localizable.strings index d83665d..668be15 100644 --- a/PureMac/zh-Hant.lproj/Localizable.strings +++ b/PureMac/zh-Hant.lproj/Localizable.strings @@ -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" = "智慧掃描"; diff --git a/README.md b/README.md index eb9089e..5f996a4 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@
English | + العربية | Español | 日本語 | 简体中文 | diff --git a/docs/README.ar.md b/docs/README.ar.md new file mode 100644 index 0000000..e9dff95 --- /dev/null +++ b/docs/README.ar.md @@ -0,0 +1,166 @@ +
+
+
+ English | + العربية | + Español | + 日本語 | + 简体中文 | + 繁體中文 +
+ +
+ أداة مجانية ومفتوحة المصدر لإدارة التطبيقات وتنظيف النظام على macOS.
+ إزالة التطبيقات بالكامل. العثور على الملفات اليتيمة. تنظيف ملفات النظام غير المرغوبة.
+ بلا اشتراكات. بلا تتبع. بلا جمع بيانات.
+
+ التثبيت - + الميزات - + لقطات الشاشة - + المساهمة +
+ +--- + +English | + العربية | Español | 日本語 | 简体中文 | diff --git a/docs/README.ja.md b/docs/README.ja.md index 954a5c1..e8f8003 100644 --- a/docs/README.ja.md +++ b/docs/README.ja.md @@ -4,6 +4,7 @@
English | + العربية | Español | 日本語 | 简体中文 | diff --git a/docs/README.zh-Hans.md b/docs/README.zh-Hans.md index 109fde1..eb04407 100644 --- a/docs/README.zh-Hans.md +++ b/docs/README.zh-Hans.md @@ -4,6 +4,7 @@
English | + العربية | Español | 日本語 | 简体中文 | diff --git a/docs/README.zh-Hant.md b/docs/README.zh-Hant.md index b3f0962..2361210 100644 --- a/docs/README.zh-Hant.md +++ b/docs/README.zh-Hant.md @@ -4,6 +4,7 @@