Skip to content

Commit

Permalink
feat: initiate support for Google Gemini
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerry23011 committed Jan 3, 2024
1 parent aa0b60d commit 788d370
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Easydict.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,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 */; };
Expand Down Expand Up @@ -728,6 +730,8 @@
9672D7D02B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MASShortcutBinder+EZMASShortcutBinder.h"; sourceTree = "<group>"; };
9672D7D12B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MASShortcutBinder+EZMASShortcutBinder.m"; sourceTree = "<group>"; };
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 = "<group>"; };
C415C0AC2B450D4800A9D231 /* GeminiService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiService.swift; sourceTree = "<group>"; };
C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GeminiTranslateType.swift; path = ../../../../../../../GeminiTranslateType.swift; sourceTree = "<group>"; };
C4DD01E82B12B3C80025EE8E /* TencentService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentService.swift; sourceTree = "<group>"; };
C4DD01EA2B12BA250025EE8E /* TencentResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentResponse.swift; sourceTree = "<group>"; };
C4DD01EC2B12BE9B0025EE8E /* TencentTranslateType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TencentTranslateType.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1276,6 +1280,7 @@
isa = PBXGroup;
children = (
62E2BF462B4082BA00E42D38 /* Ali */,
C415C0AB2B450C4500A9D231 /* Gemini */,
17BCAEF22B0DFF9000A7D372 /* Niutrans */,
2746AEBF2AF95040005FE0A1 /* Caiyun */,
C4DD01E72B12B3B00025EE8E /* Tencent */,
Expand Down Expand Up @@ -2090,6 +2095,15 @@
path = Pods;
sourceTree = "<group>";
};
C415C0AB2B450C4500A9D231 /* Gemini */ = {
isa = PBXGroup;
children = (
C415C0AC2B450D4800A9D231 /* GeminiService.swift */,
C415C0AE2B450F9200A9D231 /* GeminiTranslateType.swift */,
);
path = Gemini;
sourceTree = "<group>";
};
C4A40A9B2AC0168400B8E6EF /* Recovered References */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2536,6 +2550,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 */,
Expand Down Expand Up @@ -2610,6 +2625,7 @@
039CC90D292F664E0037B91E /* NSObject+EZWindowType.m in Sources */,
03B0232229231FA6001C7E63 /* NSImage+MM.m in Sources */,
03BB2DEF29F59C8A00447EDD /* EZSymbolImageButton.m in Sources */,
C415C0AD2B450D4800A9D231 /* GeminiService.swift in Sources */,
62A2D03F2A82967F007EEB01 /* EZBingRequest.m in Sources */,
03BDA7BE2A26DA280079D04F /* XPMCountedArgument.m in Sources */,
03D35DAA2AA6C49B00B023FE /* NSString+EZRegex.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions Easydict/App/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,23 @@
}
}
},
"gemini_translate" : {
"comment" : "The name of Gemini Translate",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Gemini Translate"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Gemini 翻译"
}
}
}
},
"GitHub:" : {
"localizations" : {
"zh-Hans" : {
Expand Down
94 changes: 94 additions & 0 deletions Easydict/Feature/Service/Gemini/GeminiService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//
// GeminiService.swift
// Easydict
//
// Created by Jerry on 2024-01-02.
// Copyright © 2024 izual. All rights reserved.
//

import Foundation
import GoogleGenerativeAI

@objc(EZGeminiService)
public final class GeminiService: QueryService {
override public func serviceType() -> 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<AnyObject, AnyObject> {
// TODO: Replace MMOrderedDictionary.
let orderedDict = MMOrderedDictionary<AnyObject, AnyObject>()
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)
}
}
}
}
1 change: 1 addition & 0 deletions Easydict/Feature/Service/Model/EZConstKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions Easydict/Feature/Service/Model/EZEnumTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions Easydict/Feature/Service/Model/EZEnumTypes.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
NSString *const EZServiceTypeCaiyun = @"Caiyun";
NSString *const EZServiceTypeTencent = @"Tencent";
NSString *const EZServiceTypeAli = @"Alibaba";
NSString *const EZServiceTypeGemini = @"Gemini";

NSString *const EZServiceTypeAppleDictionary = @"AppleDictionary";

Expand Down
1 change: 1 addition & 0 deletions Easydict/Feature/Service/Model/EZServiceTypes.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ + (instancetype)allocWithZone:(struct _NSZone *)zone {
EZServiceTypeCaiyun, [EZCaiyunService class],
EZServiceTypeTencent, [EZTencentService class],
EZServiceTypeAli, [EZAliService class],
EZServiceTypeGemini, [EZGeminiService class],
nil];
return allServiceDict;
}
Expand Down
1 change: 1 addition & 0 deletions Easydict/Feature/Utility/EZLinkParser/EZSchemeParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ - (NSArray *)allowedReadWriteKeys {

EZAliAccessKeyId,
EZAliAccessKeySecret,
EZGeminiAPIKey,

EZIntelligentQueryModeKey,
];
Expand Down

0 comments on commit 788d370

Please sign in to comment.