From 8e1171efd9eb0199db87cee736b506edb081a018 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 22 Dec 2023 20:43:56 +0800 Subject: [PATCH 01/20] test Google Gemini --- Easydict.xcodeproj/project.pbxproj | 23 ++++++++++++++++--- .../xcshareddata/swiftpm/Package.resolved | 9 ++++++++ Easydict/App/AppDelegate.m | 4 ++++ .../Service/Caiyun/CaiyunService.swift | 21 +++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 9bb89217d..cf3be43c7 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 03022F1F2B36CF3100B63209 /* SwiftShell in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F1E2B36CF3100B63209 /* SwiftShell */; }; 03022F222B36D1A400B63209 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F212B36D1A400B63209 /* SnapKit */; }; 03022F312B370B7100B63209 /* EasydictSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03022F302B370B7100B63209 /* EasydictSwiftTests.swift */; }; + 03022F192B3591AE00B63209 /* GoogleGenerativeAI in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F182B3591AE00B63209 /* GoogleGenerativeAI */; }; 030570E22ADB919900C9905E /* EZAppleScriptManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 030570E12ADB919900C9905E /* EZAppleScriptManager.m */; }; 0309E1ED292B439A00AFB76A /* EZTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0309E1EC292B439A00AFB76A /* EZTextView.m */; }; 0309E1F0292B4A5E00AFB76A /* NSView+EZGetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0309E1EF292B4A5E00AFB76A /* NSView+EZGetViewController.m */; }; @@ -794,6 +795,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 03022F192B3591AE00B63209 /* GoogleGenerativeAI in Frameworks */, 2721E4D02AFE920700A059AC /* Alamofire in Frameworks */, 03022F1F2B36CF3100B63209 /* SwiftShell in Frameworks */, 038030952B4106800009230C /* CocoaLumberjack in Frameworks */, @@ -2349,6 +2351,7 @@ 038EA1A92B41169C008A6DD1 /* ZipArchive */, 038EA1AC2B41282F008A6DD1 /* MJExtension */, EA3B81FB2B52555C004C0E8B /* Defaults */, + 03022F182B3591AE00B63209 /* GoogleGenerativeAI */, ); productName = Bob; productReference = C99EEB182385796700FEE666 /* Easydict-debug.app */; @@ -2408,6 +2411,7 @@ 038EA1A82B41169C008A6DD1 /* XCRemoteSwiftPackageReference "ZipArchive" */, 038EA1AB2B41282F008A6DD1 /* XCRemoteSwiftPackageReference "MJExtension" */, EA3B81FA2B52555C004C0E8B /* XCRemoteSwiftPackageReference "Defaults" */, + 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */, ); productRefGroup = C99EEB192385796700FEE666 /* Products */; projectDirPath = ""; @@ -3182,8 +3186,8 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 2.5.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; + MARKETING_VERSION = 2.4.1; PRODUCT_BUNDLE_IDENTIFIER = "com.izual.Easydict-debug"; PRODUCT_MODULE_NAME = Easydict; PRODUCT_NAME = "Easydict-debug"; @@ -3222,7 +3226,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 11.0; + MACOSX_DEPLOYMENT_TARGET = 12.0; MARKETING_VERSION = 2.5.0; PRODUCT_BUNDLE_IDENTIFIER = com.izual.Easydict; PRODUCT_MODULE_NAME = Easydict; @@ -3363,6 +3367,14 @@ requirement = { kind = upToNextMajorVersion; minimumVersion = 10.45.2; + }; + }; + 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/google/generative-ai-swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.4.4; }; }; 03FD68B92B1DC59600FD388E /* XCRemoteSwiftPackageReference "CryptoSwift" */ = { @@ -3456,6 +3468,11 @@ isa = XCSwiftPackageProductDependency; package = 03CF27FC2B3DA7D500E19B57 /* XCRemoteSwiftPackageReference "realm-swift" */; productName = RealmSwift; + }; + 03022F182B3591AE00B63209 /* GoogleGenerativeAI */ = { + isa = XCSwiftPackageProductDependency; + package = 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */; + productName = GoogleGenerativeAI; }; 03FD68BA2B1DC59600FD388E /* CryptoSwift */ = { isa = XCSwiftPackageProductDependency; diff --git a/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved index 38cf97c19..85e3f87d5 100644 --- a/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -72,6 +72,15 @@ "version" : "10.19.1" } }, + { + "identity" : "generative-ai-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/generative-ai-swift", + "state" : { + "revision" : "fead3038a70047a72ea2cf39e96d3add71c372de", + "version" : "0.4.4" + } + }, { "identity" : "googleappmeasurement", "kind" : "remoteSourceControl", diff --git a/Easydict/App/AppDelegate.m b/Easydict/App/AppDelegate.m index 8aa9e5f27..8b068d8d3 100644 --- a/Easydict/App/AppDelegate.m +++ b/Easydict/App/AppDelegate.m @@ -46,6 +46,10 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Change App icon manually. // NSApplication.sharedApplication.applicationIconImage = [NSImage imageNamed:@"white-black-icon"]; + + [EZCaiyunService testGeminiWithCompletionHandler:^{ + + }]; } /// Auto set up app language. diff --git a/Easydict/Feature/Service/Caiyun/CaiyunService.swift b/Easydict/Feature/Service/Caiyun/CaiyunService.swift index b36cfbdf8..a060ef4a4 100644 --- a/Easydict/Feature/Service/Caiyun/CaiyunService.swift +++ b/Easydict/Feature/Service/Caiyun/CaiyunService.swift @@ -9,6 +9,7 @@ import Alamofire import Defaults import Foundation +import GoogleGenerativeAI @objc(EZCaiyunService) public final class CaiyunService: QueryService { @@ -107,6 +108,26 @@ public final class CaiyunService: QueryService { request.cancel() }, serviceType: serviceType().rawValue) } + + @objc static func testGemini() async { + // https://github.com/google/generative-ai-swift + do { + let prompt = "你好" + let model = GenerativeModel(name: "gemini-pro", apiKey: "") + let outputContentStream = model.generateContentStream(prompt) + + // stream response + for try await outputContent in outputContentStream { + guard let line = outputContent.text else { + return + } + + print("gemini: \(line)") + } + } catch { + print(error.localizedDescription) + } + } } enum QueryServiceError: Error { From db4c2a56201919510561d5bec724f3e20f0201df Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 29 Dec 2023 13:56:34 +0800 Subject: [PATCH 02/20] perf: use Task to wrap gemini async stream --- Easydict/App/AppDelegate.m | 5 --- .../Service/Caiyun/CaiyunService.swift | 41 ++++++++++++------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Easydict/App/AppDelegate.m b/Easydict/App/AppDelegate.m index 8b068d8d3..d46a683e9 100644 --- a/Easydict/App/AppDelegate.m +++ b/Easydict/App/AppDelegate.m @@ -18,7 +18,6 @@ #import "AppDelegate+EZURLScheme.h" #import #import -#import "Easydict-Swift.h" @interface AppDelegate () @@ -46,10 +45,6 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // Change App icon manually. // NSApplication.sharedApplication.applicationIconImage = [NSImage imageNamed:@"white-black-icon"]; - - [EZCaiyunService testGeminiWithCompletionHandler:^{ - - }]; } /// Auto set up app language. diff --git a/Easydict/Feature/Service/Caiyun/CaiyunService.swift b/Easydict/Feature/Service/Caiyun/CaiyunService.swift index a060ef4a4..de2405247 100644 --- a/Easydict/Feature/Service/Caiyun/CaiyunService.swift +++ b/Easydict/Feature/Service/Caiyun/CaiyunService.swift @@ -81,6 +81,9 @@ public final class CaiyunService: QueryService { "x-authorization": "token " + token, ] + geminiTranslate(text, from: from, to: to, completion: completion) + return + let request = AF.request(apiEndPoint, method: .post, parameters: parameters, @@ -109,23 +112,31 @@ public final class CaiyunService: QueryService { }, serviceType: serviceType().rawValue) } - @objc static func testGemini() async { - // https://github.com/google/generative-ai-swift - do { - let prompt = "你好" - let model = GenerativeModel(name: "gemini-pro", apiKey: "") - let outputContentStream = model.generateContentStream(prompt) - - // stream response - for try await outputContent in outputContentStream { - guard let line = outputContent.text else { - return + public func geminiTranslate(_ text: String, from: Language, to: Language, completion: @escaping (EZQueryResult, Error?) -> Void) { + Task { + // https://github.com/google/generative-ai-swift + do { + var resultString = "" + let prompt = "translate this \(from.rawValue) text into \(to.rawValue): \(text)" + print("gemini prompt: \(prompt)") + let model = GenerativeModel(name: "gemini-pro", apiKey: "") + let outputContentStream = model.generateContentStream(prompt) + + // stream response + for try await outputContent in outputContentStream { + guard let line = outputContent.text else { + return + } + + print("gemini response: \(line)") + resultString += line + result.translatedResults = [resultString] + completion(result, nil) } - - print("gemini: \(line)") + } catch { + print(error.localizedDescription) + completion(result, error) } - } catch { - print(error.localizedDescription) } } } From a353c4aaa136c7387382170f9a046a1ac1a50034 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 2 Jan 2024 20:52:19 -0800 Subject: [PATCH 03/20] feat: initiate support for Google Gemini --- Easydict.xcodeproj/project.pbxproj | 16 +++ .../Gemini.imageset/Contents.json | 21 ++++ .../service-icon/Gemini.imageset/Gemini.png | Bin 0 -> 165317 bytes Easydict/App/Localizable.xcstrings | 17 ++++ .../Service/Gemini/GeminiService.swift | 94 ++++++++++++++++++ Easydict/Feature/Service/Model/EZConstKey.h | 1 + Easydict/Feature/Service/Model/EZEnumTypes.h | 1 + Easydict/Feature/Service/Model/EZEnumTypes.m | 1 + .../Feature/Service/Model/EZServiceTypes.m | 1 + .../Utility/EZLinkParser/EZSchemeParser.m | 1 + 10 files changed, 153 insertions(+) create mode 100644 Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Contents.json create mode 100644 Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Gemini.png create mode 100644 Easydict/Feature/Service/Gemini/GeminiService.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index cf3be43c7..2c0eeb02d 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -258,6 +258,8 @@ 9672D7D22B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m in Sources */ = {isa = PBXBuildFile; fileRef = 9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */; }; A0B65CA0F31AC8ECFB8347CC /* Pods_EasydictTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 378E73A7EA8FC8FB9C975A63 /* Pods_EasydictTests.framework */; }; B87AC7E36367075BA5D13234 /* Pods_Easydict.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6372B33DFF803C7096A82250 /* Pods_Easydict.framework */; }; + C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0AC2B450D4800A9D231 /* GeminiService.swift */; }; + C415C0AF2B450F9200A9D231 /* GeminiTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */; }; C4DD01E92B12B3C80025EE8E /* TencentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01E82B12B3C80025EE8E /* TencentService.swift */; }; C4DD01EB2B12BA250025EE8E /* TencentResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */; }; C4DD01ED2B12BE9B0025EE8E /* TencentTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */; }; @@ -747,6 +749,8 @@ 9672D7D02B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MASShortcutBinder+EZMASShortcutBinder.h"; sourceTree = ""; }; 9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MASShortcutBinder+EZMASShortcutBinder.m"; sourceTree = ""; }; A230E9A2358C7FBC7FB26189 /* Pods-EasydictTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EasydictTests.debug.xcconfig"; path = "Target Support Files/Pods-EasydictTests/Pods-EasydictTests.debug.xcconfig"; sourceTree = ""; }; + C415C0AC2B450D4800A9D231 /* GeminiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiService.swift; sourceTree = ""; }; + C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GeminiTranslateType.swift; path = ../../../../../../../GeminiTranslateType.swift; sourceTree = ""; }; C4DD01E82B12B3C80025EE8E /* TencentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentService.swift; sourceTree = ""; }; C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentResponse.swift; sourceTree = ""; }; C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentTranslateType.swift; sourceTree = ""; }; @@ -1305,6 +1309,7 @@ isa = PBXGroup; children = ( 62E2BF462B4082BA00E42D38 /* Ali */, + C415C0AB2B450C4500A9D231 /* Gemini */, 17BCAEF22B0DFF9000A7D372 /* Niutrans */, 2746AEBF2AF95040005FE0A1 /* Caiyun */, C4DD01E72B12B3B00025EE8E /* Tencent */, @@ -2143,6 +2148,15 @@ path = Pods; sourceTree = ""; }; + C415C0AB2B450C4500A9D231 /* Gemini */ = { + isa = PBXGroup; + children = ( + C415C0AC2B450D4800A9D231 /* GeminiService.swift */, + C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */, + ); + path = Gemini; + sourceTree = ""; + }; C4A40A9B2AC0168400B8E6EF /* Recovered References */ = { isa = PBXGroup; children = ( @@ -2652,6 +2666,7 @@ 03542A522937B69200C34C33 /* EZYoudaoTranslateResponse.m in Sources */, 03B0230129231FA6001C7E63 /* EZQueryView.m in Sources */, 03542A3D2937AF4F00C34C33 /* EZQueryResult.m in Sources */, + C415C0AF2B450F9200A9D231 /* GeminiTranslateType.swift in Sources */, 03262C1F29EF8EE500EFECA0 /* EZPrivacyViewController.m in Sources */, 9672D7D22B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m in Sources */, 03BDA7BF2A26DA280079D04F /* NSScanner+EscapedScanning.m in Sources */, @@ -2732,6 +2747,7 @@ 03B0232229231FA6001C7E63 /* NSImage+MM.m in Sources */, 03BB2DEF29F59C8A00447EDD /* EZSymbolImageButton.m in Sources */, 0A2BA9642B4A3CCD002872A4 /* Notification+Name.swift in Sources */, + C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */, 62A2D03F2A82967F007EEB01 /* EZBingRequest.m in Sources */, 03BDA7BE2A26DA280079D04F /* XPMCountedArgument.m in Sources */, 03D35DAA2AA6C49B00B023FE /* NSString+EZRegex.m in Sources */, diff --git a/Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Contents.json b/Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Contents.json new file mode 100644 index 000000000..f0bbce672 --- /dev/null +++ b/Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Gemini.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Gemini.png b/Easydict/App/Assets.xcassets/service-icon/Gemini.imageset/Gemini.png new file mode 100644 index 0000000000000000000000000000000000000000..de0d56846487af69e72e446bfce691db3e4fe4b2 GIT binary patch literal 165317 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 ServiceType { + .gemini + } + + override public func link() -> String? { + "https://bard.google.com/chat" + } + + override public func name() -> String { + NSLocalizedString("gemini_translate", comment: "The name of Gemini Translate") + } + + override public func supportLanguagesDictionary() -> MMOrderedDictionary { + // TODO: Replace MMOrderedDictionary. + let orderedDict = MMOrderedDictionary() + GeminiTranslateType.supportLanguagesDictionary.forEach { key, value in + orderedDict.setObject(value as NSString, forKey: key.rawValue as NSString) + } + return orderedDict + } + + override public func ocr(_: EZQueryModel) async throws -> EZOCRResult { + NSLog("Gemini Translate does not support OCR") + throw QueryServiceError.notSupported + } + + override public func needPrivateAPIKey() -> Bool { + true + } + + override public func hasPrivateAPIKey() -> Bool { + if apiKey == defaultAPIKey { + return false + } + return true + } + + private let defaultAPIKey = "" /* .decryptAES() */ + + // easydict://writeKeyValue?EZGeminiAPIKey=xxx + private var apiKey: String { + let apiKey = UserDefaults.standard.string(forKey: EZGeminiAPIKey) + if let apiKey, !apiKey.isEmpty { + return apiKey + } else { + return defaultAPIKey + } + } + + override public func autoConvertTraditionalChinese() -> Bool { + true + } + + override public func translate(_ text: String, from: Language, to: Language, completion: @escaping (EZQueryResult, Error?) -> Void) { + Task { + // https://github.com/google/generative-ai-swift + do { + var resultString = "" + let prompt = "translate this \(from.rawValue) text into \(to.rawValue): \(text)" + print("gemini prompt: \(prompt)") + let model = GenerativeModel(name: "gemini-pro", apiKey: apiKey) + let outputContentStream = model.generateContentStream(prompt) + + // stream response + for try await outputContent in outputContentStream { + guard let line = outputContent.text else { + return + } + + print("gemini response: \(line)") + resultString += line + result.translatedResults = [resultString] + completion(result, nil) + } + } catch { + print(error.localizedDescription) + completion(result, error) + } + } + } +} diff --git a/Easydict/Feature/Service/Model/EZConstKey.h b/Easydict/Feature/Service/Model/EZConstKey.h index be00eeea2..cf422670b 100644 --- a/Easydict/Feature/Service/Model/EZConstKey.h +++ b/Easydict/Feature/Service/Model/EZConstKey.h @@ -35,6 +35,7 @@ static NSString *const EZNiuTransAPIKey = @"EZNiuTransAPIKey"; static NSString *const EZCaiyunToken = @"EZCaiyunToken"; static NSString *const EZTencentSecretId = @"EZTencentSecretId"; static NSString *const EZTencentSecretKey = @"EZTencentSecretKey"; +static NSString *const EZGeminiAPIKey = @"EZGeminiAPIKey"; static NSString *const EZAliAccessKeyId = @"EZAliAccessKeyId"; static NSString *const EZAliAccessKeySecret = @"EZAliAccessKeySecret"; diff --git a/Easydict/Feature/Service/Model/EZEnumTypes.h b/Easydict/Feature/Service/Model/EZEnumTypes.h index 28dbeea3a..cad41e525 100644 --- a/Easydict/Feature/Service/Model/EZEnumTypes.h +++ b/Easydict/Feature/Service/Model/EZEnumTypes.h @@ -43,6 +43,7 @@ FOUNDATION_EXPORT EZServiceType const EZServiceTypeNiuTrans; FOUNDATION_EXPORT EZServiceType const EZServiceTypeCaiyun; FOUNDATION_EXPORT EZServiceType const EZServiceTypeTencent; FOUNDATION_EXPORT EZServiceType const EZServiceTypeAli; +FOUNDATION_EXPORT EZServiceType const EZServiceTypeGemini; FOUNDATION_EXPORT NSString *const EZQueryTextTypeKey; FOUNDATION_EXPORT NSString *const EZIntelligentQueryTextTypeKey; diff --git a/Easydict/Feature/Service/Model/EZEnumTypes.m b/Easydict/Feature/Service/Model/EZEnumTypes.m index 76e778da2..879b9102b 100644 --- a/Easydict/Feature/Service/Model/EZEnumTypes.m +++ b/Easydict/Feature/Service/Model/EZEnumTypes.m @@ -22,6 +22,7 @@ NSString *const EZServiceTypeCaiyun = @"Caiyun"; NSString *const EZServiceTypeTencent = @"Tencent"; NSString *const EZServiceTypeAli = @"Alibaba"; +NSString *const EZServiceTypeGemini = @"Gemini"; NSString *const EZServiceTypeAppleDictionary = @"AppleDictionary"; diff --git a/Easydict/Feature/Service/Model/EZServiceTypes.m b/Easydict/Feature/Service/Model/EZServiceTypes.m index d63ed6649..c40d7ceba 100644 --- a/Easydict/Feature/Service/Model/EZServiceTypes.m +++ b/Easydict/Feature/Service/Model/EZServiceTypes.m @@ -63,6 +63,7 @@ + (instancetype)allocWithZone:(struct _NSZone *)zone { EZServiceTypeCaiyun, [EZCaiyunService class], EZServiceTypeTencent, [EZTencentService class], EZServiceTypeAli, [EZAliService class], + EZServiceTypeGemini, [EZGeminiService class], nil]; return allServiceDict; } diff --git a/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m b/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m index cd8ba1630..2cf47dc60 100644 --- a/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m +++ b/Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m @@ -219,6 +219,7 @@ - (NSArray *)allowedReadWriteKeys { EZAliAccessKeyId, EZAliAccessKeySecret, + EZGeminiAPIKey, EZIntelligentQueryModeKey, ]; From 6b7a4d49f3f7d639ac9a97d2cc5c3d6fa5be28e5 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 2 Jan 2024 21:22:47 -0800 Subject: [PATCH 04/20] fix: build error --- Easydict/App/AppDelegate.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Easydict/App/AppDelegate.m b/Easydict/App/AppDelegate.m index d46a683e9..8aa9e5f27 100644 --- a/Easydict/App/AppDelegate.m +++ b/Easydict/App/AppDelegate.m @@ -18,6 +18,7 @@ #import "AppDelegate+EZURLScheme.h" #import #import +#import "Easydict-Swift.h" @interface AppDelegate () From 3a51658d706095426258fd183e3286ee667addc4 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 2 Jan 2024 21:23:09 -0800 Subject: [PATCH 05/20] fix: missing GeminiTranslateType file --- Easydict.xcodeproj/project.pbxproj | 36 +++--- .../Service/Gemini/GeminiTranslateType.swift | 122 ++++++++++++++++++ 2 files changed, 140 insertions(+), 18 deletions(-) create mode 100644 Easydict/Feature/Service/Gemini/GeminiTranslateType.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 2c0eeb02d..080d6996d 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -11,11 +11,11 @@ 03008B2B2940D3230062B821 /* EZDeepLTranslate.m in Sources */ = {isa = PBXBuildFile; fileRef = 03008B2A2940D3230062B821 /* EZDeepLTranslate.m */; }; 03008B2E2941956D0062B821 /* EZURLSchemeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 03008B2D2941956D0062B821 /* EZURLSchemeHandler.m */; }; 03008B3F29444B0A0062B821 /* NSView+EZAnimatedHidden.m in Sources */ = {isa = PBXBuildFile; fileRef = 03008B3E29444B0A0062B821 /* NSView+EZAnimatedHidden.m */; }; + 03022F192B3591AE00B63209 /* GoogleGenerativeAI in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F182B3591AE00B63209 /* GoogleGenerativeAI */; }; 03022F1C2B35DEBA00B63209 /* Hue in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F1B2B35DEBA00B63209 /* Hue */; }; 03022F1F2B36CF3100B63209 /* SwiftShell in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F1E2B36CF3100B63209 /* SwiftShell */; }; 03022F222B36D1A400B63209 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F212B36D1A400B63209 /* SnapKit */; }; 03022F312B370B7100B63209 /* EasydictSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03022F302B370B7100B63209 /* EasydictSwiftTests.swift */; }; - 03022F192B3591AE00B63209 /* GoogleGenerativeAI in Frameworks */ = {isa = PBXBuildFile; productRef = 03022F182B3591AE00B63209 /* GoogleGenerativeAI */; }; 030570E22ADB919900C9905E /* EZAppleScriptManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 030570E12ADB919900C9905E /* EZAppleScriptManager.m */; }; 0309E1ED292B439A00AFB76A /* EZTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0309E1EC292B439A00AFB76A /* EZTextView.m */; }; 0309E1F0292B4A5E00AFB76A /* NSView+EZGetViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0309E1EF292B4A5E00AFB76A /* NSView+EZGetViewController.m */; }; @@ -259,7 +259,7 @@ A0B65CA0F31AC8ECFB8347CC /* Pods_EasydictTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 378E73A7EA8FC8FB9C975A63 /* Pods_EasydictTests.framework */; }; B87AC7E36367075BA5D13234 /* Pods_Easydict.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6372B33DFF803C7096A82250 /* Pods_Easydict.framework */; }; C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0AC2B450D4800A9D231 /* GeminiService.swift */; }; - C415C0AF2B450F9200A9D231 /* GeminiTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */; }; + C415C0B22B45258600A9D231 /* GeminiTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0B12B45258600A9D231 /* GeminiTranslateType.swift */; }; C4DD01E92B12B3C80025EE8E /* TencentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01E82B12B3C80025EE8E /* TencentService.swift */; }; C4DD01EB2B12BA250025EE8E /* TencentResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */; }; C4DD01ED2B12BE9B0025EE8E /* TencentTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */; }; @@ -750,7 +750,7 @@ 9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MASShortcutBinder+EZMASShortcutBinder.m"; sourceTree = ""; }; A230E9A2358C7FBC7FB26189 /* Pods-EasydictTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EasydictTests.debug.xcconfig"; path = "Target Support Files/Pods-EasydictTests/Pods-EasydictTests.debug.xcconfig"; sourceTree = ""; }; C415C0AC2B450D4800A9D231 /* GeminiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiService.swift; sourceTree = ""; }; - C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GeminiTranslateType.swift; path = ../../../../../../../GeminiTranslateType.swift; sourceTree = ""; }; + C415C0B12B45258600A9D231 /* GeminiTranslateType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeminiTranslateType.swift; sourceTree = ""; }; C4DD01E82B12B3C80025EE8E /* TencentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentService.swift; sourceTree = ""; }; C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentResponse.swift; sourceTree = ""; }; C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentTranslateType.swift; sourceTree = ""; }; @@ -2152,7 +2152,7 @@ isa = PBXGroup; children = ( C415C0AC2B450D4800A9D231 /* GeminiService.swift */, - C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */, + C415C0B12B45258600A9D231 /* GeminiTranslateType.swift */, ); path = Gemini; sourceTree = ""; @@ -2666,7 +2666,6 @@ 03542A522937B69200C34C33 /* EZYoudaoTranslateResponse.m in Sources */, 03B0230129231FA6001C7E63 /* EZQueryView.m in Sources */, 03542A3D2937AF4F00C34C33 /* EZQueryResult.m in Sources */, - C415C0AF2B450F9200A9D231 /* GeminiTranslateType.swift in Sources */, 03262C1F29EF8EE500EFECA0 /* EZPrivacyViewController.m in Sources */, 9672D7D22B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m in Sources */, 03BDA7BF2A26DA280079D04F /* NSScanner+EscapedScanning.m in Sources */, @@ -2824,6 +2823,7 @@ 6220AD5B2A82812300BBFB52 /* EZBingService.m in Sources */, 039F5508294B6E29004AB940 /* EZAboutViewController.m in Sources */, 03D8A6592A42A1A300D9A968 /* EZAppModel.m in Sources */, + C415C0B22B45258600A9D231 /* GeminiTranslateType.swift in Sources */, 036E7D7B293F4FC8002675DF /* EZOpenLinkButton.m in Sources */, EAED41EC2B54AA920005FE0A /* ServiceConfigurationSection.swift in Sources */, 276742092B3DC230002A2C75 /* AboutTab.swift in Sources */, @@ -3305,6 +3305,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/google/generative-ai-swift"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.4.4; + }; + }; 03022F1A2B35DEBA00B63209 /* XCRemoteSwiftPackageReference "Hue" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/zenangst/Hue"; @@ -3383,14 +3391,6 @@ requirement = { kind = upToNextMajorVersion; minimumVersion = 10.45.2; - }; - }; - 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/google/generative-ai-swift"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 0.4.4; }; }; 03FD68B92B1DC59600FD388E /* XCRemoteSwiftPackageReference "CryptoSwift" */ = { @@ -3420,6 +3420,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 03022F182B3591AE00B63209 /* GoogleGenerativeAI */ = { + isa = XCSwiftPackageProductDependency; + package = 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */; + productName = GoogleGenerativeAI; + }; 03022F1B2B35DEBA00B63209 /* Hue */ = { isa = XCSwiftPackageProductDependency; package = 03022F1A2B35DEBA00B63209 /* XCRemoteSwiftPackageReference "Hue" */; @@ -3484,11 +3489,6 @@ isa = XCSwiftPackageProductDependency; package = 03CF27FC2B3DA7D500E19B57 /* XCRemoteSwiftPackageReference "realm-swift" */; productName = RealmSwift; - }; - 03022F182B3591AE00B63209 /* GoogleGenerativeAI */ = { - isa = XCSwiftPackageProductDependency; - package = 03022F172B3591AE00B63209 /* XCRemoteSwiftPackageReference "generative-ai-swift" */; - productName = GoogleGenerativeAI; }; 03FD68BA2B1DC59600FD388E /* CryptoSwift */ = { isa = XCSwiftPackageProductDependency; diff --git a/Easydict/Feature/Service/Gemini/GeminiTranslateType.swift b/Easydict/Feature/Service/Gemini/GeminiTranslateType.swift new file mode 100644 index 000000000..aaa969ff1 --- /dev/null +++ b/Easydict/Feature/Service/Gemini/GeminiTranslateType.swift @@ -0,0 +1,122 @@ +// +// GeminiTranslateType.swift +// Easydict +// +// Created by Jerry on 2024-01-02. +// Copyright © 2024 izual. All rights reserved. +// + +import Foundation + +struct GeminiTranslateType: RawRepresentable { + var rawValue: String + + static let unsupported = GeminiTranslateType(rawValue: "unsupported") + + // https://ai.google.dev/available_regions + static let supportedTypes: [Language: [Language]] = [ + .arabic: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .bengali: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .bulgarian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .simplifiedChinese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .traditionalChinese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .croatian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .czech: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .danish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .dutch: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .english: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .estonian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .finnish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .french: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .german: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .greek: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .hebrew: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .hindi: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .hungarian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .indonesian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .italian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .japanese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .korean: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .latvian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .lithuanian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .norwegian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .polish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .portuguese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .romanian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .russian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .serbian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .slovak: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .slovenian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .spanish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], +// .swahili/kiswahili: [.swahili/kiswahili], Swahili language: not supported by Easydict + .swedish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .thai: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .turkish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .ukrainian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + .vietnamese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], + ] + + static let supportLanguagesDictionary: [Language: String] = [ + .arabic: "ar", + .bengali: "bn", + .bulgarian: "bg", + .simplifiedChinese: "zh", + .traditionalChinese: "zh", + .croatian: "hr", + .czech: "cs", + .danish: "da", + .dutch: "nl", + .english: "en", + .estonian: "et", + .finnish: "fi", + .french: "fr", + .german: "de", + .greek: "el", + .hebrew: "iw", + .hindi: "hi", + .hungarian: "hu", + .indonesian: "id", + .italian: "it", + .japanese: "ja", + .korean: "ko", + .latvian: "lv", + .lithuanian: "lt", + .norwegian: "no", + .polish: "pl", + .portuguese: "pt", + .romanian: "ro", + .russian: "ru", + .serbian: "sr", + .slovak: "sk", + .slovenian: "sl", + .spanish: "es", +// .swahili/kiswahili: "sw", + .swedish: "sv", + .thai: "th", + .turkish: "tr", + .ukrainian: "uk", + .vietnamese: "vi", + ] + + static func transType(from: Language, to: Language) -> GeminiTranslateType { + // Treat traditional Chinese as simplified Chinese. + if from == .traditionalChinese { + return transType(from: .simplifiedChinese, to: to) + } + + // We can auto convert to Traditional Chinese. + guard let targetLanguages = supportedTypes[from], + targetLanguages.contains(to) || to == .traditionalChinese + else { + return .unsupported + } + + guard let from = supportLanguagesDictionary[from], + let to = supportLanguagesDictionary[to] + else { + return .unsupported + } + + return GeminiTranslateType(rawValue: "\(from)2\(to)") + } +} From 15ee2697be4ae9665a025b11a54a51902ddfec21 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 2 Jan 2024 23:26:50 -0800 Subject: [PATCH 06/20] perf: restore CaiyunService --- .../Service/Caiyun/CaiyunService.swift | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/Easydict/Feature/Service/Caiyun/CaiyunService.swift b/Easydict/Feature/Service/Caiyun/CaiyunService.swift index de2405247..b36cfbdf8 100644 --- a/Easydict/Feature/Service/Caiyun/CaiyunService.swift +++ b/Easydict/Feature/Service/Caiyun/CaiyunService.swift @@ -9,7 +9,6 @@ import Alamofire import Defaults import Foundation -import GoogleGenerativeAI @objc(EZCaiyunService) public final class CaiyunService: QueryService { @@ -81,9 +80,6 @@ public final class CaiyunService: QueryService { "x-authorization": "token " + token, ] - geminiTranslate(text, from: from, to: to, completion: completion) - return - let request = AF.request(apiEndPoint, method: .post, parameters: parameters, @@ -111,34 +107,6 @@ public final class CaiyunService: QueryService { request.cancel() }, serviceType: serviceType().rawValue) } - - public func geminiTranslate(_ text: String, from: Language, to: Language, completion: @escaping (EZQueryResult, Error?) -> Void) { - Task { - // https://github.com/google/generative-ai-swift - do { - var resultString = "" - let prompt = "translate this \(from.rawValue) text into \(to.rawValue): \(text)" - print("gemini prompt: \(prompt)") - let model = GenerativeModel(name: "gemini-pro", apiKey: "") - let outputContentStream = model.generateContentStream(prompt) - - // stream response - for try await outputContent in outputContentStream { - guard let line = outputContent.text else { - return - } - - print("gemini response: \(line)") - resultString += line - result.translatedResults = [resultString] - completion(result, nil) - } - } catch { - print(error.localizedDescription) - completion(result, error) - } - } - } } enum QueryServiceError: Error { From 3d7ca38fa986ff4b84f1ce4b5b3ab241c801e2c6 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 2 Jan 2024 23:50:28 -0800 Subject: [PATCH 07/20] perf: improve gemini prompt from openai translate --- Easydict/Feature/Service/Gemini/GeminiService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index 2acde01c2..5cfa988b0 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -69,7 +69,7 @@ public final class GeminiService: QueryService { // https://github.com/google/generative-ai-swift do { var resultString = "" - let prompt = "translate this \(from.rawValue) text into \(to.rawValue): \(text)" + let prompt = "You are a translation expert proficient in various languages that can only translate text and cannot interpret it. You are able to accurately understand the meaning of proper nouns, idioms, metaphors, allusions or other obscure words in sentences and translate them into appropriate words by combining the context and language environment. The result of the translation should be natural and fluent, you can only return the translated text, do not show additional information and notes. Translate the following \(from.rawValue) text into \(to.rawValue): \(text)" print("gemini prompt: \(prompt)") let model = GenerativeModel(name: "gemini-pro", apiKey: apiKey) let outputContentStream = model.generateContentStream(prompt) From 6835cc3abec046275bcd52cf9a9f47611547e905 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 4 Jan 2024 12:57:43 -0800 Subject: [PATCH 08/20] refractor: define static property for translation prompt Co-Authored-By: Kyle --- Easydict/Feature/Service/Gemini/GeminiService.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index 5cfa988b0..6041e4c89 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -60,6 +60,8 @@ public final class GeminiService: QueryService { } } + private static let translationPrompt = "You are a translation expert proficient in various languages that can only translate text and cannot interpret it. You are able to accurately understand the meaning of proper nouns, idioms, metaphors, allusions or other obscure words in sentences and translate them into appropriate words by combining the context and language environment. The result of the translation should be natural and fluent, you can only return the translated text, do not show additional information and notes." + override public func autoConvertTraditionalChinese() -> Bool { true } @@ -69,7 +71,7 @@ public final class GeminiService: QueryService { // https://github.com/google/generative-ai-swift do { var resultString = "" - let prompt = "You are a translation expert proficient in various languages that can only translate text and cannot interpret it. You are able to accurately understand the meaning of proper nouns, idioms, metaphors, allusions or other obscure words in sentences and translate them into appropriate words by combining the context and language environment. The result of the translation should be natural and fluent, you can only return the translated text, do not show additional information and notes. Translate the following \(from.rawValue) text into \(to.rawValue): \(text)" + let prompt = GeminiService.translationPrompt + "Translate the following \(from.rawValue) text into \(to.rawValue): \(text)" print("gemini prompt: \(prompt)") let model = GenerativeModel(name: "gemini-pro", apiKey: apiKey) let outputContentStream = model.generateContentStream(prompt) From 06d924b3b27502cdaafa1eb0a0daa2615ba3a131 Mon Sep 17 00:00:00 2001 From: Jerry Date: Thu, 4 Jan 2024 17:08:00 -0800 Subject: [PATCH 09/20] perf: bump debug version --- Easydict.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 080d6996d..82b176ac3 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -3203,7 +3203,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 2.4.1; + MARKETING_VERSION = 2.5.0; PRODUCT_BUNDLE_IDENTIFIER = "com.izual.Easydict-debug"; PRODUCT_MODULE_NAME = Easydict; PRODUCT_NAME = "Easydict-debug"; From b14666e65b9b6374606875b68a4a7671c7b7cf30 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Sun, 7 Jan 2024 21:35:18 +0800 Subject: [PATCH 10/20] fix: resolve deprecated warnings --- Easydict/Feature/Utility/EZAudioUtils/EZAudioUtils.m | 6 +++--- .../Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Easydict/Feature/Utility/EZAudioUtils/EZAudioUtils.m b/Easydict/Feature/Utility/EZAudioUtils/EZAudioUtils.m index c18ed7160..59ed2348d 100644 --- a/Easydict/Feature/Utility/EZAudioUtils/EZAudioUtils.m +++ b/Easydict/Feature/Utility/EZAudioUtils/EZAudioUtils.m @@ -34,7 +34,7 @@ + (float)getSystemVolume { AudioObjectPropertyAddress address = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster}; + kAudioObjectPropertyElementMain}; if (!AudioObjectHasProperty(outputDeviceID, &address)) { NSLog(@"No volume returned for device 0x%0x", outputDeviceID); @@ -72,7 +72,7 @@ + (void)setSystemVolume:(float)volume { AudioObjectPropertyAddress address = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeOutput, - kAudioObjectPropertyElementMaster}; + kAudioObjectPropertyElementMain}; if (!AudioObjectHasProperty(outputDeviceID, &address)) { NSLog(@"No volume returned for device 0x%0x", outputDeviceID); @@ -92,7 +92,7 @@ + (AudioDeviceID)getDefaultOutputDeviceID { AudioObjectPropertyAddress address = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster}; + kAudioObjectPropertyElementMain}; UInt32 dataSize = sizeof(AudioDeviceID); OSStatus status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, NULL, &dataSize, &outputDeviceID); diff --git a/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m b/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m index 79e11eb56..148da924f 100644 --- a/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m +++ b/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m @@ -57,7 +57,7 @@ + (NSString *)getDeviceModel { /// Get device UUID, 4F07896A-1580-5270-A0E8-D7FA9DFA6868 + (NSString *)getDeviceUUID { - io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); + io_service_t platformExpert = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice")); CFStringRef uuidString = (CFStringRef)IORegistryEntryCreateCFProperty(platformExpert, CFSTR("IOPlatformUUID"), kCFAllocatorDefault, 0); NSString *uuid = (__bridge NSString *)(uuidString); IOObjectRelease(platformExpert); From bf330be08d47aa9f4e1e0eb9e697ba440e6298a3 Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Sun, 7 Jan 2024 22:30:53 -0800 Subject: [PATCH 11/20] refractor: remove GeminiTranslateType --- Easydict.xcodeproj/project.pbxproj | 4 - .../Service/Gemini/GeminiService.swift | 11 +- .../Service/Gemini/GeminiTranslateType.swift | 122 ------------------ 3 files changed, 9 insertions(+), 128 deletions(-) delete mode 100644 Easydict/Feature/Service/Gemini/GeminiTranslateType.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 82b176ac3..49c60577c 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -259,7 +259,6 @@ A0B65CA0F31AC8ECFB8347CC /* Pods_EasydictTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 378E73A7EA8FC8FB9C975A63 /* Pods_EasydictTests.framework */; }; B87AC7E36367075BA5D13234 /* Pods_Easydict.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6372B33DFF803C7096A82250 /* Pods_Easydict.framework */; }; C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0AC2B450D4800A9D231 /* GeminiService.swift */; }; - C415C0B22B45258600A9D231 /* GeminiTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C415C0B12B45258600A9D231 /* GeminiTranslateType.swift */; }; C4DD01E92B12B3C80025EE8E /* TencentService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01E82B12B3C80025EE8E /* TencentService.swift */; }; C4DD01EB2B12BA250025EE8E /* TencentResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */; }; C4DD01ED2B12BE9B0025EE8E /* TencentTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */; }; @@ -750,7 +749,6 @@ 9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MASShortcutBinder+EZMASShortcutBinder.m"; sourceTree = ""; }; A230E9A2358C7FBC7FB26189 /* Pods-EasydictTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EasydictTests.debug.xcconfig"; path = "Target Support Files/Pods-EasydictTests/Pods-EasydictTests.debug.xcconfig"; sourceTree = ""; }; C415C0AC2B450D4800A9D231 /* GeminiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiService.swift; sourceTree = ""; }; - C415C0B12B45258600A9D231 /* GeminiTranslateType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeminiTranslateType.swift; sourceTree = ""; }; C4DD01E82B12B3C80025EE8E /* TencentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentService.swift; sourceTree = ""; }; C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentResponse.swift; sourceTree = ""; }; C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentTranslateType.swift; sourceTree = ""; }; @@ -2152,7 +2150,6 @@ isa = PBXGroup; children = ( C415C0AC2B450D4800A9D231 /* GeminiService.swift */, - C415C0B12B45258600A9D231 /* GeminiTranslateType.swift */, ); path = Gemini; sourceTree = ""; @@ -2823,7 +2820,6 @@ 6220AD5B2A82812300BBFB52 /* EZBingService.m in Sources */, 039F5508294B6E29004AB940 /* EZAboutViewController.m in Sources */, 03D8A6592A42A1A300D9A968 /* EZAppModel.m in Sources */, - C415C0B22B45258600A9D231 /* GeminiTranslateType.swift in Sources */, 036E7D7B293F4FC8002675DF /* EZOpenLinkButton.m in Sources */, EAED41EC2B54AA920005FE0A /* ServiceConfigurationSection.swift in Sources */, 276742092B3DC230002A2C75 /* AboutTab.swift in Sources */, diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index 6041e4c89..3d9eb13e0 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -23,12 +23,19 @@ public final class GeminiService: QueryService { NSLocalizedString("gemini_translate", comment: "The name of Gemini Translate") } + // https://ai.google.dev/available_regions + private static let unsupportedLanguages: [Language] = [.persian, .filipino, .khmer, .lao, .malay, .mongolian, .burmese, .telugu, .tamil, .urdu] + override public func supportLanguagesDictionary() -> MMOrderedDictionary { // TODO: Replace MMOrderedDictionary. let orderedDict = MMOrderedDictionary() - GeminiTranslateType.supportLanguagesDictionary.forEach { key, value in - orderedDict.setObject(value as NSString, forKey: key.rawValue as NSString) + for language in EZLanguageManager.shared().allLanguages { + var value = language.rawValue + if !GeminiService.unsupportedLanguages.contains(language) { + orderedDict.setObject(value as NSString, forKey: language.rawValue as NSString) + } } + return orderedDict } diff --git a/Easydict/Feature/Service/Gemini/GeminiTranslateType.swift b/Easydict/Feature/Service/Gemini/GeminiTranslateType.swift deleted file mode 100644 index aaa969ff1..000000000 --- a/Easydict/Feature/Service/Gemini/GeminiTranslateType.swift +++ /dev/null @@ -1,122 +0,0 @@ -// -// GeminiTranslateType.swift -// Easydict -// -// Created by Jerry on 2024-01-02. -// Copyright © 2024 izual. All rights reserved. -// - -import Foundation - -struct GeminiTranslateType: RawRepresentable { - var rawValue: String - - static let unsupported = GeminiTranslateType(rawValue: "unsupported") - - // https://ai.google.dev/available_regions - static let supportedTypes: [Language: [Language]] = [ - .arabic: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .bengali: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .bulgarian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .simplifiedChinese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .traditionalChinese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .croatian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .czech: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .danish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .dutch: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .english: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .estonian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .finnish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .french: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .german: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .greek: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .hebrew: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .hindi: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .hungarian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .indonesian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .italian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .japanese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .korean: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .latvian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .lithuanian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .norwegian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .polish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .portuguese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .romanian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .russian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .serbian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .slovak: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .slovenian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .spanish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], -// .swahili/kiswahili: [.swahili/kiswahili], Swahili language: not supported by Easydict - .swedish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .thai: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .turkish: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .ukrainian: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - .vietnamese: [.arabic, .bengali, .bulgarian, .simplifiedChinese, .traditionalChinese, .croatian, .czech, .danish, .dutch, .english, .estonian, .finnish, .french, .german, .greek, .hebrew, .hindi, .hungarian, .indonesian, .italian, .japanese, .korean, .latvian, .lithuanian, .norwegian, .polish, .portuguese, .romanian, .russian, .serbian, .slovak, .slovenian, .spanish, .swedish, .thai, .turkish, .ukrainian, .vietnamese], - ] - - static let supportLanguagesDictionary: [Language: String] = [ - .arabic: "ar", - .bengali: "bn", - .bulgarian: "bg", - .simplifiedChinese: "zh", - .traditionalChinese: "zh", - .croatian: "hr", - .czech: "cs", - .danish: "da", - .dutch: "nl", - .english: "en", - .estonian: "et", - .finnish: "fi", - .french: "fr", - .german: "de", - .greek: "el", - .hebrew: "iw", - .hindi: "hi", - .hungarian: "hu", - .indonesian: "id", - .italian: "it", - .japanese: "ja", - .korean: "ko", - .latvian: "lv", - .lithuanian: "lt", - .norwegian: "no", - .polish: "pl", - .portuguese: "pt", - .romanian: "ro", - .russian: "ru", - .serbian: "sr", - .slovak: "sk", - .slovenian: "sl", - .spanish: "es", -// .swahili/kiswahili: "sw", - .swedish: "sv", - .thai: "th", - .turkish: "tr", - .ukrainian: "uk", - .vietnamese: "vi", - ] - - static func transType(from: Language, to: Language) -> GeminiTranslateType { - // Treat traditional Chinese as simplified Chinese. - if from == .traditionalChinese { - return transType(from: .simplifiedChinese, to: to) - } - - // We can auto convert to Traditional Chinese. - guard let targetLanguages = supportedTypes[from], - targetLanguages.contains(to) || to == .traditionalChinese - else { - return .unsupported - } - - guard let from = supportLanguagesDictionary[from], - let to = supportLanguagesDictionary[to] - else { - return .unsupported - } - - return GeminiTranslateType(rawValue: "\(from)2\(to)") - } -} From 3163dcb3e1cbeaab8c6dc8f05b65adf9334efe4a Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:56:43 -0800 Subject: [PATCH 12/20] perf: change min version back to 11.0 --- Easydict.xcodeproj/project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../Service/Gemini/GeminiService.swift | 23 ++++++++++++++----- .../EZDeviceSystemInfo/EZDeviceSystemInfo.m | 2 +- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 49c60577c..20775b2a7 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -3198,7 +3198,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 2.5.0; PRODUCT_BUNDLE_IDENTIFIER = "com.izual.Easydict-debug"; PRODUCT_MODULE_NAME = Easydict; @@ -3238,7 +3238,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 2.5.0; PRODUCT_BUNDLE_IDENTIFIER = com.izual.Easydict; PRODUCT_MODULE_NAME = Easydict; diff --git a/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved index 85e3f87d5..6dda3d72c 100644 --- a/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -77,8 +77,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/generative-ai-swift", "state" : { - "revision" : "fead3038a70047a72ea2cf39e96d3add71c372de", - "version" : "0.4.4" + "revision" : "5cf2aae0f4d04b77fe7b2110da1145462ff92b84", + "version" : "0.4.6" } }, { diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index 3d9eb13e0..2c510b4fc 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -75,25 +75,36 @@ public final class GeminiService: QueryService { override public func translate(_ text: String, from: Language, to: Language, completion: @escaping (EZQueryResult, Error?) -> Void) { Task { - // https://github.com/google/generative-ai-swift do { var resultString = "" let prompt = GeminiService.translationPrompt + "Translate the following \(from.rawValue) text into \(to.rawValue): \(text)" print("gemini prompt: \(prompt)") let model = GenerativeModel(name: "gemini-pro", apiKey: apiKey) - let outputContentStream = model.generateContentStream(prompt) - // stream response - for try await outputContent in outputContentStream { + if #available(macOS 12.0, *) { + let outputContentStream = model.generateContentStream(prompt) + + // stream response + for try await outputContent in outputContentStream { + guard let line = outputContent.text else { + return + } + + print("gemini response: \(line)") + resultString += line + } + } else { + let outputContent = try await model.generateContent(prompt) guard let line = outputContent.text else { return } print("gemini response: \(line)") resultString += line - result.translatedResults = [resultString] - completion(result, nil) } + + result.translatedResults = [resultString] + completion(result, nil) } catch { print(error.localizedDescription) completion(result, error) diff --git a/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m b/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m index 148da924f..79e11eb56 100644 --- a/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m +++ b/Easydict/Feature/Utility/EZDeviceSystemInfo/EZDeviceSystemInfo.m @@ -57,7 +57,7 @@ + (NSString *)getDeviceModel { /// Get device UUID, 4F07896A-1580-5270-A0E8-D7FA9DFA6868 + (NSString *)getDeviceUUID { - io_service_t platformExpert = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPlatformExpertDevice")); + io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); CFStringRef uuidString = (CFStringRef)IORegistryEntryCreateCFProperty(platformExpert, CFSTR("IOPlatformUUID"), kCFAllocatorDefault, 0); NSString *uuid = (__bridge NSString *)(uuidString); IOObjectRelease(platformExpert); From 8f5e20f0622e919109c8e4bafb36d4e1745e1393 Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Tue, 9 Jan 2024 18:00:46 -0800 Subject: [PATCH 13/20] perf: resolve xcode warning Xcode Autofix --- Easydict/Feature/Service/Gemini/GeminiService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index 2c510b4fc..536834f0b 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -30,7 +30,7 @@ public final class GeminiService: QueryService { // TODO: Replace MMOrderedDictionary. let orderedDict = MMOrderedDictionary() for language in EZLanguageManager.shared().allLanguages { - var value = language.rawValue + let value = language.rawValue if !GeminiService.unsupportedLanguages.contains(language) { orderedDict.setObject(value as NSString, forKey: language.rawValue as NSString) } From eae5eefe58148a2e1626c3aefb911415a56ad254 Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Wed, 24 Jan 2024 11:50:25 -0800 Subject: [PATCH 14/20] perf: adjust gemini safety level https://github.com/tisfeng/Easydict/pull/297#issuecomment-1908144296 --- .../Feature/Service/Gemini/GeminiService.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index 536834f0b..dae887c58 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -67,6 +67,12 @@ public final class GeminiService: QueryService { } } + // Set Gemini safety level to BLOCK_NONE + private static let harassmentSafety = SafetySetting(harmCategory: .harassment, threshold: .blockNone) + private static let hateSpeechSafety = SafetySetting(harmCategory: .hateSpeech, threshold: .blockNone) + private static let sexuallyExplicitSafety = SafetySetting(harmCategory: .sexuallyExplicit, threshold: .blockNone) + private static let dangerousContentSafety = SafetySetting(harmCategory: .dangerousContent, threshold: .blockNone) + private static let translationPrompt = "You are a translation expert proficient in various languages that can only translate text and cannot interpret it. You are able to accurately understand the meaning of proper nouns, idioms, metaphors, allusions or other obscure words in sentences and translate them into appropriate words by combining the context and language environment. The result of the translation should be natural and fluent, you can only return the translated text, do not show additional information and notes." override public func autoConvertTraditionalChinese() -> Bool { @@ -79,7 +85,16 @@ public final class GeminiService: QueryService { var resultString = "" let prompt = GeminiService.translationPrompt + "Translate the following \(from.rawValue) text into \(to.rawValue): \(text)" print("gemini prompt: \(prompt)") - let model = GenerativeModel(name: "gemini-pro", apiKey: apiKey) + let model = GenerativeModel( + name: "gemini-pro", + apiKey: apiKey, + safetySettings: [ + GeminiService.harassmentSafety, + GeminiService.hateSpeechSafety, + GeminiService.sexuallyExplicitSafety, + GeminiService.dangerousContentSafety, + ] + ) if #available(macOS 12.0, *) { let outputContentStream = model.generateContentStream(prompt) From b0103bac1aaaac85d4e5bd881c62bc65aa60316c Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Wed, 24 Jan 2024 20:49:40 -0800 Subject: [PATCH 15/20] refractor: manual error handling --- Easydict/Feature/Service/Gemini/GeminiService.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index dae887c58..aa9386a91 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -121,8 +121,8 @@ public final class GeminiService: QueryService { result.translatedResults = [resultString] completion(result, nil) } catch { - print(error.localizedDescription) - completion(result, error) + let ezError = EZError(type: .API, description: nil, errorDataMessage: String(describing: error)) + completion(result, ezError) } } } From ac8a4ae5ac1154d0dd5a1c142d1b1006fd68d0f9 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 26 Jan 2024 00:30:14 +0800 Subject: [PATCH 16/20] perf: improve error message for Gemini --- Easydict.xcodeproj/project.pbxproj | 12 +++++++++ .../Service/Gemini/GeminiService.swift | 13 +++++++++- .../Extensions/String/String+Regex.swift | 26 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Easydict/NewApp/Utility/Extensions/String/String+Regex.swift diff --git a/Easydict.xcodeproj/project.pbxproj b/Easydict.xcodeproj/project.pbxproj index 1b991b984..5d2a48f3b 100644 --- a/Easydict.xcodeproj/project.pbxproj +++ b/Easydict.xcodeproj/project.pbxproj @@ -84,6 +84,7 @@ 03882F9029D95044005B5A52 /* ToastWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 03882F8829D95044005B5A52 /* ToastWindowController.xib */; }; 03882F9129D95044005B5A52 /* CTCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = 03882F8929D95044005B5A52 /* CTCommon.m */; }; 03882F9229D95044005B5A52 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 03882F8C29D95044005B5A52 /* Info.plist */; }; + 038A72402B62C0B9004995E3 /* String+Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038A723F2B62C0B9004995E3 /* String+Regex.swift */; }; 038EA1AA2B41169C008A6DD1 /* ZipArchive in Frameworks */ = {isa = PBXBuildFile; productRef = 038EA1A92B41169C008A6DD1 /* ZipArchive */; }; 038EA1AD2B41282F008A6DD1 /* MJExtension in Frameworks */ = {isa = PBXBuildFile; productRef = 038EA1AC2B41282F008A6DD1 /* MJExtension */; }; 0396D611292C932F006A11D9 /* EZSelectLanguageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0396D610292C932F006A11D9 /* EZSelectLanguageCell.m */; }; @@ -446,6 +447,7 @@ 03882F8A29D95044005B5A52 /* CTView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CTView.h; sourceTree = ""; }; 03882F8B29D95044005B5A52 /* CoolToast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoolToast.h; sourceTree = ""; }; 03882F8C29D95044005B5A52 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 038A723F2B62C0B9004995E3 /* String+Regex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Regex.swift"; sourceTree = ""; }; 0396D60F292C932F006A11D9 /* EZSelectLanguageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EZSelectLanguageCell.h; sourceTree = ""; }; 0396D610292C932F006A11D9 /* EZSelectLanguageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZSelectLanguageCell.m; sourceTree = ""; }; 0396D613292CC4C3006A11D9 /* EZLocalStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EZLocalStorage.h; sourceTree = ""; }; @@ -1200,6 +1202,14 @@ path = Kit; sourceTree = ""; }; + 038A723E2B62C07B004995E3 /* String */ = { + isa = PBXGroup; + children = ( + 038A723F2B62C0B9004995E3 /* String+Regex.swift */, + ); + path = String; + sourceTree = ""; + }; 0396D612292CBDFD006A11D9 /* Storage */ = { isa = PBXGroup; children = ( @@ -2260,6 +2270,7 @@ EA9943E62B534D7C00EE7B97 /* Extensions */ = { isa = PBXGroup; children = ( + 038A723E2B62C07B004995E3 /* String */, EAED41F02B54B1A60005FE0A /* QueryService+ConfigurableService */, EA9943E72B534D8900EE7B97 /* LanguageDetectOptimizeExtensions.swift */, EA9943ED2B5353AB00EE7B97 /* WindowTypeExtensions.swift */, @@ -2773,6 +2784,7 @@ C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */, 62A2D03F2A82967F007EEB01 /* EZBingRequest.m in Sources */, 03BDA7BE2A26DA280079D04F /* XPMCountedArgument.m in Sources */, + 038A72402B62C0B9004995E3 /* String+Regex.swift in Sources */, 03D35DAA2AA6C49B00B023FE /* NSString+EZRegex.m in Sources */, 03B022FE29231FA6001C7E63 /* EZBaseQueryViewController.m in Sources */, DC6D9C892B3969510055EFFC /* Appearance.swift in Sources */, diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index aa9386a91..b959b1550 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -121,7 +121,18 @@ public final class GeminiService: QueryService { result.translatedResults = [resultString] completion(result, nil) } catch { - let ezError = EZError(type: .API, description: nil, errorDataMessage: String(describing: error)) + /** + https://github.com/google/generative-ai-swift/issues/89 + + String(describing: error) + + "internalError(underlying: GoogleGenerativeAI.RPCError(httpResponseCode: 400, message: \"API key not valid. Please pass a valid API key.\", status: GoogleGenerativeAI.RPCStatus.invalidArgument))" + */ + let ezError = EZError(nsError: error) + let errorString = String(describing: error) + let errorMessage = errorString.extract(withPattern: "message: \"([^\"]*)\"") ?? errorString + ezError?.errorDataMessage = errorMessage + completion(result, ezError) } } diff --git a/Easydict/NewApp/Utility/Extensions/String/String+Regex.swift b/Easydict/NewApp/Utility/Extensions/String/String+Regex.swift new file mode 100644 index 000000000..0acccba89 --- /dev/null +++ b/Easydict/NewApp/Utility/Extensions/String/String+Regex.swift @@ -0,0 +1,26 @@ +// +// String+Regex.swift +// Easydict +// +// Created by tisfeng on 2024/1/26. +// Copyright © 2024 izual. All rights reserved. +// + +import Foundation + +extension String { + func extract(withPattern pattern: String) -> String? { + do { + let regex = try NSRegularExpression(pattern: pattern) + let range = NSRange(location: 0, length: utf16.count) + if let match = regex.firstMatch(in: self, options: [], range: range) { + if let range = Range(match.range(at: 1), in: self) { + return String(self[range]) + } + } + } catch { + print("Invalid regex: \(error.localizedDescription)") + } + return nil + } +} From fcc3b1111d7440a07deb9476566521ad379bd758 Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Thu, 25 Jan 2024 20:16:28 -0800 Subject: [PATCH 17/20] fix: content streaming on macOS 12+ --- Easydict/Feature/Service/Gemini/GeminiService.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index b959b1550..aaff7c7b8 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -107,7 +107,10 @@ public final class GeminiService: QueryService { print("gemini response: \(line)") resultString += line + result.translatedResults = [resultString] + completion(result, nil) } + } else { let outputContent = try await model.generateContent(prompt) guard let line = outputContent.text else { @@ -116,16 +119,15 @@ public final class GeminiService: QueryService { print("gemini response: \(line)") resultString += line + result.translatedResults = [resultString] + completion(result, nil) } - - result.translatedResults = [resultString] - completion(result, nil) } catch { /** https://github.com/google/generative-ai-swift/issues/89 - + String(describing: error) - + "internalError(underlying: GoogleGenerativeAI.RPCError(httpResponseCode: 400, message: \"API key not valid. Please pass a valid API key.\", status: GoogleGenerativeAI.RPCStatus.invalidArgument))" */ let ezError = EZError(nsError: error) From 20f79ea08d679baffb0da7473a74f4b70898f90d Mon Sep 17 00:00:00 2001 From: tisfeng Date: Fri, 26 Jan 2024 23:53:21 +0800 Subject: [PATCH 18/20] perf: improve code, remove logs --- Easydict/Feature/Service/Gemini/GeminiService.swift | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index aaff7c7b8..d8965e1c0 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -82,7 +82,6 @@ public final class GeminiService: QueryService { override public func translate(_ text: String, from: Language, to: Language, completion: @escaping (EZQueryResult, Error?) -> Void) { Task { do { - var resultString = "" let prompt = GeminiService.translationPrompt + "Translate the following \(from.rawValue) text into \(to.rawValue): \(text)" print("gemini prompt: \(prompt)") let model = GenerativeModel( @@ -97,6 +96,7 @@ public final class GeminiService: QueryService { ) if #available(macOS 12.0, *) { + var resultString = "" let outputContentStream = model.generateContentStream(prompt) // stream response @@ -105,7 +105,6 @@ public final class GeminiService: QueryService { return } - print("gemini response: \(line)") resultString += line result.translatedResults = [resultString] completion(result, nil) @@ -117,9 +116,7 @@ public final class GeminiService: QueryService { return } - print("gemini response: \(line)") - resultString += line - result.translatedResults = [resultString] + result.translatedResults = [line] completion(result, nil) } } catch { From cef098e342fd1301d5500c170222eb0d46deea00 Mon Sep 17 00:00:00 2001 From: Jerry <89069957+Jerry23011@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:46:16 -0800 Subject: [PATCH 19/20] perf: update generative-ai-swift to 0.4.7 --- Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6dda3d72c..3c8f58191 100644 --- a/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Easydict.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -77,8 +77,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/google/generative-ai-swift", "state" : { - "revision" : "5cf2aae0f4d04b77fe7b2110da1145462ff92b84", - "version" : "0.4.6" + "revision" : "dcbdb5e591e1aa2bb68851dc7515f6b0a59026cd", + "version" : "0.4.7" } }, { From 60446904df433f0abed2b082f7d9e02904c2575b Mon Sep 17 00:00:00 2001 From: tisfeng Date: Sat, 27 Jan 2024 10:51:29 +0800 Subject: [PATCH 20/20] perf: rename variable --- Easydict/Feature/Service/Gemini/GeminiService.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Easydict/Feature/Service/Gemini/GeminiService.swift b/Easydict/Feature/Service/Gemini/GeminiService.swift index d8965e1c0..6df5cfcff 100644 --- a/Easydict/Feature/Service/Gemini/GeminiService.swift +++ b/Easydict/Feature/Service/Gemini/GeminiService.swift @@ -112,11 +112,11 @@ public final class GeminiService: QueryService { } else { let outputContent = try await model.generateContent(prompt) - guard let line = outputContent.text else { + guard let resultString = outputContent.text else { return } - result.translatedResults = [line] + result.translatedResults = [resultString] completion(result, nil) } } catch {