Browse Source

AI - 补充ToolBar按钮翻译当前开启文档

wanjun 1 year ago
parent
commit
ce63ce1337

+ 16 - 0
PDF Office/PDF Master.xcodeproj/project.pbxproj

@@ -432,6 +432,12 @@
 		9F0201912A1DDAA500C9B673 /* KMAITranslationWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F02018D2A1DDAA500C9B673 /* KMAITranslationWindowController.xib */; };
 		9F0201922A1DDAA500C9B673 /* KMAITranslationWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F02018D2A1DDAA500C9B673 /* KMAITranslationWindowController.xib */; };
 		9F0201932A1DDAA500C9B673 /* KMAITranslationWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F02018D2A1DDAA500C9B673 /* KMAITranslationWindowController.xib */; };
+		9F0201962A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F0201942A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift */; };
+		9F0201972A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F0201942A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift */; };
+		9F0201982A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F0201942A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift */; };
+		9F0201992A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F0201952A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib */; };
+		9F02019A2A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F0201952A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib */; };
+		9F02019B2A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9F0201952A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib */; };
 		9F080B0F298A55A300FC27DA /* KMConvertURLToPDF.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F080B0D298A55A300FC27DA /* KMConvertURLToPDF.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
 		9F080B10298A55A300FC27DA /* KMConvertURLToPDF.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F080B0D298A55A300FC27DA /* KMConvertURLToPDF.m */; };
 		9F080B11298A55A300FC27DA /* KMConvertURLToPDF.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F080B0D298A55A300FC27DA /* KMConvertURLToPDF.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
@@ -3483,6 +3489,8 @@
 		9F0201852A1DA28B00C9B673 /* KMAILanguagePopVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMAILanguagePopVC.xib; sourceTree = "<group>"; };
 		9F02018C2A1DDAA500C9B673 /* KMAITranslationWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMAITranslationWindowController.swift; sourceTree = "<group>"; };
 		9F02018D2A1DDAA500C9B673 /* KMAITranslationWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMAITranslationWindowController.xib; sourceTree = "<group>"; };
+		9F0201942A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMAITranslationConfirmWindowController.swift; sourceTree = "<group>"; };
+		9F0201952A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMAITranslationConfirmWindowController.xib; sourceTree = "<group>"; };
 		9F080B0D298A55A300FC27DA /* KMConvertURLToPDF.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KMConvertURLToPDF.m; sourceTree = "<group>"; };
 		9F080B0E298A55A300FC27DA /* KMConvertURLToPDF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KMConvertURLToPDF.h; sourceTree = "<group>"; };
 		9F080B12298CFDB300FC27DA /* KMTextImageButtonVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMTextImageButtonVC.swift; sourceTree = "<group>"; };
@@ -5562,6 +5570,8 @@
 				9FD0FA4A29D43D6800F2AB0D /* KMDeviceBrowserWindowController.xib */,
 				9F02018C2A1DDAA500C9B673 /* KMAITranslationWindowController.swift */,
 				9F02018D2A1DDAA500C9B673 /* KMAITranslationWindowController.xib */,
+				9F0201942A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift */,
+				9F0201952A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib */,
 			);
 			path = WindowController;
 			sourceTree = "<group>";
@@ -9076,6 +9086,7 @@
 				9FF94F1429A7476000B1EF69 /* KMDesignPropertySelector.xib in Resources */,
 				BBC348462956A638008D2CD1 /* KMEditBackgroundController.xib in Resources */,
 				BBA2109429ACC10F00E6B346 /* signlist_add.pdf in Resources */,
+				9F0201992A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib in Resources */,
 				BB89721B294AED6C0045787C /* KMWatermarkAdjectivePreViewBaseController.xib in Resources */,
 				89E4E72F2963FBA2002DBA6F /* KMPropertiesViewPopController.xib in Resources */,
 				9F8539E32947126000DF644E /* KMChromiumToolbar.xib in Resources */,
@@ -9508,6 +9519,7 @@
 				8942F7FC2926089200389627 /* KMSignatureViewController.xib in Resources */,
 				BB98080129CA93D400BEEB81 /* WelcomeWindowController.xib in Resources */,
 				9F080B18298CFDB300FC27DA /* KMTextImageButtonVC.xib in Resources */,
