From 6f9aaaf5fa578e2b2a725e42d89f718f7dc38dfc Mon Sep 17 00:00:00 2001 From: Stephen B <158498287+StephenDev0@users.noreply.github.com> Date: Wed, 9 Jul 2025 20:09:03 -0400 Subject: [PATCH] Add basic localization support (#217) --- StikJIT/StikJITApp.swift | 4 +-- StikJIT/Utilities/Localization.swift | 7 +++++ StikJIT/Views/HomeView.swift | 10 ++++---- StikJIT/Views/InstalledAppsListView.swift | 8 +++--- StikJIT/Views/TextFieldAlert.swift | 4 +-- StikJIT/en.lproj/Localizable.strings | 31 +++++++++++++++++++++++ StikJIT/es.lproj/Localizable.strings | 31 +++++++++++++++++++++++ 7 files changed, 82 insertions(+), 13 deletions(-) create mode 100644 StikJIT/Utilities/Localization.swift create mode 100644 StikJIT/en.lproj/Localizable.strings create mode 100644 StikJIT/es.lproj/Localizable.strings diff --git a/StikJIT/StikJITApp.swift b/StikJIT/StikJITApp.swift index e41a0ba..2034dc8 100644 --- a/StikJIT/StikJITApp.swift +++ b/StikJIT/StikJITApp.swift @@ -906,8 +906,8 @@ struct LoadingView: View { animate = true let os = ProcessInfo.processInfo.operatingSystemVersion if os.majorVersion < 17 || (os.majorVersion == 17 && os.minorVersion < 4) { - alertTitle = "Unsupported OS Version" - alertMessage = "StikJIT only supports 17.4 and above. Your device is running iOS/iPadOS \(os.majorVersion).\(os.minorVersion).\(os.patchVersion)" + alertTitle = "Unsupported OS Version".localized + alertMessage = String(format: "StikJIT only supports 17.4 and above. Your device is running iOS/iPadOS %@".localized, "\(os.majorVersion).\(os.minorVersion).\(os.patchVersion)") showAlert = true } } diff --git a/StikJIT/Utilities/Localization.swift b/StikJIT/Utilities/Localization.swift new file mode 100644 index 0000000..76482fa --- /dev/null +++ b/StikJIT/Utilities/Localization.swift @@ -0,0 +1,7 @@ +import Foundation + +extension String { + var localized: String { + NSLocalizedString(self, comment: "") + } +} diff --git a/StikJIT/Views/HomeView.swift b/StikJIT/Views/HomeView.swift index 7aeceec..29af174 100644 --- a/StikJIT/Views/HomeView.swift +++ b/StikJIT/Views/HomeView.swift @@ -78,7 +78,7 @@ struct HomeView: View { if pairingFileExists { // Got a pairing file, show apps if !isMounted() { - showAlert(title: "Device Not Mounted", message: "The Developer Disk Image has not been mounted yet. Check in settings for more information.", showOk: true) { cool in + showAlert(title: "Device Not Mounted".localized, message: "The Developer Disk Image has not been mounted yet. Check in settings for more information.".localized, showOk: true) { cool in // No Need } return @@ -327,7 +327,7 @@ struct HomeView: View { } .textFieldAlert( isPresented: $pidTextAlertShow, - title: "Please enter the PID of the process you want to connect to", + title: "Please enter the PID of the process you want to connect to".localized, text: $pidStr, placeholder: "", action: { newText in @@ -337,7 +337,7 @@ struct HomeView: View { } guard let pid = Int(pidStr) else { - showAlert(title: "", message: "Invalid PID", showOk: true, completion: { _ in }) + showAlert(title: "", message: "Invalid PID".localized, showOk: true, completion: { _ in }) return } startJITInBackground(with: pid) @@ -417,7 +417,7 @@ struct HomeView: View { do { try jsModel?.runScript(path: selectedScriptURL) } catch { - showAlert(title: "Error Occurred While Executing the Default Script.", message: error.localizedDescription, showOk: true) + showAlert(title: "Error Occurred While Executing the Default Script.".localized, message: error.localizedDescription, showOk: true) } } } @@ -463,7 +463,7 @@ struct HomeView: View { DispatchQueue.main.async { LogManager.shared.addInfoLog("JIT process completed for \(pid)") - showAlert(title: "Success", message: "JIT has been enabled for pid \(pid).", showOk: true, messageType: .success) + showAlert(title: "Success".localized, message: String(format: "JIT has been enabled for pid %d.".localized, pid), showOk: true, messageType: .success) isProcessing = false } } diff --git a/StikJIT/Views/InstalledAppsListView.swift b/StikJIT/Views/InstalledAppsListView.swift index fd06de6..4d1c855 100644 --- a/StikJIT/Views/InstalledAppsListView.swift +++ b/StikJIT/Views/InstalledAppsListView.swift @@ -41,7 +41,7 @@ struct InstalledAppsListView: View { appsList } } - .navigationTitle("Installed Apps") + .navigationTitle("Installed Apps".localized) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Done") { dismiss() } @@ -70,7 +70,7 @@ Please check if the app you want to connect to is signed with a **development** private var appsList: some View { List { if !favoriteApps.isEmpty { - Section(header: Text("Favorites (\(favoriteApps.count)/4)")) { + Section(header: Text(String(format: "Favorites (%d/4)".localized, favoriteApps.count))) { ForEach(favoriteApps, id: \.self) { bundleID in AppButton( bundleID: bundleID, @@ -86,7 +86,7 @@ Please check if the app you want to connect to is signed with a **development** } if !filteredRecents.isEmpty { - Section(header: Text("Recents")) { + Section(header: Text("Recents".localized)) { ForEach(filteredRecents, id: \.self) { bundleID in AppButton( bundleID: bundleID, @@ -112,7 +112,7 @@ Please check if the app you want to connect to is signed with a **development** } } - Section(header: Text((favoriteApps.isEmpty && filteredRecents.isEmpty) ? "" : "All Applications")) { + Section(header: Text((favoriteApps.isEmpty && filteredRecents.isEmpty) ? "" : "All Applications".localized)) { ForEach(viewModel.apps.sorted(by: { $0.key < $1.key }), id: \.key) { bundleID, appName in AppButton( bundleID: bundleID, diff --git a/StikJIT/Views/TextFieldAlert.swift b/StikJIT/Views/TextFieldAlert.swift index c555e38..d9ddbaa 100644 --- a/StikJIT/Views/TextFieldAlert.swift +++ b/StikJIT/Views/TextFieldAlert.swift @@ -43,11 +43,11 @@ public struct TextFieldAlertModifier: ViewModifier { $0.text = self.text.wrappedValue $0.clearButtonMode = .always } - controller.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in + controller.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel) { _ in self.actionCancel(nil) shutdown() }) - controller.addAction(UIAlertAction(title: "OK", style: .default) { _ in + controller.addAction(UIAlertAction(title: "OK".localized, style: .default) { _ in self.action(controller.textFields?.first?.text) shutdown() }) diff --git a/StikJIT/en.lproj/Localizable.strings b/StikJIT/en.lproj/Localizable.strings new file mode 100644 index 0000000..f0470aa --- /dev/null +++ b/StikJIT/en.lproj/Localizable.strings @@ -0,0 +1,31 @@ +"Welcome to StikDebug %@!" = "Welcome to StikDebug %@!"; +"Click connect to get started" = "Click connect to get started"; +"Pick pairing file to get started" = "Pick pairing file to get started"; +"Device Not Mounted" = "Device Not Mounted"; +"The Developer Disk Image has not been mounted yet. Check in settings for more information." = "The Developer Disk Image has not been mounted yet. Check in settings for more information."; +"Connect by App" = "Connect by App"; +"Select Pairing File" = "Select Pairing File"; +"Connect by PID" = "Connect by PID"; +"Open Console" = "Open Console"; +"Processing pairing file..." = "Processing pairing file..."; +"\u2713 Pairing file successfully imported" = "\u2713 Pairing file successfully imported"; +"Please enter the PID of the process you want to connect to" = "Please enter the PID of the process you want to connect to"; +"Invalid PID" = "Invalid PID"; +"Success" = "Success"; +"JIT has been enabled for pid %d." = "JIT has been enabled for pid %d."; +"Installed Apps" = "Installed Apps"; +"No Debuggable App Found" = "No Debuggable App Found"; +"StikDebug can only connect to apps with the \"get-task-allow\" entitlement. Please check if the app you want to connect to is signed with a development certificate." = "StikDebug can only connect to apps with the \"get-task-allow\" entitlement. Please check if the app you want to connect to is signed with a development certificate."; +"Favorites (%d/4)" = "Favorites (%d/4)"; +"Recents" = "Recents"; +"All Applications" = "All Applications"; +"Remove Favorite" = "Remove Favorite"; +"Add to Favorites" = "Add to Favorites"; +"Copy Bundle ID" = "Copy Bundle ID"; +"Delete" = "Delete"; +"Loading..." = "Loading..."; +"Error Occurred While Executing the Default Script." = "Error Occurred While Executing the Default Script."; +"Unsupported OS Version" = "Unsupported OS Version"; +"StikJIT only supports 17.4 and above. Your device is running iOS/iPadOS %@" = "StikJIT only supports 17.4 and above. Your device is running iOS/iPadOS %@"; +"Cancel" = "Cancel"; +"OK" = "OK"; diff --git a/StikJIT/es.lproj/Localizable.strings b/StikJIT/es.lproj/Localizable.strings new file mode 100644 index 0000000..b4f9889 --- /dev/null +++ b/StikJIT/es.lproj/Localizable.strings @@ -0,0 +1,31 @@ +"Welcome to StikDebug %@!" = "\u00a1Bienvenido a StikDebug %@!"; +"Click connect to get started" = "Haz clic en conectar para comenzar"; +"Pick pairing file to get started" = "Selecciona el archivo de emparejamiento para comenzar"; +"Device Not Mounted" = "Dispositivo no montado"; +"The Developer Disk Image has not been mounted yet. Check in settings for more information." = "La imagen de desarrollo no se ha montado todav\u00eda. Consulta la configuraci\u00f3n para obtener m\u00e1s informaci\u00f3n."; +"Connect by App" = "Conectar por app"; +"Select Pairing File" = "Seleccionar archivo de emparejamiento"; +"Connect by PID" = "Conectar por PID"; +"Open Console" = "Abrir consola"; +"Processing pairing file..." = "Procesando archivo de emparejamiento..."; +"\u2713 Pairing file successfully imported" = "\u2713 Archivo de emparejamiento importado correctamente"; +"Please enter the PID of the process you want to connect to" = "Introduce el PID del proceso al que deseas conectarte"; +"Invalid PID" = "PID no v\u00e1lido"; +"Success" = "\u00c9xito"; +"JIT has been enabled for pid %d." = "JIT habilitado para el pid %d."; +"Installed Apps" = "Aplicaciones instaladas"; +"No Debuggable App Found" = "No se encontr\u00f3 ninguna aplicaci\u00f3n depurable"; +"StikDebug can only connect to apps with the \"get-task-allow\" entitlement. Please check if the app you want to connect to is signed with a development certificate." = "StikDebug solo puede conectarse a aplicaciones con el derecho \"get-task-allow\". Verifica que la aplicaci\u00f3n a la que deseas conectarte est\u00e9 firmada con un certificado de desarrollo."; +"Favorites (%d/4)" = "Favoritos (%d/4)"; +"Recents" = "Recientes"; +"All Applications" = "Todas las aplicaciones"; +"Remove Favorite" = "Eliminar favorito"; +"Add to Favorites" = "A\u00f1adir a favoritos"; +"Copy Bundle ID" = "Copiar Bundle ID"; +"Delete" = "Eliminar"; +"Loading..." = "Cargando..."; +"Error Occurred While Executing the Default Script." = "Ocurri\u00f3 un error al ejecutar el script predeterminado."; +"Unsupported OS Version" = "Versi\u00f3n de iOS no compatible"; +"StikJIT only supports 17.4 and above. Your device is running iOS/iPadOS %@" = "StikJIT solo es compatible con la versi\u00f3n 17.4 o superior. Tu dispositivo ejecuta iOS/iPadOS %@"; +"Cancel" = "Cancelar"; +"OK" = "Aceptar";