From 2ddd914b4cd7d08899efcc0d7bea916f941f287d Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 19:36:29 +0800 Subject: [PATCH 01/10] Added Chinese Localization #1 --- StikJIT/Assets.xcassets/Localizable.xcstrings | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 StikJIT/Assets.xcassets/Localizable.xcstrings diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings new file mode 100644 index 00000000..900453da --- /dev/null +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -0,0 +1,7 @@ +{ + "sourceLanguage" : "en", + "strings" : { + + }, + "version" : "1.1" +} \ No newline at end of file From 9a35bf3d185a950c9c34cfe966ea4fc8fa7c54ee Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 19:37:03 +0800 Subject: [PATCH 02/10] #2 --- .gitignore | 5 + StikDebug.xcodeproj/project.pbxproj | 13 +- .../xcschemes/DebugWidgetExtension.xcscheme | 3 +- .../xcshareddata/xcschemes/StikDebug.xcscheme | 2 +- StikJIT/Assets.xcassets/Localizable.xcstrings | 1378 ++++++++++++++++- 5 files changed, 1396 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 17d36288..cad6d0e8 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,8 @@ iOSInjectionProject/ .DS_Store .vscode/settings.json .vscode + + +package.json +package-lock.json +node_modules/ \ No newline at end of file diff --git a/StikDebug.xcodeproj/project.pbxproj b/StikDebug.xcodeproj/project.pbxproj index 33127f18..6c880407 100644 --- a/StikDebug.xcodeproj/project.pbxproj +++ b/StikDebug.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 43953ACC2F9246C6006CB77E /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 43953ACB2F9246C6006CB77E /* Localizable.xcstrings */; }; 68D569BE2E1B415700A5BA36 /* CodeEditorView in Frameworks */ = {isa = PBXBuildFile; productRef = 68D569BD2E1B415700A5BA36 /* CodeEditorView */; }; 68D569C02E1B415700A5BA36 /* LanguageSupport in Frameworks */ = {isa = PBXBuildFile; productRef = 68D569BF2E1B415700A5BA36 /* LanguageSupport */; }; /* End PBXBuildFile section */ @@ -42,6 +43,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 43953ACB2F9246C6006CB77E /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; name = Localizable.xcstrings; path = StikJIT/Assets.xcassets/Localizable.xcstrings; sourceTree = ""; }; DC139F6D2DE97EA400F63846 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; DC139F6F2DE97EA400F63846 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; DC6F1D372D94EADD0071B2B6 /* StikDebug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StikDebug.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -110,6 +112,7 @@ DC6F1D2E2D94EADD0071B2B6 = { isa = PBXGroup; children = ( + 43953ACB2F9246C6006CB77E /* Localizable.xcstrings */, DC6F1D392D94EADD0071B2B6 /* StikJIT */, DC6F1D4B2D94EADF0071B2B6 /* StikJITTests */, DC6F1D552D94EADF0071B2B6 /* StikJITUITests */, @@ -219,7 +222,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1620; - LastUpgradeCheck = 1620; + LastUpgradeCheck = 2620; TargetAttributes = { DC6F1D362D94EADD0071B2B6 = { CreatedOnToolsVersion = 16.2; @@ -243,6 +246,7 @@ Base, es, it, + "zh-Hans", ); mainGroup = DC6F1D2E2D94EADD0071B2B6; minimizedProjectReferenceProxies = 1; @@ -266,6 +270,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 43953ACC2F9246C6006CB77E /* Localizable.xcstrings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -328,6 +333,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -379,7 +385,9 @@ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; @@ -389,6 +397,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -433,7 +442,9 @@ LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; }; name = Release; }; diff --git a/StikDebug.xcodeproj/xcshareddata/xcschemes/DebugWidgetExtension.xcscheme b/StikDebug.xcodeproj/xcshareddata/xcschemes/DebugWidgetExtension.xcscheme index c2efed42..1ce5d7a8 100644 --- a/StikDebug.xcodeproj/xcshareddata/xcschemes/DebugWidgetExtension.xcscheme +++ b/StikDebug.xcodeproj/xcshareddata/xcschemes/DebugWidgetExtension.xcscheme @@ -1,6 +1,6 @@ diff --git a/StikDebug.xcodeproj/xcshareddata/xcschemes/StikDebug.xcscheme b/StikDebug.xcodeproj/xcshareddata/xcschemes/StikDebug.xcscheme index cf047ee7..988f1fef 100644 --- a/StikDebug.xcodeproj/xcshareddata/xcschemes/StikDebug.xcscheme +++ b/StikDebug.xcodeproj/xcshareddata/xcschemes/StikDebug.xcscheme @@ -1,6 +1,6 @@ Date: Fri, 17 Apr 2026 20:44:01 +0800 Subject: [PATCH 03/10] zh-Hans Localizations #3 --- StikJIT/Assets.xcassets/Localizable.xcstrings | 104 +++++++++++++++++- StikJIT/Views/MainTabView.swift | 16 +-- StikJIT/Views/ToolsView.swift | 14 +-- 3 files changed, 118 insertions(+), 16 deletions(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index 3fbc0ade..80de43ac 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -1377,7 +1377,109 @@ } } } - } + }, + "Search apps or bundle ID": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search apps or bundle ID" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索应用或应用ID" + } + } + } + }, + "Reset Script": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset Script" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重置脚本" + } + } + } + }, + "Tools": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tools" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "工具" + } + } + } + }, + "Target Device IP": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Target Device IP" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "目标设备IP" + } + } + } + }, + "Star on Github": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Star on Github" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "给颗星星吧awa~" + } + } + } + }, + "Silent Audio": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Silent Audio" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无声音频" + } + } + } + }, }, "version" : "1.1" } \ No newline at end of file diff --git a/StikJIT/Views/MainTabView.swift b/StikJIT/Views/MainTabView.swift index 84d017c1..42e44708 100644 --- a/StikJIT/Views/MainTabView.swift +++ b/StikJIT/Views/MainTabView.swift @@ -27,13 +27,13 @@ struct MainTabView: View { private var configurableTabs: [TabDescriptor] { let tabs: [TabDescriptor] = [ - TabDescriptor(id: "home", title: "Apps", systemImage: "square.grid.2x2") { AnyView(HomeView()) }, - TabDescriptor(id: "scripts", title: "Scripts", systemImage: "scroll") { AnyView(ScriptListView()) }, - TabDescriptor(id: "tools", title: "Tools", systemImage: "wrench.and.screwdriver") { AnyView(ToolsView()) }, - TabDescriptor(id: "deviceinfo", title: "Device Info", systemImage: "iphone.and.arrow.forward") { AnyView(DeviceInfoView()) }, - TabDescriptor(id: "profiles", title: "App Expiry", systemImage: "calendar.badge.clock") { AnyView(ProfileView()) }, - TabDescriptor(id: "processes", title: "Processes", systemImage: "rectangle.stack.person.crop") { AnyView(ProcessInspectorView()) }, - TabDescriptor(id: "location", title: "Location", systemImage: "location") { AnyView(LocationSimulationView()) } + TabDescriptor(id: "home", title: NSLocalizedString("Apps", comment: ""), systemImage: "square.grid.2x2") { AnyView(HomeView()) }, + TabDescriptor(id: "scripts", title: NSLocalizedString("Scripts", comment: ""), systemImage: "scroll") { AnyView(ScriptListView()) }, + TabDescriptor(id: "tools", title: NSLocalizedString("Tools", comment: ""), systemImage: "wrench.and.screwdriver") { AnyView(ToolsView()) }, + TabDescriptor(id: "deviceinfo", title: NSLocalizedString("Device Info", comment: ""), systemImage: "iphone.and.arrow.forward") { AnyView(DeviceInfoView()) }, + TabDescriptor(id: "profiles", title: NSLocalizedString("App Expiry", comment: ""), systemImage: "calendar.badge.clock") { AnyView(ProfileView()) }, + TabDescriptor(id: "processes", title: NSLocalizedString("Processes", comment: ""), systemImage: "rectangle.stack.person.crop") { AnyView(ProcessInspectorView()) }, + TabDescriptor(id: "location", title: NSLocalizedString("Location", comment: ""), systemImage: "location") { AnyView(LocationSimulationView()) } ] return tabs } @@ -42,7 +42,7 @@ struct MainTabView: View { configurableTabs } - private let settingsTab = TabDescriptor(id: "settings", title: "Settings", systemImage: "gearshape.fill") { + private let settingsTab = TabDescriptor(id: "settings", title: NSLocalizedString("Settings", comment: ""), systemImage: "gearshape.fill") { AnyView(SettingsView()) } diff --git a/StikJIT/Views/ToolsView.swift b/StikJIT/Views/ToolsView.swift index bf274bb9..8b2f548b 100644 --- a/StikJIT/Views/ToolsView.swift +++ b/StikJIT/Views/ToolsView.swift @@ -18,12 +18,12 @@ struct ToolsView: View { private var tools: [ToolItem] { [ - ToolItem(id: "scripts", title: "Scripts", detail: "Manage and run JS scripts", systemImage: "scroll", destination: AnyView(ScriptListView())), - ToolItem(id: "console", title: "Console", detail: "Live device logs", systemImage: "terminal", destination: AnyView(ConsoleLogsView())), - ToolItem(id: "deviceinfo", title: "Device Info", detail: "View detailed device metadata", systemImage: "iphone.and.arrow.forward", destination: AnyView(DeviceInfoView())), - ToolItem(id: "profiles", title: "App Expiry", detail: "Check app expiration dates", systemImage: "calendar.badge.clock", destination: AnyView(ProfileView())), - ToolItem(id: "processes", title: "Processes", detail: "Inspect running apps", systemImage: "rectangle.stack.person.crop", destination: AnyView(ProcessInspectorView())), - ToolItem(id: "location", title: "Location Simulation", detail: "Simulate GPS location", systemImage: "location", destination: AnyView(LocationSimulationView())) + ToolItem(id: "scripts", title: NSLocalizedString("Scripts", comment: ""), detail: NSLocalizedString("Manage and run JS scripts", comment: ""), systemImage: "scroll", destination: AnyView(ScriptListView())), + ToolItem(id: "console", title: NSLocalizedString("Console", comment: ""), detail: NSLocalizedString("Live device logs", comment: ""), systemImage: "terminal", destination: AnyView(ConsoleLogsView())), + ToolItem(id: "deviceinfo", title: NSLocalizedString("Device Info", comment: ""), detail: NSLocalizedString("View detailed device metadata", comment: ""), systemImage: "iphone.and.arrow.forward", destination: AnyView(DeviceInfoView())), + ToolItem(id: "profiles", title: NSLocalizedString("App Expiry", comment: ""), detail: NSLocalizedString("Check app expiration dates", comment: ""), systemImage: "calendar.badge.clock", destination: AnyView(ProfileView())), + ToolItem(id: "processes", title: NSLocalizedString("Processes", comment: ""), detail: NSLocalizedString("Inspect running apps", comment: ""), systemImage: "rectangle.stack.person.crop", destination: AnyView(ProcessInspectorView())), + ToolItem(id: "location", title: NSLocalizedString("Location Simulation", comment: ""), detail: NSLocalizedString("Simulate GPS location", comment: ""), systemImage: "location", destination: AnyView(LocationSimulationView())) ] } @@ -45,7 +45,7 @@ struct ToolsView: View { } } } - .navigationTitle("Tools") + .navigationTitle(NSLocalizedString("Tools", comment: "")) } } } From 78fa4ce2230127733145c8567aa6130d39c52b04 Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 21:19:07 +0800 Subject: [PATCH 04/10] zh-Hans Localization #4 --- StikJIT/Assets.xcassets/Localizable.xcstrings | 442 ++++++++++++++++++ StikJIT/Views/SettingsView.swift | 82 ++-- 2 files changed, 483 insertions(+), 41 deletions(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index 80de43ac..7f9d50d9 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -1480,6 +1480,448 @@ } } }, + "Access additional tools": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Access additional tools" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "访问其他工具" + } + } + } + }, + "Check app expiration date, install/remove profiles": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Check app expiration date, install/remove profiles" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "检查应用过期日期,并安装/删除配置" + } + } + } + }, + "Check app expiration dates": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Check app expiration dates" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "检查应用过期日期" + } + } + } + }, + "Dashboard overview": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dashboard overview" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "仪表板概览" + } + } + } + }, + "DDI files refreshed successfully.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "DDI files refreshed successfully." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "开发者镜像刷新成功。" + } + } + } + }, + "Existing DDI files will be removed before downloading fresh copies.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Existing DDI files will be removed before downloading fresh copies." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "现有开发者镜像将在下载新副本之前被删除。" + } + } + } + }, + "Failed to redownload DDI files: %@": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Failed to redownload DDI files: %@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新下载开发者镜像失败:%@" + } + } + } + }, + "Imported successfully": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Imported successfully" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "导入成功" + } + } + } + }, + "Inspect running apps": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inspect running apps" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "检查运行中的应用" + } + } + } + }, + "Location Sim": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location Sim" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "虚拟定位" + } + } + } + }, + "Manage automation scripts": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manage automation scripts" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "管理自动化脚本" + } + } + } + }, + "Non TXM": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Non TXM" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "非TXM" + } + } + } + }, + "Plays inaudible audio so iOS keeps the app running.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Plays inaudible audio so iOS keeps the app running." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "播放无声音频以保持应用运行。" + } + } + } + }, + "Preparing download…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preparing download…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "准备下载…" + } + } + } + }, + "Processing pairing file…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Processing pairing file…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "处理配对文件…" + } + } + } + }, + "Redownload DDI Files?": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Redownload DDI Files?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新下载开发者镜像?" + } + } + } + }, + "Settings is fixed as the 4th tab.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings is fixed as the 4th tab." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "设置已经固定为第4个标签。" + } + } + } + }, + "Sideload only": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sideload only" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "仅侧载" + } + } + } + }, + "Simulate GPS location": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Simulate GPS location" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模拟GPS位置" + } + } + } + }, + "Tab Bar": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tab Bar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "标签栏" + } + } + } + }, + "Treats device as TXM-capable to bypass hardware checks.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Treats device as TXM-capable to bypass hardware checks." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "将设备视为支持TXM以绕过硬件检查。" + } + } + } + }, + "TXM": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TXM" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "TXM" + } + } + } + }, + "TXM (Override)": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TXM (Override)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "TXM(覆盖)" + } + } + } + }, + "Uses low-accuracy location to stay alive when an activity needs it.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uses low-accuracy location to stay alive when an activity needs it." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在需要时使用低精度定位保活。" + } + } + } + }, + "Version %@ • iOS %@ • %@": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Version %@ • iOS %@ • %@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "版本 %@ • iOS %@ • %@" + } + } + } + }, + "View detailed device metadata": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "View detailed device metadata" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看详细设备元数据" + } + } + } + } }, "version" : "1.1" } \ No newline at end of file diff --git a/StikJIT/Views/SettingsView.swift b/StikJIT/Views/SettingsView.swift index 83f0cb37..261c772b 100644 --- a/StikJIT/Views/SettingsView.swift +++ b/StikJIT/Views/SettingsView.swift @@ -46,14 +46,14 @@ struct SettingsView: View { private var tabOptions: [TabOption] { var options: [TabOption] = [ - TabOption(id: "home", title: "Home", detail: "Dashboard overview", icon: "house", isBeta: false), - TabOption(id: "scripts", title: "Scripts", detail: "Manage automation scripts", icon: "scroll", isBeta: false), - TabOption(id: "tools", title: "Tools", detail: "Access additional tools", icon: "wrench.and.screwdriver", isBeta: false) + TabOption(id: "home", title: NSLocalizedString("Home", comment: ""), detail: NSLocalizedString("Dashboard overview", comment: ""), icon: "house", isBeta: false), + TabOption(id: "scripts", title: NSLocalizedString("Scripts", comment: ""), detail: NSLocalizedString("Manage automation scripts", comment: ""), icon: "scroll", isBeta: false), + TabOption(id: "tools", title: NSLocalizedString("Tools", comment: ""), detail: NSLocalizedString("Access additional tools", comment: ""), icon: "wrench.and.screwdriver", isBeta: false) ] - options.append(TabOption(id: "deviceinfo", title: "Device Info", detail: "View detailed device metadata", icon: "iphone.and.arrow.forward", isBeta: false)) - options.append(TabOption(id: "profiles", title: "App Expiry", detail: "Check app expiration date, install/remove profiles", icon: "calendar.badge.clock", isBeta: false)) - options.append(TabOption(id: "processes", title: "Processes", detail: "Inspect running apps", icon: "rectangle.stack.person.crop", isBeta: false)) - options.append(TabOption(id: "location", title: "Location Sim", detail: "Sideload only", icon: "location", isBeta: false)) + options.append(TabOption(id: "deviceinfo", title: NSLocalizedString("Device Info", comment: ""), detail: NSLocalizedString("View detailed device metadata", comment: ""), icon: "iphone.and.arrow.forward", isBeta: false)) + options.append(TabOption(id: "profiles", title: NSLocalizedString("App Expiry", comment: ""), detail: NSLocalizedString("Check app expiration date, install/remove profiles", comment: ""), icon: "calendar.badge.clock", isBeta: false)) + options.append(TabOption(id: "processes", title: NSLocalizedString("Processes", comment: ""), detail: NSLocalizedString("Inspect running apps", comment: ""), icon: "rectangle.stack.person.crop", isBeta: false)) + options.append(TabOption(id: "location", title: NSLocalizedString("Location Sim", comment: ""), detail: NSLocalizedString("Sideload only", comment: ""), icon: "location", isBeta: false)) return options } @@ -80,17 +80,17 @@ struct SettingsView: View { // 2) GitHub Section { Link(destination: URL(string: "https://github.com/StephenDev0/StikDebug/stargazers")!) { - Label("Star on GitHub", systemImage: "star") + Label(NSLocalizedString("Star on GitHub", comment: ""), systemImage: "star") } } // 3) Pairing File - Section("Pairing File") { + Section(NSLocalizedString("Pairing File", comment: "")) { Button { isShowingPairingFilePicker = true } label: { - Label("Import Pairing File", systemImage: "doc.badge.plus") + Label(NSLocalizedString("Import Pairing File", comment: ""), systemImage: "doc.badge.plus") } if showPairingFileMessage && !isImportingFile { - Label("Imported successfully", systemImage: "checkmark.circle.fill") + Label(NSLocalizedString("Imported successfully", comment: ""), systemImage: "checkmark.circle.fill") .foregroundStyle(.green) } } @@ -99,8 +99,8 @@ struct SettingsView: View { Section { Toggle(isOn: $keepAliveAudio) { VStack(alignment: .leading, spacing: 2) { - Text("Silent Audio") - Text("Plays inaudible audio so iOS keeps the app running.") + Text(NSLocalizedString("Silent Audio", comment: "")) + Text(NSLocalizedString("Plays inaudible audio so iOS keeps the app running.", comment: "")) .font(.caption).foregroundStyle(.secondary) } } @@ -111,8 +111,8 @@ struct SettingsView: View { Toggle(isOn: $keepAliveLocation) { VStack(alignment: .leading, spacing: 2) { - Text("Background Location") - Text("Uses low-accuracy location to stay alive when an activity needs it.") + Text(NSLocalizedString("Background Location", comment: "")) + Text(NSLocalizedString("Uses low-accuracy location to stay alive when an activity needs it.", comment: "")) .font(.caption).foregroundStyle(.secondary) } } @@ -121,24 +121,24 @@ struct SettingsView: View { } } header: { - Text("Background Keep-Alive") + Text(NSLocalizedString("Background Keep-Alive", comment: "")) } // 6) Behavior - Section("Behavior") { + Section(NSLocalizedString("Behavior", comment: "")) { Toggle(isOn: $overrideTXMDetection) { VStack(alignment: .leading, spacing: 2) { - Text("Always Run Scripts") - Text("Treats device as TXM-capable to bypass hardware checks.") + Text(NSLocalizedString("Always Run Scripts", comment: "")) + Text(NSLocalizedString("Treats device as TXM-capable to bypass hardware checks.", comment: "")) .font(.caption).foregroundStyle(.secondary) } } } // 7) Advanced - Section("Advanced") { + Section(NSLocalizedString("Advanced", comment: "")) { HStack { - Text("Target Device IP") + Text(NSLocalizedString("Target Device IP", comment: "")) Spacer() TextField("10.7.0.1", text: $customTargetIP) .multilineTextAlignment(.trailing) @@ -146,10 +146,10 @@ struct SettingsView: View { .submitLabel(.done) } Button { openAppFolder() } label: { - Label("App Folder", systemImage: "folder") + Label(NSLocalizedString("App Folder", comment: ""), systemImage: "folder") }.foregroundStyle(.primary) Button { showDDIConfirmation = true } label: { - Label("Redownload DDI", systemImage: "arrow.down.circle") + Label(NSLocalizedString("Redownload DDI", comment: ""), systemImage: "arrow.down.circle") }.foregroundStyle(.primary).disabled(isRedownloadingDDI) if isRedownloadingDDI { VStack(alignment: .leading, spacing: 4) { @@ -162,15 +162,15 @@ struct SettingsView: View { } // 7) Help - Section("Help") { + Section(NSLocalizedString("Help", comment: "")) { Link(destination: URL(string: "https://github.com/StephenDev0/StikDebug-Guide/blob/main/pairing_file.md")!) { - Label("Pairing File Guide", systemImage: "questionmark.circle") + Label(NSLocalizedString("Pairing File Guide", comment: ""), systemImage: "questionmark.circle") } Link(destination: URL(string: "https://apps.apple.com/us/app/localdevvpn/id6755608044")!) { - Label("Download LocalDevVPN", systemImage: "arrow.down.circle") + Label(NSLocalizedString("Download LocalDevVPN", comment: ""), systemImage: "arrow.down.circle") } Link(destination: URL(string: "https://discord.gg/qahjXNTDwS")!) { - Label("Discord Support", systemImage: "bubble.left.and.bubble.right") + Label(NSLocalizedString("Discord Support", comment: ""), systemImage: "bubble.left.and.bubble.right") } } @@ -182,7 +182,7 @@ struct SettingsView: View { .listRowBackground(Color.clear) } } - .navigationTitle("Settings") + .navigationTitle(NSLocalizedString("Settings", comment: "")) } .fileImporter( isPresented: $isShowingPairingFilePicker, @@ -225,13 +225,13 @@ struct SettingsView: View { break } } - .confirmationDialog("Redownload DDI Files?", isPresented: $showDDIConfirmation, titleVisibility: .visible) { - Button("Redownload", role: .destructive) { + .confirmationDialog(NSLocalizedString("Redownload DDI Files?", comment: ""), isPresented: $showDDIConfirmation, titleVisibility: .visible) { + Button(NSLocalizedString("Redownload", comment: ""), role: .destructive) { redownloadDDIPressed() } - Button("Cancel", role: .cancel) { } + Button(NSLocalizedString("Cancel", comment: ""), role: .cancel) { } } message: { - Text("Existing DDI files will be removed before downloading fresh copies.") + Text(NSLocalizedString("Existing DDI files will be removed before downloading fresh copies.", comment: "")) } .overlay { if isImportingFile { importBusyOverlay } } } @@ -240,7 +240,7 @@ struct SettingsView: View { private var importBusyOverlay: some View { Color.black.opacity(0.35).ignoresSafeArea() VStack(spacing: 12) { - ProgressView("Processing pairing file…") + ProgressView(NSLocalizedString("Processing pairing file…", comment: "")) VStack(spacing: 8) { GeometryReader { geometry in ZStack(alignment: .leading) { @@ -276,11 +276,11 @@ struct SettingsView: View { let processInfo = ProcessInfo.processInfo let txmLabel: String if processInfo.isTXMOverridden { - txmLabel = "TXM (Override)" + txmLabel = NSLocalizedString("TXM (Override)", comment: "") } else { - txmLabel = processInfo.hasTXM ? "TXM" : "Non TXM" + txmLabel = processInfo.hasTXM ? NSLocalizedString("TXM", comment: "") : NSLocalizedString("Non TXM", comment: "") } - return "Version \(appVersion) • iOS \(UIDevice.current.systemVersion) • \(txmLabel)" + return String(format: NSLocalizedString("Version %@ • iOS %@ • %@", comment: ""), appVersion, UIDevice.current.systemVersion, txmLabel) } // MARK: - Business Logic @@ -299,7 +299,7 @@ struct SettingsView: View { await MainActor.run { isRedownloadingDDI = true ddiDownloadProgress = 0 - ddiStatusMessage = "Preparing download…" + ddiStatusMessage = NSLocalizedString("Preparing download…", comment: "") ddiResultMessage = nil } do { @@ -368,13 +368,13 @@ struct TabCustomizationView: View { enabledTabIdentifiers = TabConfiguration.serialize(ids) } } header: { - Text("Pinned") + Text(NSLocalizedString("Pinned", comment: "")) } footer: { - Text("Settings is fixed as the 4th tab.") + Text(NSLocalizedString("Settings is fixed as the 4th tab.", comment: "")) } if !availableOptions.isEmpty { - Section("Available") { + Section(NSLocalizedString("Available", comment: "")) { ForEach(availableOptions) { option in Button { var ids = selectedIDs @@ -391,7 +391,7 @@ struct TabCustomizationView: View { } } } - .navigationTitle("Tab Bar") + .navigationTitle(NSLocalizedString("Tab Bar", comment: "")) .toolbar { EditButton() } From 91fe7c81ba56a9b4ca9ab11a49dd3935cd661287 Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 21:40:34 +0800 Subject: [PATCH 05/10] zh-Hans Localization #5 --- StikJIT/Assets.xcassets/Localizable.xcstrings | 155 +++++++++++++++++- StikJIT/Views/ProfileView.swift | 2 +- 2 files changed, 155 insertions(+), 2 deletions(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index 7f9d50d9..083fb814 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -1446,7 +1446,7 @@ } } }, - "Star on Github": { + "Star on GitHub": { "extractionState" : "manual", "localizations" : { "en" : { @@ -1921,6 +1921,159 @@ } } } + }, + "Search scripts…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search scripts…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索脚本…" + } + } + } + }, + "Scripts": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Scripts" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "脚本" + } + } + } + }, + "System": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "System" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "系统" + } + } + } + }, + "Settings": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "设置" + } + } + } + }, + "Pause syslog stream":{ + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pause syslog stream" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂停系统日志输出" + } + } + } + }, + "Search device info…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search device info…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索设备信息…" + } + } + } + }, + "Total Processes": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Total Processes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "总进程数量" + } + } + } + }, + "Search location…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search location…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索地址…" + } + } + } + }, + "Expires: %@": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Expires: %@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在%@之后过期" + } + } + } } }, "version" : "1.1" diff --git a/StikJIT/Views/ProfileView.swift b/StikJIT/Views/ProfileView.swift index 2f8e948e..8f31f994 100644 --- a/StikJIT/Views/ProfileView.swift +++ b/StikJIT/Views/ProfileView.swift @@ -158,7 +158,7 @@ struct ProfileView: View { if let match = entry.bestMatchingProfile { HStack { Image(systemName: "clock") - Text("Expires: \(match.profile.formattedDate)") + Text(String(format: NSLocalizedString("Expires: %@", comment: ""), match.profile.formattedDate)) } .foregroundStyle(match.profile.dateColor) .font(.subheadline) From cb4f6d62c11eebe6755c76ac6f5a07eb206510fe Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 22:08:00 +0800 Subject: [PATCH 06/10] Localization #6 --- StikJIT/Assets.xcassets/Localizable.xcstrings | 329 ++++++++++++++++-- StikJIT/Views/ConsoleLogsView.swift | 4 +- StikJIT/Views/MapSelectionView.swift | 12 +- 3 files changed, 317 insertions(+), 28 deletions(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index 083fb814..771313a7 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -545,23 +545,6 @@ } } }, - "End" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "End" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "结束" - } - } - } - }, "Export Failed" : { "extractionState" : "manual", "localizations" : { @@ -1203,7 +1186,7 @@ "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "固定" + "value" : "选定地点" } } } @@ -1237,7 +1220,7 @@ "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "启动方式(?)" + "value" : "启用路线" } } } @@ -1480,6 +1463,125 @@ } } }, + "Start syslog relay": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Start syslog relay" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启动系统日志输出" + } + } + } + }, + "Simulation Failed": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Simulation Failed" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "模拟失败" + } + } + } + }, + "Could not simulate location (error %d). Make sure the device is connected and the DDI is mounted.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Could not simulate location (error %d). Make sure the device is connected and the DDI is mounted." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "无法模拟位置(错误 %d)。请确保设备已连接且DDI已挂载。" + } + } + } + }, + "Route Simulation Failed": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Route Simulation Failed" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "路线模拟失败" + } + } + } + }, + "Could not start route simulation (error %d). Make sure the device is connected and the DDI is mounted.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Could not start route simulation (error %d). Make sure the device is connected and the DDI is mounted." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "无法启动路线模拟(错误 %d)。请确保设备已连接且DDI已挂载。" + } + } + } + }, + "Resume syslog stream": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resume syslog stream" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "恢复系统日志输出" + } + } + } + }, + "Pause syslog stream": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pause syslog stream" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "暂停系统日志输出" + } + } + } + }, "Access additional tools": { "extractionState" : "manual", "localizations" : { @@ -1956,6 +2058,23 @@ } } }, + "Save": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Save" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "保存" + } + } + } + }, "System": { "extractionState" : "manual", "localizations" : { @@ -2041,7 +2160,7 @@ } } }, - "Search location…": { + "Search location...": { "extractionState" : "manual", "localizations" : { "en" : { @@ -2074,6 +2193,176 @@ } } } + }, + "Simulate Route": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Simulate Route" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模拟路线" + } + } + } + }, + "Use Route": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Use Route" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用路线" + } + } + } + }, + "Start": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Start" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "起点" + } + } + } + }, + "End": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "End" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "终点" + } + } + } + }, + "Search for a start and destination to build the route.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search for a start and destination to build the route." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索起终点以建立路线" + } + } + } + }, + "Resolving location…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resolving location…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "建立路线中…" + } + } + } + }, + "Simulate Location": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Simulate Location" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模拟定位" + } + } + } + }, + "Stop": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Stop" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "停止" + } + } + } + }, + "Tap map to drop pin": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tap map to drop pin" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "点击地图来固定位置" + } + } + } + }, + "Drop a pin on the map and tap the bookmark icon to save a location.": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Drop a pin on the map and tap the bookmark icon to save a location." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在地图上标记地点以保存位置" + } + } + } } }, "version" : "1.1" diff --git a/StikJIT/Views/ConsoleLogsView.swift b/StikJIT/Views/ConsoleLogsView.swift index ac592e83..a21a2a40 100644 --- a/StikJIT/Views/ConsoleLogsView.swift +++ b/StikJIT/Views/ConsoleLogsView.swift @@ -534,9 +534,9 @@ struct ConsoleLogsView: View { private var syslogControlLabel: String { if !systemLogStream.isStreaming { - return "Start syslog relay" + return NSLocalizedString("Start syslog relay", comment: "") } - return systemLogStream.isPaused ? "Resume syslog stream" : "Pause syslog stream" + return systemLogStream.isPaused ? NSLocalizedString("Resume syslog stream", comment: "") : NSLocalizedString("Pause syslog stream", comment: "") } private func presentAlert(title: String, message: String) { diff --git a/StikJIT/Views/MapSelectionView.swift b/StikJIT/Views/MapSelectionView.swift index b787e583..7ef26232 100644 --- a/StikJIT/Views/MapSelectionView.swift +++ b/StikJIT/Views/MapSelectionView.swift @@ -804,9 +804,9 @@ struct LocationSimulationView: View { private func simulate() { guard pairingExists, let coord = coordinate, !isBusy else { return } runLocationCommand( - errorTitle: "Simulation Failed", + errorTitle: NSLocalizedString("Simulation Failed", comment: ""), errorMessage: { code in - "Could not simulate location (error \(code)). Make sure the device is connected and the DDI is mounted." + String(format: NSLocalizedString("Could not simulate location (error %d). Make sure the device is connected and the DDI is mounted.", comment: ""), code) }, operation: { locationUpdateCode(for: coord) } ) { @@ -827,9 +827,9 @@ struct LocationSimulationView: View { stopResendLoop() cancelRoutePlayback(resetMarker: false) runLocationCommand( - errorTitle: "Route Simulation Failed", + errorTitle: NSLocalizedString("Route Simulation Failed", comment: ""), errorMessage: { code in - "Could not start route simulation (error \(code)). Make sure the device is connected and the DDI is mounted." + String(format: NSLocalizedString("Could not start route simulation (error %d). Make sure the device is connected and the DDI is mounted.", comment: ""), code) }, operation: { locationUpdateCode(for: firstCoordinate) } ) { @@ -1137,7 +1137,7 @@ private struct RouteSearchSheet: View { NavigationStack { VStack(alignment: .leading, spacing: 16) { routeField( - title: "Start", + title: NSLocalizedString("Start", comment: ""), icon: "circle.fill", tint: .green, text: $startQuery, @@ -1146,7 +1146,7 @@ private struct RouteSearchSheet: View { ) routeField( - title: "End", + title: NSLocalizedString("End", comment: ""), icon: "flag.checkered.circle.fill", tint: .red, text: $endQuery, From b451a4a9bfa5bf76c532eb1c9e4855324dbaf606 Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 22:18:05 +0800 Subject: [PATCH 07/10] Localization #7 --- StikJIT/Assets.xcassets/Localizable.xcstrings | 68 +++++++++++++++++++ StikJIT/Utilities/DeviceInfoManager.swift | 6 +- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index 771313a7..cc677b87 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -1582,6 +1582,57 @@ } } }, + "Copy All (Text)": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copy All (Text)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "复制全部(文本)" + } + } + } + }, + "Copy All (CSV)": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copy All (CSV)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "复制全部(CSV)" + } + } + } + }, + "Share…": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Share…" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "分享…" + } + } + } + }, "Access additional tools": { "extractionState" : "manual", "localizations" : { @@ -2363,6 +2414,23 @@ } } } + }, + "Copied": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copied" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已复制" + } + } + } } }, "version" : "1.1" diff --git a/StikJIT/Utilities/DeviceInfoManager.swift b/StikJIT/Utilities/DeviceInfoManager.swift index 51201706..c7307bee 100644 --- a/StikJIT/Utilities/DeviceInfoManager.swift +++ b/StikJIT/Utilities/DeviceInfoManager.swift @@ -253,13 +253,13 @@ struct DeviceInfoView: View { Menu { Button { copyAllText() } label: { - Label("Copy All (Text)", systemImage: "doc.on.doc") + Label(NSLocalizedString("Copy All (Text)", comment: ""), systemImage: "doc.on.doc") } Button { copyAllCSV() } label: { - Label("Copy All (CSV)", systemImage: "tablecells") + Label(NSLocalizedString("Copy All (CSV)", comment: ""), systemImage: "tablecells") } Button { shareAll() } label: { - Label("Share…", systemImage: "square.and.arrow.up.on.square") + Label(NSLocalizedString("Share…", comment: ""), systemImage: "square.and.arrow.up.on.square") } } label: { Image(systemName: "ellipsis.circle") From 5e375413920a05dc7c5e9e2d7af3d2dc547d0d81 Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 22:28:55 +0800 Subject: [PATCH 08/10] Localization #8 (Ready for PRs) --- StikJIT/Assets.xcassets/Localizable.xcstrings | 51 ++++++++++++------- StikJIT/Views/ProfileView.swift | 2 +- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index cc677b87..16c635f6 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -1633,6 +1633,23 @@ } } }, + "Show %d older profiles": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show %d older profiles" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "显示 %d 个旧配置" + } + } + } + }, "Access additional tools": { "extractionState" : "manual", "localizations" : { @@ -2160,23 +2177,6 @@ } } }, - "Pause syslog stream":{ - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pause syslog stream" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "暂停系统日志输出" - } - } - } - }, "Search device info…": { "extractionState" : "manual", "localizations" : { @@ -2431,6 +2431,23 @@ } } } + }, + "Search": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索" + } + } + } } }, "version" : "1.1" diff --git a/StikJIT/Views/ProfileView.swift b/StikJIT/Views/ProfileView.swift index 8f31f994..008f6912 100644 --- a/StikJIT/Views/ProfileView.swift +++ b/StikJIT/Views/ProfileView.swift @@ -203,7 +203,7 @@ struct ProfileView: View { else { expandedApps.insert(entry.id) } } } label: { - Label(showMore ? "Hide older profiles" : "Show \(extraProfiles.count) older profiles", + Label(showMore ? NSLocalizedString("Hide older profiles", comment: "") : String(format: NSLocalizedString("Show %d older profiles", comment: ""), extraProfiles.count), systemImage: showMore ? "chevron.up" : "chevron.down") .font(.caption) .foregroundStyle(.blue) From 7d7caeba8cf827ad81e62cd85074a1b1b81f843f Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 22:36:44 +0800 Subject: [PATCH 09/10] added xcpretty --- .github/workflows/build_ipa.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_ipa.yml b/.github/workflows/build_ipa.yml index 3b636bf3..698ab781 100644 --- a/.github/workflows/build_ipa.yml +++ b/.github/workflows/build_ipa.yml @@ -40,7 +40,8 @@ jobs: CODE_SIGNING_REQUIRED=NO \ CODE_SIGNING_ALLOWED=NO \ SWIFT_OPTIMIZATION_LEVEL="-Onone" \ - IPHONEOS_DEPLOYMENT_TARGET=17.4 + IPHONEOS_DEPLOYMENT_TARGET=17.4 \ + | xcpretty - name: 4. Package .app into .ipa run: | From 7f264423c2dac861de2f71c1edfe6af2a700de3f Mon Sep 17 00:00:00 2001 From: jlj1102 Date: Fri, 17 Apr 2026 22:42:54 +0800 Subject: [PATCH 10/10] Enhancement of Localization --- StikJIT/Assets.xcassets/Localizable.xcstrings | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/StikJIT/Assets.xcassets/Localizable.xcstrings b/StikJIT/Assets.xcassets/Localizable.xcstrings index 16c635f6..2f1ebcb9 100644 --- a/StikJIT/Assets.xcassets/Localizable.xcstrings +++ b/StikJIT/Assets.xcassets/Localizable.xcstrings @@ -35,6 +35,23 @@ } } }, + "Advanced": { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Advanced" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "高级" + } + } + } + }, "Add to Home" : { "extractionState" : "manual", "localizations" : { @@ -506,7 +523,7 @@ "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "确认完成" + "value" : "完成" } } }