+				9F02019A2A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib in Resources */,
 				BBFE6E832930EBD400142C01 /* KMCompressWindowController.xib in Resources */,
 				9F0CB46B2967E5CB00007028 /* KMPropertiesPanelSubViewController.xib in Resources */,
 				AD68783929A60FC0005B5210 /* KMLoginView.xib in Resources */,
@@ -9666,6 +9678,7 @@
 				ADC075C629866B05006C752F /* KMBatchTextRecognitionView.xib in Resources */,
 				AD8810B729A846B100178CA1 /* KMVerficationCodeWindowController.xib in Resources */,
 				BBC348192955920B008D2CD1 /* KMBackgroundPropertyController.xib in Resources */,
+				9F02019B2A1F352100C9B673 /* KMAITranslationConfirmWindowController.xib in Resources */,
 				BB98080229CA93D400BEEB81 /* WelcomeWindowController.xib in Resources */,
 				89E4E76629656A88002DBA6F /* KMAnnotationStampViewController.xib in Resources */,
 				899700E428F3A9F2009AF911 /* KMHomeWindowController.xib in Resources */,
@@ -10641,6 +10654,7 @@
 				8997010E28F40842009AF911 /* KMOutlineViewController.swift in Sources */,
 				BB2F61502966A91D001CB369 /* KMBackgroundPropertyHomeController.swift in Sources */,
 				9F1FE3DE293EE51F00E952CA /* KMMainDocument.swift in Sources */,
+				9F0201962A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */,
 				BBB9B31F299A5D6D004F3235 /* KMGoogleDriveManager.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -11002,6 +11016,7 @@
 				9F0201732A1B488C00C9B673 /* KMAITranslationVC.swift in Sources */,
 				BBFBE74728DD7DB7008B2335 /* ViewController.swift in Sources */,
 				9FDD0F812952FC36000C4DAD /* KMDesignToken.swift in Sources */,
+				9F0201972A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */,
 				BB147036299DC0D200784A6A /* OIDRegistrationResponse.m in Sources */,
 				BB86C21A28F561C7005AD968 /* NSColor_SKExtensions.m in Sources */,
 				9FDD0F8D2952FCE0000C4DAD /* KMGlobalParser.swift in Sources */,
@@ -11488,6 +11503,7 @@
 				9F1FE4B629406E4700E952CA /* CTBrowser.m in Sources */,
 				BBA19F4529ADE6A3001A285A /* KMBookMarkRowView.swift in Sources */,
 				ADE614A52977952C00F62ED7 /* KMBatchConvertPDFViewModel.swift in Sources */,
+				9F0201982A1F352100C9B673 /* KMAITranslationConfirmWindowController.swift in Sources */,
 				9FDD0FAC29534FCC000C4DAD /* KMAliasLight.swift in Sources */,
 				BBF38A64294F53FD0086D025 /* KMWatermarkFileView.swift in Sources */,
 				899700F828F4051B009AF911 /* KMAnnotationViewController.swift in Sources */,

+ 12 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/Home/ic_function_other_AITranslation.imageset/Contents.json

@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "filename" : "other.pdf",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

File diff suppressed because it is too large
+ 2393 - 0
PDF Office/PDF Master/Class/Appearance/Image.xcassets/Home/ic_function_other_AITranslation.imageset/other.pdf


+ 230 - 0
PDF Office/PDF Master/Class/Home/WindowController/KMAITranslationConfirmWindowController.swift

