diff --git a/Packages/vChewing_Shared/Sources/Shared/Protocols/PrefMgrProtocol.swift b/Packages/vChewing_Shared/Sources/Shared/Protocols/PrefMgrProtocol.swift index 94bf4e02..30981dd6 100644 --- a/Packages/vChewing_Shared/Sources/Shared/Protocols/PrefMgrProtocol.swift +++ b/Packages/vChewing_Shared/Sources/Shared/Protocols/PrefMgrProtocol.swift @@ -41,7 +41,7 @@ public protocol PrefMgrProtocol { var hardenVerticalPunctuations: Bool { get set } var trimUnfinishedReadingsOnCommit: Bool { get set } var alwaysShowTooltipTextsHorizontally: Bool { get set } - var clientsIMKTextInputIncapable: [String] { get set } + var clientsIMKTextInputIncapable: [String: Bool] { get set } var onlyLoadFactoryLangModelsIfNeeded: Bool { get set } var useIMKCandidateWindow: Bool { get set } var handleDefaultCandidateFontsByLangIdentifier: Bool { get set } diff --git a/Source/Modules/InputHandler_Core.swift b/Source/Modules/InputHandler_Core.swift index b9cf9463..be72b709 100644 --- a/Source/Modules/InputHandler_Core.swift +++ b/Source/Modules/InputHandler_Core.swift @@ -61,6 +61,7 @@ public protocol InputHandlerDelegate { var selectionKeys: String { get } var state: IMEStateProtocol { get set } var clientBundleIdentifier: String { get } + var clientMitigationLevel: Int { get } func callError(_ logMessage: String) func updateVerticalTypingStatus() func switchState(_ newState: IMEStateProtocol) @@ -540,8 +541,8 @@ extension InputHandler { var commitOverflownComposition: String { guard !compositor.walkedNodes.isEmpty, compositor.length > compositorWidthLimit, - let identifier = delegate?.clientBundleIdentifier, - prefs.clientsIMKTextInputIncapable.contains(identifier) + let delegate = delegate, + delegate.clientMitigationLevel >= 2 else { return "" } // 回頭在這裡插上對 Steam 的 Client Identifier 的要求。 var textToCommit = "" diff --git a/Source/Modules/PrefMgr_Core.swift b/Source/Modules/PrefMgr_Core.swift index d3f284a7..48f1d92e 100644 --- a/Source/Modules/PrefMgr_Core.swift +++ b/Source/Modules/PrefMgr_Core.swift @@ -22,8 +22,8 @@ public class PrefMgr: PrefMgrProtocol { return "com.apple.keylayout.US" }() - public static let kDefaultClientsIMKTextInputIncapable: [String] = [ - "com.valvesoftware.steam", "jp.naver.line.mac", + public static let kDefaultClientsIMKTextInputIncapable: [String: Bool] = [ + "com.valvesoftware.steam": true, "jp.naver.line.mac": true, ] // MARK: - Settings (Tier 1) @@ -144,7 +144,7 @@ public class PrefMgr: PrefMgrProtocol { public var alwaysShowTooltipTextsHorizontally: Bool @AppProperty(key: UserDef.kClientsIMKTextInputIncapable.rawValue, defaultValue: kDefaultClientsIMKTextInputIncapable) - public var clientsIMKTextInputIncapable: [String] + public var clientsIMKTextInputIncapable: [String: Bool] @AppProperty(key: UserDef.kOnlyLoadFactoryLangModelsIfNeeded.rawValue, defaultValue: true) public var onlyLoadFactoryLangModelsIfNeeded: Bool { diff --git a/Source/Modules/PrefMgr_Extension.swift b/Source/Modules/PrefMgr_Extension.swift index 894e824c..c57ce9aa 100644 --- a/Source/Modules/PrefMgr_Extension.swift +++ b/Source/Modules/PrefMgr_Extension.swift @@ -23,8 +23,16 @@ public extension PrefMgr { } // 自動糾正選字鍵 (利用其 didSet 特性) candidateKeys = candidateKeys - // 客體黑名單自動排序去重複。 - clientsIMKTextInputIncapable = Array(Set(clientsIMKTextInputIncapable)).sorted() + // 客體黑名單資料類型升級。 + if let clients = UserDefaults.standard.object( + forKey: UserDef.kClientsIMKTextInputIncapable.rawValue + ) as? [String] { + UserDefaults.standard.removeObject(forKey: UserDef.kClientsIMKTextInputIncapable.rawValue) + clients.forEach { neta in + guard !clientsIMKTextInputIncapable.keys.contains(neta) else { return } + clientsIMKTextInputIncapable[neta] = true + } + } // 注拼槽注音排列選項糾錯。 var isKeyboardParserOptionValid = false KeyboardParser.allCases.forEach { diff --git a/Source/Modules/SessionCtl_Delegates.swift b/Source/Modules/SessionCtl_Delegates.swift index ed63d513..59e60bfc 100644 --- a/Source/Modules/SessionCtl_Delegates.swift +++ b/Source/Modules/SessionCtl_Delegates.swift @@ -11,6 +11,15 @@ import Shared // MARK: - InputHandler Delegate extension SessionCtl: InputHandlerDelegate { + public var clientMitigationLevel: Int { + guard + let result = PrefMgr.shared.clientsIMKTextInputIncapable[clientBundleIdentifier] + else { + return 0 + } + return result ? 2 : 1 + } + public func candidateController() -> CtlCandidateProtocol? { candidateUI } public func candidateSelectionCalledByInputHandler(at index: Int) { diff --git a/Source/Modules/SessionCtl_HandleDisplay.swift b/Source/Modules/SessionCtl_HandleDisplay.swift index 6e975345..c6770549 100644 --- a/Source/Modules/SessionCtl_HandleDisplay.swift +++ b/Source/Modules/SessionCtl_HandleDisplay.swift @@ -16,8 +16,8 @@ public extension SessionCtl { // 有些 App 會濫用內文組字區的內容來預測使用者的輸入行為。 // 對此類 App 有疑慮者,可以將這類 App 登記到客體管理員當中。 // 這樣,不但強制使用(限制讀音 20 個的)浮動組字窗,而且內文組字區只會顯示一個空格。 - var attributedStringSecured: (NSAttributedString, NSRange) { - PrefMgr.shared.clientsIMKTextInputIncapable.contains(clientBundleIdentifier) + var attributedStringSecured: (value: NSAttributedString, range: NSRange) { + clientMitigationLevel >= 2 ? (state.data.attributedStringPlaceholder, NSRange(location: 0, length: 0)) : (state.attributedString, NSRange(state.u16MarkedRange)) } diff --git a/Source/Modules/SessionCtl_HandleStates.swift b/Source/Modules/SessionCtl_HandleStates.swift index dec6f108..e2a59249 100644 --- a/Source/Modules/SessionCtl_HandleStates.swift +++ b/Source/Modules/SessionCtl_HandleStates.swift @@ -87,7 +87,7 @@ public extension SessionCtl { showCandidates() } // 浮動組字窗的顯示判定 - if newState.hasComposition, PrefMgr.shared.clientsIMKTextInputIncapable.contains(clientBundleIdentifier) { + if newState.hasComposition, clientMitigationLevel >= 2 { updateVerticalTypingStatus() popupCompositionBuffer.isTypingDirectionVertical = isVerticalTyping popupCompositionBuffer.show( @@ -100,12 +100,25 @@ public extension SessionCtl { /// 如果當前狀態含有「組字結果內容」、或者有選字窗內容、或者存在正在輸入的字根/讀音,則在組字區內顯示游標。 func setInlineDisplayWithCursor() { + var attrStr: NSAttributedString = attributedStringSecured.value + var theRange: NSRange = attributedStringSecured.range + // 包括早期版本的騰訊 QQNT 在內,有些客體的 client.setMarkedText() 無法正常處理 .thick 下劃線。 + mitigation: if clientMitigationLevel == 1, state.type == .ofMarking { + if !PrefMgr.shared.disableSegmentedThickUnderlineInMarkingModeForManagedClients { break mitigation } + let neo = NSMutableAttributedString(attributedString: attributedStringSecured.value) + neo.setAttributes( + [ + .underlineStyle: NSUnderlineStyle.thick.rawValue, + .markedClauseSegment: 0, + ], range: NSRange(location: 0, length: neo.string.utf16.count) + ) + attrStr = neo + theRange = NSRange.zero + } /// 所謂選區「selectionRange」,就是「可見游標位置」的位置,只不過長度 /// 是 0 且取代範圍(replacementRange)為「NSNotFound」罷了。 /// 也就是說,內文組字區該在哪裡出現,得由客體軟體來作主。 - doSetMarkedText( - attributedStringSecured.0, selectionRange: attributedStringSecured.1 - ) + doSetMarkedText(attrStr, selectionRange: theRange) } /// 在處理某些「沒有組字區內容顯示」且「不需要攔截某些按鍵處理」的狀態時使用的函式,會清空螢幕上顯示的組字區。 diff --git a/Source/Modules/WindowControllers/CtlClientListMgr.swift b/Source/Modules/WindowControllers/CtlClientListMgr.swift index 5a6e9750..6bac8eda 100644 --- a/Source/Modules/WindowControllers/CtlClientListMgr.swift +++ b/Source/Modules/WindowControllers/CtlClientListMgr.swift @@ -34,15 +34,30 @@ class CtlClientListMgr: NSWindowController, NSTableViewDelegate, NSTableViewData tblClients.delegate = self tblClients.allowsMultipleSelection = true tblClients.dataSource = self + tblClients.action = #selector(onItemClicked(_:)) + tblClients.target = self tblClients.reloadData() } } +// MARK: - UserDefaults Handlers + +extension CtlClientListMgr { + public static var clientsList: [String] { PrefMgr.shared.clientsIMKTextInputIncapable.keys.sorted() } + public static func removeClient(at index: Int) { + guard index < Self.clientsList.count else { return } + let key = Self.clientsList[index] + var dict = PrefMgr.shared.clientsIMKTextInputIncapable + dict[key] = nil + PrefMgr.shared.clientsIMKTextInputIncapable = dict + } +} + // MARK: - Implementations extension CtlClientListMgr { func numberOfRows(in _: NSTableView) -> Int { - PrefMgr.shared.clientsIMKTextInputIncapable.count + Self.clientsList.count } @IBAction func btnAddClientClicked(_: Any) { @@ -105,8 +120,8 @@ extension CtlClientListMgr { switch result { case .OK: for url in dlgOpenPath.urls { - var title = NSLocalizedString( - "The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier.", + let title = NSLocalizedString( + "The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier.", comment: "" ) let text = url.path + "\n\n" + NSLocalizedString("Please try again.", comment: "") @@ -118,14 +133,21 @@ extension CtlClientListMgr { self.window?.callAlert(title: title, text: text) return } - if PrefMgr.shared.clientsIMKTextInputIncapable.contains(identifier) { - title = NSLocalizedString( - "The selected item's identifier is already in the list.", comment: "" - ) - self.window?.callAlert(title: title, text: identifier + "\n\n" + url.path) - return + let isIdentifierAlreadyRegistered = Self.clientsList.contains(identifier) + let alert2 = NSAlert() + alert2.messageText = + "Do you want to enable the popup composition buffer for this client?".localized + alert2.informativeText = "\(identifier)\n\n" + + "Some client apps may have different compatibility issues in IMKTextInput implementation.".localized + alert2.addButton(withTitle: "Yes".localized) + alert2.addButton(withTitle: "No".localized) + alert2.beginSheetModal(for: window) { result2 in + let oldValue = PrefMgr.shared.clientsIMKTextInputIncapable[identifier] + let newValue = result2 == .alertFirstButtonReturn + if !(isIdentifierAlreadyRegistered && oldValue == newValue) { + self.applyNewValue(identifier, highMitigation: newValue) + } } - self.applyNewValue(identifier) } default: return } @@ -135,50 +157,71 @@ extension CtlClientListMgr { } } - private func applyNewValue(_ newValue: String) { + private func applyNewValue(_ newValue: String, highMitigation mitigation: Bool = true) { guard !newValue.isEmpty else { return } - var arrResult = PrefMgr.shared.clientsIMKTextInputIncapable - arrResult.append(newValue) - PrefMgr.shared.clientsIMKTextInputIncapable = arrResult.sorted() + var dict = PrefMgr.shared.clientsIMKTextInputIncapable + dict[newValue] = mitigation + PrefMgr.shared.clientsIMKTextInputIncapable = dict tblClients.reloadData() - btnRemoveClient.isEnabled = (0 ..< PrefMgr.shared.clientsIMKTextInputIncapable.count).contains( + btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains( tblClients.selectedRow) } @IBAction func btnRemoveClientClicked(_: Any) { guard let minIndexSelected = tblClients.selectedRowIndexes.min() else { return } - if minIndexSelected >= PrefMgr.shared.clientsIMKTextInputIncapable.count { return } + if minIndexSelected >= Self.clientsList.count { return } if minIndexSelected < 0 { return } var isLastRow = false tblClients.selectedRowIndexes.sorted().reversed().forEach { index in isLastRow = { - if PrefMgr.shared.clientsIMKTextInputIncapable.count < 2 { return false } - return minIndexSelected == PrefMgr.shared.clientsIMKTextInputIncapable.count - 1 + if Self.clientsList.count < 2 { return false } + return minIndexSelected == Self.clientsList.count - 1 }() - if index < PrefMgr.shared.clientsIMKTextInputIncapable.count { - PrefMgr.shared.clientsIMKTextInputIncapable.remove(at: index) + if index < Self.clientsList.count { + Self.removeClient(at: index) } } if isLastRow { tblClients.selectRowIndexes(.init(arrayLiteral: minIndexSelected - 1), byExtendingSelection: false) } tblClients.reloadData() - btnRemoveClient.isEnabled = (0 ..< PrefMgr.shared.clientsIMKTextInputIncapable.count).contains(minIndexSelected) + btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains(minIndexSelected) } - func tableView(_: NSTableView, objectValueFor _: NSTableColumn?, row: Int) -> Any? { + @objc func onItemClicked(_: Any!) { + guard tblClients.clickedColumn == 0 else { return } + PrefMgr.shared.clientsIMKTextInputIncapable[Self.clientsList[tblClients.clickedRow]]?.toggle() + tblClients.reloadData() + } + + func tableView(_: NSTableView, shouldEdit _: NSTableColumn?, row _: Int) -> Bool { + false + } + + func tableView(_: NSTableView, objectValueFor column: NSTableColumn?, row: Int) -> Any? { defer { - self.btnRemoveClient.isEnabled = (0 ..< PrefMgr.shared.clientsIMKTextInputIncapable.count).contains( + self.btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains( self.tblClients.selectedRow) } - return PrefMgr.shared.clientsIMKTextInputIncapable[row] + guard row < Self.clientsList.count else { return "" } + if let column = column { + let colName = column.identifier.rawValue + switch colName { + case "colPCBEnabled": + let tick = PrefMgr.shared.clientsIMKTextInputIncapable[Self.clientsList[row]] ?? true + return tick + case "colClient": return Self.clientsList[row] + default: return "" + } + } + return Self.clientsList[row] } private func localize() { guard let window = window else { return } window.title = NSLocalizedString("Client Manager", comment: "") lblClientMgrWindow.stringValue = NSLocalizedString( - "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable.", + "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable.", comment: "" ) btnAddClient.title = NSLocalizedString("Add Client", comment: "") diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index 470d6687..4aee8c7a 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -1,4 +1,8 @@ "vChewing" = "vChewing"; +"Do you want to enable the popup composition buffer for this client?" = "Do you want to enable the popup composition buffer for this client?"; +"Some client apps may have different compatibility issues in IMKTextInput implementation." = "Some client apps may have different compatibility issues in IMKTextInput implementation."; +"Yes" = "Yes"; +"No" = "No"; "Hanin Keyboard Symbol Input." = "Hanin Keyboard Symbol Input."; "Open App Support Folder" = "Open App Support Folder"; "Invalid Code Point." = "Invalid Code Point."; @@ -58,11 +62,11 @@ "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed."; "Just Select" = "Just Select"; "Client Manager" = "Client Manager"; -"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable."; +"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable." = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable."; "Add Client" = "Add Client"; "Remove Selected" = "Remove Selected"; "Choose the target application bundle." = "Choose the target application bundle."; -"The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier." = "The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier."; +"The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier." = "The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier."; "Please try again." = "Please try again."; "The selected item's identifier is already in the list." = "The selected item's identifier is already in the list."; "Update Check Completed" = "Update Check Completed"; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 470d6687..4aee8c7a 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -1,4 +1,8 @@ "vChewing" = "vChewing"; +"Do you want to enable the popup composition buffer for this client?" = "Do you want to enable the popup composition buffer for this client?"; +"Some client apps may have different compatibility issues in IMKTextInput implementation." = "Some client apps may have different compatibility issues in IMKTextInput implementation."; +"Yes" = "Yes"; +"No" = "No"; "Hanin Keyboard Symbol Input." = "Hanin Keyboard Symbol Input."; "Open App Support Folder" = "Open App Support Folder"; "Invalid Code Point." = "Invalid Code Point."; @@ -58,11 +62,11 @@ "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed."; "Just Select" = "Just Select"; "Client Manager" = "Client Manager"; -"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable."; +"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable." = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable."; "Add Client" = "Add Client"; "Remove Selected" = "Remove Selected"; "Choose the target application bundle." = "Choose the target application bundle."; -"The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier." = "The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier."; +"The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier." = "The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier."; "Please try again." = "Please try again."; "The selected item's identifier is already in the list." = "The selected item's identifier is already in the list."; "Update Check Completed" = "Update Check Completed"; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index f0f3eade..0f58681f 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -1,4 +1,8 @@ "vChewing" = "威注音入力アプリ"; +"Do you want to enable the popup composition buffer for this client?" = "この客体アプリに「吹き出し入力緩衝列ウィンドウ」を起用しますか?"; +"Some client apps may have different compatibility issues in IMKTextInput implementation." = "それぞれの客体アプリには、それぞれの IMKTextInput 不具合はあるかもしれません。"; +"Yes" = "うむ"; +"No" = "いな"; "Hanin Keyboard Symbol Input." = "漢音キーボード符号入力。"; "Open App Support Folder" = "App Support フォルダーを開く"; "Invalid Code Point." = "コードポイントは正しくない。"; @@ -58,11 +62,11 @@ "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "毎行は1つ記録とみなす。Option+Enter キーで改行。\n空白の記録値は無視される。"; "Just Select" = "直接に選ぶ"; "Client Manager" = "客体アプリの管理"; -"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "下記の種類の客体アプリはここでご登録ください:1)IMKTextInput 議定規約に反するもの;2)文脈内入力緩衝列の内容の不正利用の疑いのあるもの。登録済みのアプリには、威注音入力アプリは「吹き出し入力緩衝列ウィンドウ」と「緩衝列容量制限」を起用し、容量制限は最大限音読み20箇とする。"; +"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable." = "下記の客体アプリはここでご登録を:1)IMKTextInput 議定規約に反するもの;2)文脈内入力緩衝列の内容の不正利用容疑のあるもの。「登録済みのアプリ」にチェックを入れると、「吹き出し入力緩衝列ウィンドウ」と「緩衝列容量制限」を起用し、容量制限は最大限音読み20箇とする。"; "Add Client" = "入れる"; "Remove Selected" = "外す"; "Choose the target application bundle." = "登録したいアプリのバンドルのお選びを。"; -"The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier." = "今選んだんのは正しい macOS アプリバンドルではないと考えられる。少なくとも、唯一識別子は検出できぬ。"; +"The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier." = "今選んだんのは正しい macOS アプリバンドルではないと考えられる。少なくとも、唯一識別子は検出できぬ。"; "Please try again." = "お選び直しください。"; "The selected item's identifier is already in the list." = "今選んだバンドルの唯一識別子(Bundle Identifier)は既に登録済みである。"; "Update Check Completed" = "新バージョンチェック完了"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index 569d4271..7f19071c 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -1,4 +1,8 @@ "vChewing" = "威注音输入法"; +"Do you want to enable the popup composition buffer for this client?" = "您要對該客體啟用浮動組字窗嗎?"; +"Some client apps may have different compatibility issues in IMKTextInput implementation." = "有些客體應用可能會有不同的 IMKTextInput 實作相容問題。"; +"Yes" = "是"; +"No" = "否"; "Hanin Keyboard Symbol Input." = "汉音键盘符号模式。"; "Open App Support Folder" = "开启 App Support 目录"; "Invalid Code Point." = "内码不正确。"; @@ -58,11 +62,11 @@ "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一笔记录,用 Option+Enter 换行。\n空白值会被无视。"; "Just Select" = "直接选取"; "Client Manager" = "管理客体应用"; -"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "请在此管理这两类客体应用:1) 不遵守 IMKTextInput 协定;2)有滥用内文组字区的嫌疑。威注音输入法对于任何位列在此的客体应用均启用浮动组字窗、且对组字区内容设定容量上限(最多二十个读音)。"; +"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable." = "请在此管理这两类客体应用:1) 不遵守 IMKTextInput 协定;2)有滥用内文组字区的嫌疑。您可以勾选上述客体应用、以启用下述特性:启用浮动组字窗、且对组字区内容设定容量上限(最多二十个读音)。"; "Add Client" = "登记新客体"; "Remove Selected" = "移除所选条目"; "Choose the target application bundle." = "请选择要登记的应用程式的封包。"; -"The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier." = "当前所选之物并非 macOS 应用程式封包,至少无法发现其唯一标帜(Bundle Identifier)。"; +"The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier." = "当前所选之物并非 macOS 应用程式封包,至少无法发现其唯一标帜(Bundle Identifier)。"; "Please try again." = "请重试。"; "The selected item's identifier is already in the list." = "当前所选之封包的唯一标帜(Bundle Identifier)已被登记。"; "Update Check Completed" = "更新检查完毕"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index aa6bfedb..303b5d20 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -1,4 +1,8 @@ "vChewing" = "威注音輸入法"; +"Do you want to enable the popup composition buffer for this client?" = "您要对该客体启用浮动组字窗吗?"; +"Some client apps may have different compatibility issues in IMKTextInput implementation." = "有些客体应用可能会有不同的 IMKTextInput 实作相容问题。"; +"Yes" = "是"; +"No" = "否"; "Hanin Keyboard Symbol Input." = "漢音鍵盤符號模式。"; "Open App Support Folder" = "開啟 App Support 目錄"; "Invalid Code Point." = "內碼不正確。"; @@ -58,11 +62,11 @@ "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一筆記錄,用 Option+Enter 換行。\n空白值會被無視。"; "Just Select" = "直接選取"; "Client Manager" = "管理客體應用"; -"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. Clients listed here will only use popup composition buffer with maximum 20 reading counts holdable." = "請在此管理這兩類客體應用:1) 不遵守 IMKTextInput 協定;2)有濫用內文組字區的嫌疑。威注音輸入法對於任何位列在此的客體應用均啟用浮動組字窗、且對組字區內容設定容量上限(最多二十個讀音)。"; +"Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable." = "請在此管理這兩類客體應用:1) 不遵守 IMKTextInput 協定;2)有濫用內文組字區的嫌疑。您可以勾選上述客體應用、以啟用下述特性:啟用浮動組字窗、且對組字區內容設定容量上限(最多二十個讀音)。"; "Add Client" = "登記新客體"; "Remove Selected" = "移除所選條目"; "Choose the target application bundle." = "請選擇要登記的應用程式的封包。"; -"The selected item is not a valid macOS application bundle, nor not having a valid app bundle identifier." = "當前所選之物並非 macOS 應用程式封包,至少無法發現其唯一標幟(Bundle Identifier)。"; +"The selected item is either not a valid macOS application bundle or not having a valid app bundle identifier." = "當前所選之物並非 macOS 應用程式封包,至少無法發現其唯一標幟(Bundle Identifier)。"; "Please try again." = "請重試。"; "The selected item's identifier is already in the list." = "當前所選之封包的唯一標幟(Bundle Identifier)已被登記。"; "Update Check Completed" = "更新檢查完畢"; diff --git a/Source/WindowNIBs/frmClientListMgr.xib b/Source/WindowNIBs/frmClientListMgr.xib index 825d65a0..925858eb 100644 --- a/Source/WindowNIBs/frmClientListMgr.xib +++ b/Source/WindowNIBs/frmClientListMgr.xib @@ -1,7 +1,8 @@ - + - + + @@ -20,17 +21,17 @@ - + - + - + - - + + @@ -39,19 +40,30 @@ - + - - + + - + - + + + + + + + + + + + + @@ -69,7 +81,7 @@ - +