@@ -0,0 +1,230 @@
+//
+//  KMAITranslationConfirmWindowController.swift
+//  PDF Master
+//
+//  Created by wanjun on 2023/5/25.
+//
+
+import Cocoa
+
+class KMAITranslationConfirmWindowController: NSWindowController {
+
+    @IBOutlet weak var label: NSTextField!
+    @IBOutlet weak var subLabel: NSTextField!
+    @IBOutlet weak var cancelBox: NSBox!
+    @IBOutlet weak var cancelLabel: NSTextField!
+    @IBOutlet weak var cancelButton: NSButton!
+    @IBOutlet weak var translateBox: NSBox!
+    @IBOutlet weak var translateLabel: NSTextField!
+    @IBOutlet weak var translateButton: NSButton!
+    
+    var filePath: String = ""
+    var progressController: SKProgressController?
+
+    override func windowDidLoad() {
+        super.windowDidLoad()
+
+        self.initLocalization()
+        self.initializeUI()
+    }
+    
+    func initializeUI() -> Void {
+        self.label.textColor = NSColor(hex: "#4D4D4D")
+        self.label.font = NSFont.SFProTextSemibold(13.0)
+        self.subLabel.textColor = NSColor(hex: "##4D4D4D")
+        self.subLabel.font = NSFont.SFProTextRegular(11.0)
+        self.cancelBox.fillColor = NSColor(hex: "#F5F5F5")
+        self.cancelBox.cornerRadius = 5.0
+        self.cancelBox.borderWidth = 0.0
+        self.cancelLabel.textColor = NSColor(hex: "#4D4D4D")
+        self.cancelLabel.font = NSFont.SFProTextRegular(13.0)
+        self.translateBox.fillColor = NSColor(hex: "#4B91F7")
+        self.translateBox.cornerRadius = 5.0
+        self.translateBox.borderWidth = 0.0
+        self.translateLabel.textColor = NSColor(hex: "#FFFFFF")
+        self.translateLabel.font = NSFont.SFProTextRegular(13.0)
+    }
+    
+    func initLocalization() -> Void {
+        self.label.stringValue = NSLocalizedString("AI Translation", comment: "")
+        self.subLabel.stringValue = NSLocalizedString("Intelligent translation of the currently open document, the translated file will be opened as a new file.", comment: "")
+        self.cancelLabel.stringValue = NSLocalizedString("Cancel", comment: "")
+        self.translateLabel.stringValue = NSLocalizedString("Translate", comment: "")
+    }
+    
+    // MARK: Private Methods
+    
+    
+
+    // MARK: Action Methods
+
+    @IBAction func translateAction(_ sender: NSButton) {
+        if !KMLightMemberManager.manager.isLogin() {
+            KMLoginWindowController.show(window: NSApp.mainWindow!)
+            return
+        }
+        
+        DispatchQueue.main.async {
+            self.showProgressWindow()
+        }
+        
+        let infoDictionary = Bundle .main.infoDictionary!
+        let majorVersion = infoDictionary["CFBundleShortVersionString"]
+
+        KMRequestServerManager.manager.aiTranslationFileUpload(file: self.filePath, version: "1.0.1") { [unowned self] success, result in
+            if success {
+                let result: NSDictionary = result!.result
+
+                let fileKey = result["fileKey"]
+                let fileName = result["fileName"]
+                let pageCount = result["pageCount"]
+                if fileKey != nil {
+                    self.fileTranslateHandle(fileKey as! String)
+                }
+            } else {
+                let result: String = result!.message
+
+                DispatchQueue.main.async {
+                    self.hiddenProgressWindow()
+ 
+                    let alert = NSAlert()
+                    alert.alertStyle = .critical
+                    alert.messageText = result
+                    alert.runModal()
+                }
+            }
+        }
+    }
+    
+    @IBAction func cancelAction(_ sender: NSButton) {
+        NSApp.mainWindow!.endSheet(self.window!)
+        self.window?.orderOut(self)
+    }
+    
+    // MARK: Private Methods
+
+    func showProgressWindow() {
+        let progress = SKProgressController()
+        progress.message = NSLocalizedString("translation...", comment: "")
+        progress.window?.backgroundColor = NSColor(hex: "#36383B")
+        progress.window?.contentView?.wantsLayer = true
+        progress.window?.contentView?.layer?.backgroundColor = NSColor(hex: "#36383B").cgColor
+        progress.progressField.textColor = NSColor.white
+        
+        progress.closeBlock = { [unowned self] in
+            
+        }
+        
+        self.progressController = progress
+        self.window?.beginSheet(progress.window!)
+    }
+    
+    func hiddenProgressWindow() {
+        if (self.progressController != nil) {
+            self.window?.endSheet((self.progressController?.window)!)
+            self.progressController = nil
+        }
+    }
+    
+    func fileTranslateHandle(_ fileKey: String) -> Void {
+        let infoDictionary = Bundle .main.infoDictionary!
+        let majorVersion = infoDictionary["CFBundleShortVersionString"]
+
+        KMRequestServerManager.manager.aiTranslationFileTranslateHandle(fileKey: fileKey, from: "auto", to: "en", version: "1.0.1") { success, result in
+            if success {
+                let result: NSDictionary = result!.result
+
+                let fileUrl: String = result["fileUrl"] as! String
+                let downFileUrl: String = result["downFileUrl"] as! String
+                let ossDownUrl: String = result["ossDownUrl"] as! String
+                let fileName: String = result["fileName"] as! String
+                let downFileName: String = result["downFileName"] as! String
+                let from: String = result["from"] as! String
+                let to: String = result["to"] as! String
+                
+                self.downloadFile(filePath: ossDownUrl, downFileName: downFileName)
+            } else {
+                let result: String = result!.message
+
+                DispatchQueue.main.async {
+                    self.hiddenProgressWindow()
+                    
+                    let alert = NSAlert()
+                    alert.alertStyle = .critical
+                    alert.messageText = result
+                    alert.runModal()
+                }
+            }
+        }
+    }
+    
+    func downloadFile(filePath: String, downFileName: String) -> Void {
+        guard let fileURL = URL(string: filePath) else {
+            let alert = NSAlert()
+            alert.alertStyle = .critical
+            alert.messageText = NSLocalizedString("Invalid file link", comment: "")
+            alert.runModal()
+
+            return
+        }
+        
+        let fileNameWithoutExtension = fileURL.deletingPathExtension().lastPathComponent
+        let fileExtension = fileURL.pathExtension
+        let newFileName = fileNameWithoutExtension + "_aiTranslation" + "." + fileExtension
+        let newDestinationURL = fileURL.deletingLastPathComponent().appendingPathComponent(newFileName)
+        
+        let destinationURL = newDestinationURL
+        if FileManager.default.fileExists(atPath: destinationURL.path) {
+            do {
+                try FileManager.default.removeItem(at: destinationURL)
+                print("删除旧文件成功")
+            } catch {
+                print("删除旧文件失败:\(error)")
+            }
+        }
+        let sessionConfiguration = URLSessionConfiguration.default
+        let session = URLSession(configuration: sessionConfiguration)
+        let downloadTask = session.downloadTask(with: fileURL) { (tempLocalURL, response, error) in
+            if let error = error {
+                let alert = NSAlert()
+                alert.alertStyle = .critical
+                alert.messageText = String(format: "%@:\(error)", NSLocalizedString("Download failure", comment: ""))
+                alert.runModal()
+                
+                return
+            }
+
+            guard let tempLocalURL = tempLocalURL else {
+                let alert = NSAlert()
+                alert.alertStyle = .critical
+                alert.messageText = NSLocalizedString("The download file temporary path is invalid", comment: "")
+                alert.runModal()
+
+                return
+            }
+            
+            DispatchQueue.main.async {
+                self.hiddenProgressWindow()
+            }
+            
+            do {
+                try FileManager.default.moveItem(at: tempLocalURL, to: destinationURL)
+
+                NSDocumentController.shared.openDocument(withContentsOf: destinationURL, display: true) { document, documentWasAlreadyOpen, error in
+                    if error != nil {
+                        NSApp.presentError(error!)
+                    } else {
+                        
+                    }
+                }
+            } catch {
+                let alert = NSAlert()
+                alert.alertStyle = .critical
+                alert.messageText = String(format: "%@:\(error)", NSLocalizedString("File saving failure", comment: ""))
+                alert.runModal()
+            }
+        }
+        downloadTask.resume()
+    }
+
+}

+ 183 - 0
PDF Office/PDF Master/Class/Home/WindowController/KMAITranslationConfirmWindowController.xib

@@ -0,0 +1,183 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner" customClass="KMAITranslationConfirmWindowController" customModule="PDF_Master" customModuleProvider="target">
+            <connections>
+                <outlet property="cancelBox" destination="vyK-GF-45b" id="SmK-bv-L3Z"/>
+                <outlet property="cancelButton" destination="cGZ-Im-IxK" id="rmV-MT-RM5"/>
+                <outlet property="cancelLabel" destination="deL-QF-z0s" id="eA4-QB-zXm"/>
+                <outlet property="label" destination="sgz-NY-FUz" id="SEK-zO-T8W"/>
+                <outlet property="subLabel" destination="GiQ-wT-5ua" id="gGd-EG-0RC"/>
+                <outlet property="translateBox" destination="mxT-Tw-rlp" id="Jh5-hM-0hL"/>
+                <outlet property="translateButton" destination="3Am-My-14a" id="Gzf-c0-bSh"/>
+                <outlet property="translateLabel" destination="nFO-mt-ZB4" id="gmM-Ju-YLy"/>
+                <outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
+            </connections>
+        </customObject>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="F0z-JX-Cv5">
+            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
+            <rect key="contentRect" x="196" y="240" width="480" height="270"/>
+            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1415"/>
+            <view key="contentView" id="se5-gp-TjO">
+                <rect key="frame" x="0.0" y="0.0" width="260" height="206"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="sgz-NY-FUz">
+                        <rect key="frame" x="14" y="86" width="232" height="16"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="228" id="hN5-mW-iTm"/>
+                        </constraints>
+                        <textFieldCell key="cell" alignment="center" title="Label" id="zzD-u1-CIR">
+                            <font key="font" usesAppearanceFont="YES"/>
+                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kuS-aO-ayK">
+                        <rect key="frame" x="98" y="122" width="64" height="64"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="64" id="e9X-XE-pCa"/>
+                            <constraint firstAttribute="height" constant="64" id="fsU-zz-eih"/>
+                        </constraints>
+                        <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="KMimageAppIcon" id="cz6-ID-DI3"/>
+                    </imageView>
+                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GiQ-wT-5ua">
+                        <rect key="frame" x="14" y="60" width="232" height="16"/>
+                        <textFieldCell key="cell" alignment="center" title="Label" id="fAf-ym-cnT">
+                            <font key="font" metaFont="system"/>
+                            <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                        </textFieldCell>
+                    </textField>
+                    <box boxType="custom" borderWidth="0.0" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="zwE-aA-0ce">
+                        <rect key="frame" x="16" y="16" width="228" height="28"/>
+                        <view key="contentView" id="11a-a7-FcD">
+                            <rect key="frame" x="0.0" y="0.0" width="228" height="28"/>
+                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            <subviews>
+                                <box boxType="custom" cornerRadius="5" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="vyK-GF-45b">
+                                    <rect key="frame" x="0.0" y="0.0" width="110" height="28"/>
+                                    <view key="contentView" id="XSf-Em-cr2">
+                                        <rect key="frame" x="1" y="1" width="108" height="26"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="deL-QF-z0s">
+                                                <rect key="frame" x="36" y="5" width="37" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="FIx-7a-CCI">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="cGZ-Im-IxK">
+                                                <rect key="frame" x="0.0" y="0.0" width="108" height="26"/>
+                                                <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="mp1-Jt-tKe">
+                                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                    <font key="font" metaFont="system"/>
+                                                </buttonCell>
+                                                <connections>
+                                                    <action selector="cancelAction:" target="-2" id="LCk-7o-yve"/>
+                                                </connections>
+                                            </button>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstAttribute="trailing" secondItem="cGZ-Im-IxK" secondAttribute="trailing" id="3wu-YM-dAg"/>
+                                            <constraint firstItem="deL-QF-z0s" firstAttribute="centerY" secondItem="XSf-Em-cr2" secondAttribute="centerY" id="4t3-q9-nio"/>
+                                            <constraint firstAttribute="bottom" secondItem="cGZ-Im-IxK" secondAttribute="bottom" id="8ZJ-B7-GY3"/>
+                                            <constraint firstItem="cGZ-Im-IxK" firstAttribute="top" secondItem="XSf-Em-cr2" secondAttribute="top" id="RrO-O9-QeA"/>
+                                            <constraint firstItem="cGZ-Im-IxK" firstAttribute="leading" secondItem="XSf-Em-cr2" secondAttribute="leading" id="d8c-36-nkZ"/>
+                                            <constraint firstItem="deL-QF-z0s" firstAttribute="centerX" secondItem="XSf-Em-cr2" secondAttribute="centerX" id="jvx-ko-4Wn"/>
+                                        </constraints>
+                                    </view>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="110" id="TY4-G0-aVa"/>
+                                    </constraints>
+                                    <color key="fillColor" red="0.92156862750000001" green="0.92156862750000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                </box>
+                                <box boxType="custom" cornerRadius="5" title="Box" translatesAutoresizingMaskIntoConstraints="NO" id="mxT-Tw-rlp">
+                                    <rect key="frame" x="118" y="0.0" width="110" height="28"/>
+                                    <view key="contentView" id="5yL-5z-83R">
+                                        <rect key="frame" x="1" y="1" width="108" height="26"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <subviews>
+                                            <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nFO-mt-ZB4">
+                                                <rect key="frame" x="36" y="5" width="37" height="16"/>
+                                                <textFieldCell key="cell" lineBreakMode="clipping" title="Label" id="UTP-2e-VlX">
+                                                    <font key="font" usesAppearanceFont="YES"/>
+                                                    <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                                                    <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                </textFieldCell>
+                                            </textField>
+                                            <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="3Am-My-14a">
+                                                <rect key="frame" x="0.0" y="0.0" width="108" height="26"/>
+                                                <buttonCell key="cell" type="bevel" bezelStyle="rounded" alignment="center" imageScaling="proportionallyDown" inset="2" id="Fkj-HH-Ela">
+                                                    <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                                    <font key="font" metaFont="system"/>
+                                                </buttonCell>
+                                                <connections>
+                                                    <action selector="translateAction:" target="-2" id="6uA-Vn-Eq3"/>
+                                                </connections>
+                                            </button>
+                                        </subviews>
+                                        <constraints>
+                                            <constraint firstItem="nFO-mt-ZB4" firstAttribute="centerY" secondItem="5yL-5z-83R" secondAttribute="centerY" id="0ZN-RX-fTY"/>
+                                            <constraint firstItem="3Am-My-14a" firstAttribute="top" secondItem="5yL-5z-83R" secondAttribute="top" id="1Ly-FI-FtW"/>
+                                            <constraint firstItem="3Am-My-14a" firstAttribute="leading" secondItem="5yL-5z-83R" secondAttribute="leading" id="CUV-Lr-tG5"/>
+                                            <constraint firstAttribute="bottom" secondItem="3Am-My-14a" secondAttribute="bottom" id="S46-iY-pqT"/>
+                                            <constraint firstItem="nFO-mt-ZB4" firstAttribute="centerX" secondItem="5yL-5z-83R" secondAttribute="centerX" id="Yvu-BP-umJ"/>
+                                            <constraint firstAttribute="trailing" secondItem="3Am-My-14a" secondAttribute="trailing" id="yFX-3N-teC"/>
+                                        </constraints>
+                                    </view>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="28" id="r0S-8M-b5L"/>
+                                    </constraints>
+                                    <color key="fillColor" red="0.92156862750000001" green="0.92156862750000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                </box>
+                            </subviews>
+                            <constraints>
+                                <constraint firstItem="mxT-Tw-rlp" firstAttribute="leading" secondItem="vyK-GF-45b" secondAttribute="trailing" constant="8" id="2zX-i0-5Pl"/>
+                                <constraint firstItem="mxT-Tw-rlp" firstAttribute="top" secondItem="11a-a7-FcD" secondAttribute="top" id="4Ku-SF-lJy"/>
+                                <constraint firstItem="mxT-Tw-rlp" firstAttribute="width" secondItem="vyK-GF-45b" secondAttribute="width" id="AuU-eU-f7L"/>
+                                <constraint firstItem="vyK-GF-45b" firstAttribute="top" secondItem="11a-a7-FcD" secondAttribute="top" id="Fmj-o2-C5j"/>
+                                <constraint firstAttribute="bottom" secondItem="vyK-GF-45b" secondAttribute="bottom" id="M5z-xX-014"/>
+                                <constraint firstItem="mxT-Tw-rlp" firstAttribute="height" secondItem="vyK-GF-45b" secondAttribute="height" id="cV1-EH-k3m"/>
+                                <constraint firstAttribute="bottom" secondItem="mxT-Tw-rlp" secondAttribute="bottom" id="cke-B4-boT"/>
+                                <constraint firstAttribute="trailing" secondItem="mxT-Tw-rlp" secondAttribute="trailing" id="sBz-LK-0mB"/>
+                                <constraint firstItem="vyK-GF-45b" firstAttribute="leading" secondItem="11a-a7-FcD" secondAttribute="leading" id="zfg-bG-f0W"/>
+                            </constraints>
+                        </view>
+                    </box>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="trailing" secondItem="GiQ-wT-5ua" secondAttribute="trailing" constant="16" id="7Je-TW-Rhc"/>
+                    <constraint firstAttribute="bottom" secondItem="zwE-aA-0ce" secondAttribute="bottom" constant="16" id="87a-u4-6V6"/>
+                    <constraint firstItem="kuS-aO-ayK" firstAttribute="centerX" secondItem="se5-gp-TjO" secondAttribute="centerX" id="F5c-Xa-6dQ"/>
+                    <constraint firstItem="zwE-aA-0ce" firstAttribute="top" secondItem="GiQ-wT-5ua" secondAttribute="bottom" constant="16" id="GTd-Xb-oMN"/>
+                    <constraint firstItem="kuS-aO-ayK" firstAttribute="centerX" secondItem="sgz-NY-FUz" secondAttribute="centerX" id="GjF-sI-wjz"/>
+                    <constraint firstAttribute="trailing" secondItem="sgz-NY-FUz" secondAttribute="trailing" constant="16" id="Hel-rI-MQ8"/>
+                    <constraint firstAttribute="trailing" secondItem="zwE-aA-0ce" secondAttribute="trailing" constant="16" id="Jys-Ms-lYK"/>
+                    <constraint firstItem="GiQ-wT-5ua" firstAttribute="top" secondItem="sgz-NY-FUz" secondAttribute="bottom" constant="10" id="Mlm-je-6cK"/>
+                    <constraint firstItem="sgz-NY-FUz" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="16" id="bqe-Ul-XFt"/>
+                    <constraint firstItem="kuS-aO-ayK" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="20" id="eph-jI-Hp8"/>
+                    <constraint firstItem="sgz-NY-FUz" firstAttribute="top" secondItem="kuS-aO-ayK" secondAttribute="bottom" constant="20" id="kWa-5S-CFo"/>
+                    <constraint firstItem="GiQ-wT-5ua" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="16" id="vlg-ep-wCG"/>
+                    <constraint firstItem="zwE-aA-0ce" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="16" id="ycW-xd-coP"/>
+                </constraints>
+            </view>
+            <connections>
+                <outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
+            </connections>
+            <point key="canvasLocation" x="139" y="144"/>
+        </window>
+    </objects>
+    <resources>
+        <image name="KMimageAppIcon" width="1024" height="1024"/>
+    </resources>
+</document>

+ 5 - 0
PDF Office/PDF Master/Class/PDFWindowController/Toolbar/KMToolbarController.swift

@@ -18,6 +18,7 @@ import Cocoa
     @objc optional func changePDFViewGotoNextPageAction()
     @objc optional func changePDFViewGoToPreviousPageAction()
     @objc optional func showPDFViewPrintViewController()
+    @objc optional func aiTranslationPDFFileAction()
     @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, zoomModel selectedTag:Int)
     @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, zoomSting : String)
     @objc optional func mainToolDidClicked(_ toolController: KMToolbarController, _ type: KMToolbarViewType, _ item: KMToolBoxItem, _ pages: [Int])
@@ -623,6 +624,10 @@ extension KMToolbarController: KMToolbarViewControllerDelegate {
         self.delegate?.showPDFViewPrintViewController?()
     }
     
+    func aiTranslationPDFFileAction() {
+        self.delegate?.aiTranslationPDFFileAction?()
+    }
+    
     func toolbarViewController(_ viewController: KMToolbarViewController, shareDocument item: NSMenuItem) {
         self.delegate?.toolbarViewController?(viewController, shareDocument: item)
     }

+ 19 - 1
PDF Office/PDF Master/Class/PDFWindowController/Toolbar/KMToolbarViewController.swift

@@ -95,6 +95,7 @@ import Cocoa
     @objc optional func changePDFViewGotoNextPageAction()
     @objc optional func changePDFViewGoToPreviousPageAction()
     @objc optional func showPDFViewPrintViewController()
+    @objc optional func aiTranslationPDFFileAction()
     @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, zoomSting : String)
     @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, zoomModel selectedTag:Int)
     @objc optional func toolbarViewController(_ viewController:KMToolbarViewController, shareDocument item:NSMenuItem)
@@ -278,6 +279,10 @@ class KMToolbarViewController: NSViewController, NSTextFieldDelegate {
         self.delegate?.showPDFViewPrintViewController?()
     }
     
+    @IBAction func aiTranslationButtonAction(sender:KMToolbarClickButton) {
+        self.delegate?.aiTranslationPDFFileAction?()
+    }
+    
     @IBAction func shareButtonAction(sender:KMToolbarClickButton) {
         self.shareButton = sender
         let menu = NSMenu()
@@ -367,7 +372,8 @@ extension KMToolbarViewController : KMNewToolbarDelegate,NSToolbarItemValidation
     
     func toolbarRightDefaultItemIdentifiers(_ toolbar: KMToolbar!) -> [String]! {
         if toolbarType == .Main {
-            return [KMDocumentPrintToolbarItemIdentifier,
+            return [KMDocumentAITranslationToolbarItemIdentifier,
+                    KMDocumentPrintToolbarItemIdentifier,
                     KMDocumentShareToolbarItemIdentifier,
                     KMRightControlToolbarItemIdentifier]
         }
@@ -645,6 +651,18 @@ extension KMToolbarViewController : KMNewToolbarDelegate,NSToolbarItemValidation
                 menuItem?.target = self
                 menuItem?.tag = item!.btnTag
                 item?.menuFormRepresentation = menuItem
+            } else if identifier == KMDocumentAITranslationToolbarItemIdentifier {
+                item?.image = NSImage(named: "ic_function_other_AITranslation")
+                item?.titleName = "AI Translation"
+                item?.alternateImage = NSImage(named: "ic_function_other_AITranslation")
+                item?.target = self
+                item?.toolTip = NSLocalizedString("AI Translation", comment: "")
+                item?.boxImagePosition = KMToolBoxImagePosition.only
+                item?.btnAction = #selector(aiTranslationButtonAction)
+                
+                let menuItem = NSMenuItem.init(title: item?.titleName, action: #selector(aiTranslationButtonAction), target: self)
+                menuItem?.target = self
+                item?.menuFormRepresentation = menuItem
             } else if identifier == KMDocumentPrintToolbarItemIdentifier {
                 item?.image = NSImage(named: "KMImageNameMainToolbarPrint")
                 item?.titleName = "Print"

+ 1 - 0
PDF Office/PDF Master/Class/PDFWindowController/Toolbar/PublicKey.swift

@@ -23,6 +23,7 @@ let KMDocumentEditToolbarItemIdentifier = "KMDocumentPageEditToolbarItemIdentifi
 let KMDocumentFillSginToolbarItemIdentifier = "KMDocumentFillSginToolbarItemIdentifier"
 let KMDocumentToolToolbarItemIdentifier = "KMDocumentToolToolbarItemIdentifier"
 let KMDocumentPrintToolbarItemIdentifier = "KMDocumentPrintToolbarItemIdentifier"
+let KMDocumentAITranslationToolbarItemIdentifier = "KMDocumentAITranslationToolbarItemIdentifier"
 let KMDocumentShareToolbarItemIdentifier = "KMDocumentShareToolbarItemIdentifier"
 let KMRightControlToolbarItemIdentifier  = "KMRightControlToolbarItemIdentifier"
 let mainToolIdentifiers = [KMLeftControlToolbarItemIdentifier, KMDocumentZoomToolbarItemIdentifier, KMDocumentZoomOutToolbarItemIdentifier,

+ 11 - 0
PDF Office/PDF Master/Class/PDFWindowController/ViewController/KMMainViewController+Action.swift

@@ -1913,6 +1913,17 @@ extension KMMainViewController : KMMainToolbarControllerDelegate {
         self.showPrintWindow()
     }
     
+    func aiTranslationPDFFileAction() {
+        if !KMLightMemberManager.manager.isLogin() {
+            KMLoginWindowController.show(window: NSApp.mainWindow!)
+            return
+        }
+
+        self.aiTranslationConfirWC = KMAITranslationConfirmWindowController.init(windowNibName: NSNib.Name("KMAITranslationConfirmWindowController"))
+        self.aiTranslationConfirWC!.filePath = (self.document?.documentURL.path)!
+        self.view.window?.beginSheet(self.aiTranslationConfirWC!.window!)
+    }
+    
     func toolbarViewController(_ viewController: KMToolbarViewController, shareDocument item: NSMenuItem) {
         self.shareDocument(sender: viewController)
     }

+ 1 - 0
PDF Office/PDF Master/Class/PDFWindowController/ViewController/KMMainViewController.swift

@@ -125,6 +125,7 @@ import Cocoa
     var eventMonitor: Any?
     var mouseRightMenuEvent: NSEvent?
     var aiTranslationWindow: KMAITranslationWindowController?
+    var aiTranslationConfirWC: KMAITranslationConfirmWindowController?
     
     deinit {
         NotificationCenter.default.removeObserver(self)