Repo // Add KimoDataReader using NSConnection.
This commit is contained in:
parent
424a736c8e
commit
b479acf779
|
@ -0,0 +1,212 @@
|
|||
---
|
||||
# BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: true
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: "^<.*"
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: ".*"
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: "([-_](test|unittest))?$"
|
||||
IncludeIsMainSourceRegex: ""
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
MacroBlockBegin: ""
|
||||
MacroBlockEnd: ""
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
- cc
|
||||
- CC
|
||||
- cpp
|
||||
- Cpp
|
||||
- CPP
|
||||
- "c++"
|
||||
- "C++"
|
||||
- "cs"
|
||||
CanonicalDelimiter: ""
|
||||
BasedOnStyle: google
|
||||
- Language: TextProto
|
||||
Delimiters:
|
||||
- pb
|
||||
- PB
|
||||
- proto
|
||||
- PROTO
|
||||
EnclosingFunctions:
|
||||
- EqualsProto
|
||||
- EquivToProto
|
||||
- PARSE_PARTIAL_TEXT_PROTO
|
||||
- PARSE_TEST_PROTO
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
- ParseTestProto
|
||||
- ParsePartialTestProto
|
||||
CanonicalDelimiter: pb
|
||||
BasedOnStyle: google
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: CaseSensitive
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Auto
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
---
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/configuration/registries.json
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.netrc
|
|
@ -0,0 +1,31 @@
|
|||
// swift-tools-version: 5.9
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "KimoDataReader",
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, making them visible to other packages.
|
||||
.library(
|
||||
name: "KimoDataReader",
|
||||
targets: ["KimoDataReader"]
|
||||
),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
||||
// Targets can depend on other targets in this package and products from dependencies.
|
||||
.target(
|
||||
name: "ObjcKimoCommunicator",
|
||||
publicHeadersPath: "include"
|
||||
),
|
||||
.target(
|
||||
name: "KimoDataReader",
|
||||
dependencies: ["ObjcKimoCommunicator"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "KimoDataReaderTests",
|
||||
dependencies: ["KimoDataReader"]
|
||||
),
|
||||
]
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
# KimoCommunicator
|
||||
|
||||
用來與奇摩輸入法進行 NSConnection 通訊的模組,便於直接從奇摩輸入法讀入使用者自訂詞資料庫的資料。
|
||||
|
||||
> 免責聲明:
|
||||
> 與奇摩輸入法有關的原始碼是由 Yahoo 奇摩以 `SPDX Identifier: BSD-3-Clause` 釋出的,
|
||||
> 但敝模組只是藉由其 Protocol API 與該當程式進行跨執行緒通訊,所以屬於合理使用範圍。
|
||||
|
||||
```
|
||||
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
// ... with NTL restriction stating that:
|
||||
// No trademark license is granted to use the trade names, trademarks, service
|
||||
// marks, or product names of Contributor, except as required to fulfill notice
|
||||
// requirements defined in MIT License.
|
||||
```
|
||||
|
||||
$ EOF.
|
|
@ -0,0 +1,25 @@
|
|||
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
// ... with NTL restriction stating that:
|
||||
// No trademark license is granted to use the trade names, trademarks, service
|
||||
// marks, or product names of Contributor, except as required to fulfill notice
|
||||
// requirements defined in MIT License.
|
||||
|
||||
import Foundation
|
||||
import ObjcKimoCommunicator
|
||||
|
||||
public class KimoCommunicator: ObjcKimoCommunicator {
|
||||
public static let shared: KimoCommunicator = .init()
|
||||
|
||||
public func prepareData(handler: @escaping (_ key: String, _ value: String) -> Void) {
|
||||
guard KimoCommunicator.shared.establishConnection() else { return }
|
||||
assert(KimoCommunicator.shared.hasValidConnection())
|
||||
let loopAmount = KimoCommunicator.shared.userPhraseDBTotalAmountOfRows()
|
||||
for i in 0 ..< loopAmount {
|
||||
let fetched = KimoCommunicator.shared.userPhraseDBDictionary(atRow: i)
|
||||
guard let key = fetched["BPMF"], let text = fetched["Text"] else { continue }
|
||||
handler(key, text)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
// ... with NTL restriction stating that:
|
||||
// No trademark license is granted to use the trade names, trademarks, service
|
||||
// marks, or product names of Contributor, except as required to fulfill notice
|
||||
// requirements defined in MIT License.
|
||||
|
||||
// 免責聲明:
|
||||
// 與奇摩輸入法有關的原始碼是由 Yahoo 奇摩以 `SPDX Identifier: BSD-3-Clause` 釋出的,
|
||||
// 但敝模組只是藉由其 Protocol API 與該當程式進行跨執行緒通訊,所以屬於合理使用範圍。
|
||||
|
||||
#import "KimoCommunicator.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define kYahooKimoDataObjectConnectionName @"YahooKeyKeyService"
|
||||
|
||||
@implementation ObjcKimoCommunicator {
|
||||
id _xpcConnection;
|
||||
}
|
||||
|
||||
/// 解構。
|
||||
- (void)dealloc {
|
||||
[self disconnect];
|
||||
}
|
||||
|
||||
/// 斷開連線。
|
||||
- (void)disconnect {
|
||||
_xpcConnection = nil;
|
||||
}
|
||||
|
||||
/// 嘗試連線。
|
||||
- (bool)establishConnection {
|
||||
// 奇摩輸入法2012最終版在建置的時候還沒用到 NSXPCConnection,實質上並不支援
|
||||
// NSXPCConnection。 因此,這裡使用 NSXPCConnection 的話反而會壞事。
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
_xpcConnection = [NSConnection rootProxyForConnectionWithRegisteredName:
|
||||
kYahooKimoDataObjectConnectionName
|
||||
host:nil];
|
||||
#pragma GCC diagnostic pop
|
||||
BOOL result = false;
|
||||
if (_xpcConnection) {
|
||||
result = true;
|
||||
}
|
||||
if (result) {
|
||||
[_xpcConnection setProtocolForProxy:@protocol(KimoUserDataReaderService)];
|
||||
NSLog(@"vChewingDebug: Connection successful. Available data amount: %d.\n",
|
||||
[_xpcConnection userPhraseDBNumberOfRow]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 偵測連線是否有效。
|
||||
- (bool)hasValidConnection {
|
||||
BOOL result = false;
|
||||
if (_xpcConnection) result = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)userPhraseDBCanProvideService {
|
||||
return [self hasValidConnection]
|
||||
? [_xpcConnection userPhraseDBCanProvideService]
|
||||
: NO;
|
||||
}
|
||||
|
||||
- (int)userPhraseDBTotalAmountOfRows {
|
||||
return [self hasValidConnection] ? [_xpcConnection userPhraseDBNumberOfRow]
|
||||
: 0;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString*, NSString*> *)userPhraseDBDictionaryAtRow:(int)row {
|
||||
return [self hasValidConnection]
|
||||
? [_xpcConnection userPhraseDBDictionaryAtRow:row]
|
||||
: [NSDictionary alloc];
|
||||
}
|
||||
|
||||
- (bool)exportUserPhraseDBToFile:(NSString *)path {
|
||||
return [self hasValidConnection]
|
||||
? [_xpcConnection exportUserPhraseDBToFile:path]
|
||||
: NO;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,46 @@
|
|||
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
// ====================
|
||||
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
|
||||
// ... with NTL restriction stating that:
|
||||
// No trademark license is granted to use the trade names, trademarks, service
|
||||
// marks, or product names of Contributor, except as required to fulfill notice
|
||||
// requirements defined in MIT License.
|
||||
|
||||
// 免責聲明:
|
||||
// 與奇摩輸入法有關的原始碼是由 Yahoo 奇摩以 `SPDX Identifier: BSD-3-Clause` 釋出的,
|
||||
// 但敝模組只是藉由其 Protocol API 與該當程式進行跨執行緒通訊,所以屬於合理使用範圍。
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol KimoUserDataReaderService
|
||||
- (BOOL)userPhraseDBCanProvideService;
|
||||
- (int)userPhraseDBNumberOfRow;
|
||||
- (NSDictionary *)userPhraseDBDictionaryAtRow:(int)row;
|
||||
- (bool)exportUserPhraseDBToFile:(NSString *)path;
|
||||
@end
|
||||
|
||||
/// 不要理會 Xcode 對 NSDistantObject 的過期狗吠。
|
||||
/// 奇摩輸入法是用 NSConnection 寫的,
|
||||
/// 換用 NSXPCConnection 只會製造更多的問題。
|
||||
@interface ObjcKimoCommunicator : NSObject
|
||||
|
||||
/// 嘗試連線。
|
||||
- (bool)establishConnection;
|
||||
|
||||
/// 偵測連線是否有效。
|
||||
- (bool)hasValidConnection;
|
||||
|
||||
/// 斷開連線。
|
||||
- (void)disconnect;
|
||||
|
||||
// Conforming KimoUserDataReaderService protocol.
|
||||
- (BOOL)userPhraseDBCanProvideService;
|
||||
- (int)userPhraseDBTotalAmountOfRows;
|
||||
- (NSDictionary<NSString*, NSString*> *)userPhraseDBDictionaryAtRow:(int)row;
|
||||
- (bool)exportUserPhraseDBToFile:(NSString *)path;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,10 @@
|
|||
@testable import ObjcKimoCommunicator
|
||||
import XCTest
|
||||
|
||||
final class KimoDataReaderTests: XCTestCase {
|
||||
// 先運行奇摩輸入法,再跑這個測試。
|
||||
func testExample() throws {
|
||||
let shared = ObjcKimoCommunicator()
|
||||
print(shared.establishConnection())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
find . -regex '.*\.\(hh\)' -exec clang-format -style=file -i {} \;
|
||||
find . -regex '.*\.\(cc\)' -exec clang-format -style=file -i {} \;
|
||||
find . -regex '.*\.\(mm\)' -exec clang-format -style=file -i {} \;
|
||||
find . -regex '.*\.\(h\)' -exec clang-format -style=file -i {} \;
|
||||
find . -regex '.*\.\(c\)' -exec clang-format -style=file -i {} \;
|
||||
find . -regex '.*\.\(m\)' -exec clang-format -style=file -i {} \;
|
|
@ -21,6 +21,7 @@ let package = Package(
|
|||
.package(path: "../vChewing_CocoaExtension"),
|
||||
.package(path: "../vChewing_Hotenka"),
|
||||
.package(path: "../vChewing_IMKUtils"),
|
||||
.package(path: "../vChewing_KimoDataReader"),
|
||||
.package(path: "../vChewing_LangModelAssembly"),
|
||||
.package(path: "../vChewing_Megrez"),
|
||||
.package(path: "../vChewing_NotifierUI"),
|
||||
|
@ -43,6 +44,7 @@ let package = Package(
|
|||
.product(name: "FolderMonitor", package: "DanielGalasko_FolderMonitor"),
|
||||
.product(name: "Hotenka", package: "vChewing_Hotenka"),
|
||||
.product(name: "IMKUtils", package: "vChewing_IMKUtils"),
|
||||
.product(name: "KimoDataReader", package: "vChewing_KimoDataReader"),
|
||||
.product(name: "LangModelAssembly", package: "vChewing_LangModelAssembly"),
|
||||
.product(name: "Megrez", package: "vChewing_Megrez"),
|
||||
.product(name: "NotifierUI", package: "vChewing_NotifierUI"),
|
||||
|
|
|
@ -6,16 +6,78 @@
|
|||
// marks, or product names of Contributor, except as required to fulfill notice
|
||||
// requirements defined in MIT License.
|
||||
|
||||
import AppKit
|
||||
import Foundation
|
||||
import KimoDataReader
|
||||
import LineReader
|
||||
import Shared
|
||||
|
||||
public extension LMMgr {
|
||||
enum KimoDataImportError: Error, LocalizedError {
|
||||
case connectionFailure
|
||||
case fileHandlerFailure
|
||||
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .fileHandlerFailure: return "i18n:KimoDataImportError.fileHandlerFailure.errMsg".localized
|
||||
case .connectionFailure: return "i18n:KimoDataImportError.connectionFailure.errMsg".localized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 藉由 XPC 通訊的方式匯入自奇摩輸入法使用者自訂詞資料庫檔案。
|
||||
/// - Parameter rawString: 原始 TXT 檔案內容。
|
||||
/// - Returns: 成功匯入的資料數量。
|
||||
@discardableResult static func importYahooKeyKeyUserDictionaryByXPC() throws -> Int {
|
||||
let kimoBundleID = "com.yahoo.inputmethod.KeyKey"
|
||||
if #unavailable(macOS 11) {
|
||||
NSWorkspace.shared.launchApplication(
|
||||
withBundleIdentifier: kimoBundleID,
|
||||
additionalEventParamDescriptor: nil,
|
||||
launchIdentifier: nil
|
||||
)
|
||||
} else {
|
||||
guard let imeURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: kimoBundleID) else {
|
||||
throw KimoDataImportError.connectionFailure
|
||||
}
|
||||
NSWorkspace.shared.openApplication(at: imeURL, configuration: .init())
|
||||
}
|
||||
guard KimoCommunicator.shared.establishConnection() else { throw KimoDataImportError.connectionFailure }
|
||||
var allPhrasesCHT = [UserPhrase]()
|
||||
var allPhrasesCHS = [UserPhrase]()
|
||||
KimoCommunicator.shared.prepareData { key, value in
|
||||
let phraseCHT = UserPhrase(
|
||||
keyArray: key.components(separatedBy: ","),
|
||||
value: value,
|
||||
inputMode: .imeModeCHT,
|
||||
isConverted: false
|
||||
)
|
||||
guard phraseCHT.isValid, !phraseCHT.isDuplicated else { return }
|
||||
guard !(phraseCHT.value.count == 1 && phraseCHT.keyArray.count == 1) else { return }
|
||||
allPhrasesCHT.append(phraseCHT)
|
||||
let phraseCHS = phraseCHT.crossConverted
|
||||
guard phraseCHS.isValid, !phraseCHS.isDuplicated else { return }
|
||||
guard !(phraseCHS.value.count == 1 && phraseCHS.keyArray.count == 1) else { return }
|
||||
allPhrasesCHS.append(phraseCHS)
|
||||
}
|
||||
|
||||
guard Self.batchImportUserPhrasePairs(allPhrasesCHT: allPhrasesCHT, allPhrasesCHS: allPhrasesCHS) else {
|
||||
throw KimoDataImportError.fileHandlerFailure
|
||||
}
|
||||
|
||||
let result = allPhrasesCHT.count
|
||||
if result > 0 {
|
||||
Broadcaster.shared.eventForReloadingPhraseEditor = .init()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/// 匯入自奇摩輸入法使用者自訂詞資料庫匯出的 TXT 檔案。
|
||||
/// - Parameter rawString: 原始 TXT 檔案內容。
|
||||
/// - Returns: 成功匯入的資料數量。
|
||||
@discardableResult static func importYahooKeyKeyUserDictionary(text rawString: inout String) -> Int {
|
||||
@discardableResult static func importYahooKeyKeyUserDictionary(text rawString: inout String) throws -> Int {
|
||||
var allPhrasesCHT = [UserPhrase]()
|
||||
var allPhrasesCHS = [UserPhrase]()
|
||||
rawString.enumerateLines { currentLine, _ in
|
||||
let cells = currentLine.split(separator: "\t")
|
||||
guard cells.count >= 3, cells.first != "#", cells.first != "MJSR" else { return }
|
||||
|
@ -25,12 +87,25 @@ public extension LMMgr {
|
|||
guard phraseCHT.isValid, !phraseCHT.isDuplicated else { return }
|
||||
guard !(phraseCHT.value.count == 1 && phraseCHT.keyArray.count == 1) else { return }
|
||||
allPhrasesCHT.append(phraseCHT)
|
||||
let phraseCHS = phraseCHT.crossConverted
|
||||
guard phraseCHS.isValid, !phraseCHS.isDuplicated else { return }
|
||||
guard !(phraseCHS.value.count == 1 && phraseCHS.keyArray.count == 1) else { return }
|
||||
allPhrasesCHS.append(phraseCHS)
|
||||
}
|
||||
guard !allPhrasesCHT.isEmpty else { return 0 }
|
||||
let allPhrasesCHS = allPhrasesCHT.compactMap { chtPhrase in
|
||||
let chsPhrase = chtPhrase.crossConverted
|
||||
return chsPhrase.isValid && !chsPhrase.isDuplicated ? chsPhrase : nil
|
||||
}.deduplicated
|
||||
|
||||
guard Self.batchImportUserPhrasePairs(allPhrasesCHT: allPhrasesCHT, allPhrasesCHS: allPhrasesCHS) else {
|
||||
throw KimoDataImportError.fileHandlerFailure
|
||||
}
|
||||
|
||||
let result = allPhrasesCHT.count
|
||||
if result > 0 {
|
||||
Broadcaster.shared.eventForReloadingPhraseEditor = .init()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private static func batchImportUserPhrasePairs(allPhrasesCHT: [UserPhrase], allPhrasesCHS: [UserPhrase]) -> Bool {
|
||||
let outputStrCHS = allPhrasesCHS.map(\.description).joined(separator: "\n")
|
||||
let outputStrCHT = allPhrasesCHT.map(\.description).joined(separator: "\n")
|
||||
var outputDataCHS = "\(outputStrCHS)\n".data(using: .utf8) ?? .init([])
|
||||
|
@ -40,7 +115,7 @@ public extension LMMgr {
|
|||
|
||||
let fileHandlerCHS = try? FileHandle(forUpdating: urlCHS)
|
||||
let fileHandlerCHT = try? FileHandle(forUpdating: urlCHT)
|
||||
guard let fileHandlerCHS = fileHandlerCHS, let fileHandlerCHT = fileHandlerCHT else { return 0 }
|
||||
guard let fileHandlerCHS = fileHandlerCHS, let fileHandlerCHT = fileHandlerCHT else { return false }
|
||||
defer {
|
||||
fileHandlerCHS.closeFile()
|
||||
fileHandlerCHT.closeFile()
|
||||
|
@ -63,12 +138,7 @@ public extension LMMgr {
|
|||
}
|
||||
fileHandlerCHT.seekToEndOfFile()
|
||||
fileHandlerCHT.write(outputDataCHT)
|
||||
|
||||
let result = allPhrasesCHT.count
|
||||
if result > 0 {
|
||||
Broadcaster.shared.eventForReloadingPhraseEditor = .init()
|
||||
}
|
||||
return result
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,9 +66,16 @@ public extension SettingsPanesCocoa {
|
|||
NSStackView.buildSection(width: contentWidth) {
|
||||
UserDef.kAllowBoostingSingleKanjiAsUserPhrase.render(fixWidth: contentWidth)
|
||||
NSStackView.build(.horizontal) {
|
||||
"i18n:settings.importFromKimoTxt.buttonText".makeNSLabel(fixWidth: contentWidth)
|
||||
"i18n:settings.importFromKimoTxt.label".makeNSLabel(fixWidth: contentWidth)
|
||||
NSView()
|
||||
importKimoDragButton()
|
||||
NSStackView.build(.horizontal, spacing: 4) {
|
||||
importKimoDragButton()
|
||||
NSButton(
|
||||
"i18n:settings.importFromKimoTxt.DirectlyImport",
|
||||
target: self,
|
||||
action: #selector(importYahooKeyKeyUserDictionaryDataXPC(_:))
|
||||
)
|
||||
}
|
||||
}
|
||||
}?.boxed()
|
||||
NSView().makeSimpleConstraint(.height, relation: .equal, value: NSFont.systemFontSize)
|
||||
|
@ -78,7 +85,8 @@ public extension SettingsPanesCocoa {
|
|||
func importKimoDragButton() -> NSFileDragRetrieverButton {
|
||||
dragRetrieverKimo.postDragHandler = { url in
|
||||
guard var rawString = try? String(contentsOf: url) else { return }
|
||||
let count = LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let maybeCount = try? LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let count: Int = maybeCount ?? 0
|
||||
CtlSettingsCocoa.shared?.window.callAlert(
|
||||
title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description)
|
||||
)
|
||||
|
@ -137,6 +145,20 @@ public extension SettingsPanesCocoa {
|
|||
}
|
||||
}
|
||||
|
||||
@IBAction func importYahooKeyKeyUserDictionaryDataXPC(_: NSButton) {
|
||||
do {
|
||||
let count = try LMMgr.importYahooKeyKeyUserDictionaryByXPC()
|
||||
CtlSettingsCocoa.shared?.window.callAlert(
|
||||
title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description)
|
||||
)
|
||||
} catch {
|
||||
let error = NSAlert(error: error)
|
||||
error.beginSheetModal(at: CtlSettingsCocoa.shared?.window) { _ in
|
||||
// DO NOTHING.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func importYahooKeyKeyUserDictionaryData(_: NSButton) {
|
||||
guard #available(macOS 10.13, *) else {
|
||||
SettingsPanesCocoa.warnAboutComDlg32Inavailability()
|
||||
|
@ -144,7 +166,7 @@ public extension SettingsPanesCocoa {
|
|||
}
|
||||
let dlgOpenFile = NSOpenPanel()
|
||||
dlgOpenFile.title = NSLocalizedString(
|
||||
"i18n:settings.importFromKimoTxt.buttonText", comment: ""
|
||||
"i18n:settings.importFromKimoTxt.label", comment: ""
|
||||
) + ":"
|
||||
dlgOpenFile.showsResizeIndicator = true
|
||||
dlgOpenFile.showsHiddenFiles = true
|
||||
|
@ -162,7 +184,8 @@ public extension SettingsPanesCocoa {
|
|||
if result == NSApplication.ModalResponse.OK {
|
||||
guard let url = dlgOpenFile.url else { return }
|
||||
guard var rawString = try? String(contentsOf: url) else { return }
|
||||
let count = LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let maybeCount = try? LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let count: Int = maybeCount ?? 0
|
||||
window.callAlert(title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,12 +186,10 @@ public struct VwrSettingsPaneDictionary: View {
|
|||
}
|
||||
Section {
|
||||
UserDef.kAllowBoostingSingleKanjiAsUserPhrase.bind($allowBoostingSingleKanjiAsUserPhrase).render()
|
||||
} footer: {
|
||||
HStack {
|
||||
Spacer()
|
||||
Button {
|
||||
LabeledContent("i18n:settings.importFromKimoTxt.label") {
|
||||
Button("…") {
|
||||
Self.dlgOpenFile.title = NSLocalizedString(
|
||||
"i18n:settings.importFromKimoTxt.buttonText", comment: ""
|
||||
"i18n:settings.importFromKimoTxt.label", comment: ""
|
||||
) + ":"
|
||||
Self.dlgOpenFile.showsResizeIndicator = true
|
||||
Self.dlgOpenFile.showsHiddenFiles = true
|
||||
|
@ -207,15 +205,27 @@ public struct VwrSettingsPaneDictionary: View {
|
|||
defer { keykeyImportButtonDisabled = false }
|
||||
guard let url = Self.dlgOpenFile.url else { return }
|
||||
guard var rawString = try? String(contentsOf: url) else { return }
|
||||
let count = LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let maybeCount = try? LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let count: Int = maybeCount ?? 0
|
||||
window.callAlert(title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description))
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Text(verbatim: "i18n:settings.importFromKimoTxt.buttonText".localized + " (TXT)…")
|
||||
}.disabled(keykeyImportButtonDisabled)
|
||||
}
|
||||
}
|
||||
Button("i18n:settings.importFromKimoTxt.DirectlyImport") {
|
||||
do {
|
||||
let count = try LMMgr.importYahooKeyKeyUserDictionaryByXPC()
|
||||
CtlSettingsUI.shared?.window.callAlert(
|
||||
title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description)
|
||||
)
|
||||
} catch {
|
||||
let error = NSAlert(error: error)
|
||||
error.beginSheetModal(at: CtlSettingsUI.shared?.window) { _ in
|
||||
// DO NOTHING.
|
||||
}
|
||||
}
|
||||
}
|
||||
}.disabled(keykeyImportButtonDisabled)
|
||||
}
|
||||
}.formStyled()
|
||||
}
|
||||
|
|
|
@ -351,7 +351,7 @@ public extension UserDef {
|
|||
)
|
||||
case .kCassetteEnabled: return .init(
|
||||
userDef: self, shortTitle: "Enable cassette mode, suppressing phonabet input",
|
||||
description: "Cassette mode is similar to the CIN support of the Yahoo Kimo IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)."
|
||||
description: "Cassette mode is similar to the CIN support of the Yahoo! KeyKey IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)."
|
||||
)
|
||||
case .kCNS11643Enabled: return .init(userDef: self, shortTitle: "i18n:UserDef.kCNS11643Enabled.shortTitle")
|
||||
case .kSymbolInputEnabled: return .init(
|
||||
|
|
|
@ -52,7 +52,8 @@ case 2:
|
|||
print("[Kimo Import] Given file path is either invalid or not accessible. Read access is needed for this operation.")
|
||||
exit(1)
|
||||
}
|
||||
let count = LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let maybeCount = try? LMMgr.importYahooKeyKeyUserDictionary(text: &rawString)
|
||||
let count: Int = maybeCount ?? 0
|
||||
let msg = String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description)
|
||||
print("[Kimo Import] \(msg)")
|
||||
exit(0)
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"Candidate keys cannot contain space." = "Candidate keys cannot contain space.";
|
||||
"Candidate Layout:" = "Candidate Layout:";
|
||||
"Candidate Size:" = "Candidate Size:";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo Kimo IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "Cassette mode is similar to the CIN support of the Yahoo Kimo IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated).";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo! KeyKey IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "Cassette mode is similar to the CIN support of the Yahoo! KeyKey IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated).";
|
||||
"Cassette" = "Cassette";
|
||||
"catAlphabets" = "Alphabets";
|
||||
"catBracketedASCII" = "BracketASCII";
|
||||
|
@ -195,11 +195,14 @@
|
|||
"i18n:aboutWindow.OK_BUTTON" = "I Accept";
|
||||
"i18n:aboutWindow.WEBSITE_BUTTON" = "Website";
|
||||
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "Candidates cannot have those keys who are assigned for other purposes.";
|
||||
"i18n:KimoDataImportError.connectionFailure.errMsg" = "Directly Import is not available due to an NSConnection failure.\n\n- Please enable Yahoo! KeyKey Input Method and run it prior to performing the current action. vChewing now have just triggered Yahoo! KeyKey Input Method to run, so you can retry the import immediately.\n\n- If this copy of vChewing is compiled by yourself, please double-check the Sandbox Entitlements you have modified.\n\n- If this mac is not an Intel Mac, then Rosetta 2 is required to run Yahoo! KeyKey Input Method.\n\n- If all of the above reasons are not met in this case, then the __objc_empty_cache API might be unavailable in the current system. This API is crucial in order to let Yahoo! KeyKey Input Method run. Please double check the Console.app in your system to see whether there are any crash reports related to Yahoo! KeyKey Input Method.";
|
||||
"i18n:KimoDataImportError.fileHandlerFailure.errMsg" = "Failed in writing new user phrases data.";
|
||||
"i18n:kimoImportButton.DragFileToHere" = "DRAG FILE TO HERE";
|
||||
"i18n:securityAgentHelper.warningMessage.footer" = "When this message shows up, vChewing has already attempted to call DisableSecureEventInput() trying to make itself selectable in the input method menu again. Your suggested further steps:\n\n0. Keep a screenshot of this dialog (if you don't have one) for further purposes.\n\n1. If vChewing is still not selectable in the input method menu, you are suggested to manually terminate the processes listed above to force-release their SecureEventInput states. This will make vChewing available immediately.\n\n2. If the process belongs to an app from Mac App Store, please report its abuse of SecureEventInput to Apple. Apple may take actions to such apps if necessary, including pulling them off from the Mac App Store until the problem gets solved by the developers of such apps.\n\n3. Whether this process is from Mac App Store or not, you report this abuse to the related app vendor / developer. You may give them the screenshot of this alert message since it should have enough information to help the vendor / developer troubleshoot the issue.";
|
||||
"i18n:securityAgentHelper.warningMessage.header" = "vChewing has detected that the following background processes are abusing the SecureEventInput, hindering all 3rd-party input methods from being able to switch to.\n\nIt is fine to use SecureEventInput for sensitive input fields. However, an app calling EnableSecureEventInput() is responsible to call DisableSecureEventInput() immediately right after the input field loses focus. This situation may also happen if an app is hanging in the background (or working as a helper application in the background) with its SecureEventInput left enabled.\n\nThe found processes are:";
|
||||
"i18n:securityAgentHelper.warningMessage.title" = "SecureEventInput Abuse Detected";
|
||||
"i18n:settings.importFromKimoTxt.buttonText" = "Import Yahoo! KeyKey User Dictionary File";
|
||||
"i18n:settings.importFromKimoTxt.label" = "Import Yahoo! KeyKey User Dictionary file";
|
||||
"i18n:settings.importFromKimoTxt.DirectlyImport" = "Directly Import";
|
||||
"i18n:settings.importFromKimoTxt.finishedCount:%@" = "Imported %@ new records.";
|
||||
"i18n:settings.shiftKeyASCIITogle.description" = "This feature only needs to parse consecutive NSEvents passed by macOS built-in InputMethodKit framework, hence no necessity of asking end-users for extra privileges of monitoring global keyboard inputs. You are free to investigate our codebase or reverse-engineer this input method to see whether the above statement is trustable. Also, this Shift-key toggle won't work if CapsLock is ON.";
|
||||
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "This won't affect the same feature offered by macOS since 10.14 Mojave and later.";
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
"Candidate Layout:" = "入力候補陳列の仕様";
|
||||
"Candidate Layout:" = "候補陳列の仕様";
|
||||
"Candidate Size:" = "候補文字の字号:";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo Kimo IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "カセットモードは、CIN ファイルを用いて、(五筆や倉頡や嘸蝦米などのような)筆画入力を機能拡張できるモードである。ですが、単なる予備機能として提供したもののため、使いやすいかどうか、RIME や OpenVanilla などに比べられないかもしれん。";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo! KeyKey IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "カセットモードは、CIN ファイルを用いて、(五筆や倉頡や嘸蝦米などのような)筆画入力を機能拡張できるモードである。ですが、単なる予備機能として提供したもののため、使いやすいかどうか、RIME や OpenVanilla などに比べられないかもしれん。";
|
||||
"Cassette" = "カセ設定";
|
||||
"catAlphabets" = "字母";
|
||||
"catBracketedASCII" = "括付英数";
|
||||
|
@ -195,11 +195,14 @@
|
|||
"i18n:aboutWindow.OK_BUTTON" = "うむ";
|
||||
"i18n:aboutWindow.WEBSITE_BUTTON" = "公式HP";
|
||||
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "他の用途に指定したキーは言選りには使えません。";
|
||||
"i18n:KimoDataImportError.connectionFailure.errMsg" = "「直接読み込む」作動失敗:両アプリの NSConnection 通信はできませんでした。\n\n- 「直接読込」を続行する前に、まずは Yahoo! KeyKey そのアプリを実行すること。弊アプリは Yahoo! KeyKey をすでに1度呼び覚ませてみたため、すぐにもう一度「直接読込」するのも可能です。\n\n- 今の実行中の弊アプリはご自分で Xcode で組み立てた場合、Xcode プロジェクトの Sandbox Entitlements の配置の正しさをご確認ください。\n\n- 今のパソコンは Intel Mac ではない場合、必ず Rosetta 2 をご実装ください。Yahoo! KeyKey の実行には Rosetta 2 は必要条件です。\n\n- 上記のすべての状況を排除したら、多分「__objc_empty_cache」という肝心なる API は今のこのシステムでもう利用できないと推測できます。この API がない限り、Yahoo! KeyKey の実行は不可能です。今のこのシステムの「Console.app」で Yahoo! KeyKey の故障報告の有無をご確認ください。";
|
||||
"i18n:KimoDataImportError.fileHandlerFailure.errMsg" = "新しい資料はユーザー辞書データファイルに書き込むのはできませんでした。";
|
||||
"i18n:kimoImportButton.DragFileToHere" = "ここにドラッグして";
|
||||
"i18n:securityAgentHelper.warningMessage.footer" = "このメッセージが出た時に、威注音がすでに「DisableSecureEventInput()」を実行してみました。これで入力ソースメニューで威注音は利用できる状態になったかもしれませんが、下記のステップはおすすめです:\n\nイ)今のこのメッセージの画面のスクリーンショットを撮って置いてください。後ほど使えます。\n\nロ)もし、今でも入力ソースメニューで威注音は利用できぬ状態でしたら、上記のプロセスを(強制)中止してください。そうすれば、それぞれのSecureEventInput状態は解消できて、入力ソースメニューで威注音はすぐ利用できることになります。\n\nハ)もし、該当プロセスは Mac App Store のアプリからのものでしたら、該当アプリを Apple 社にご通報ください。状況と必要性次第、該当アプリは Mac App Store からしばらく取り下がて、支障解決まで Mac App Store 提供中止になるかもしれません。\n\nニ)該当プロセスは Mac App Store からダウンロードしたものか否か、それぞれの開発元にこの支障をご通報ください。今のこのメッセージの画面のスクリーンショットを該当開発元に送れば、必要なる情報は該当開発元に全部お知らせすることができます。";
|
||||
"i18n:securityAgentHelper.warningMessage.header" = "威注音入力アプリ(略称「威注音」)は「他のバックグラウンド・プロセスがSecureEventInputを正しく利用していない」と検出しました。このような不正利用は「システム内蔵入力以外の全ての入力アプリがメニューで灰色状態で選べなくて使えない」の元凶です。\n\nセンシティブな資料の記入どころでSecureEventInputをEnableSecureEventInput()で使うのは当然ですが、「入力中」状態が終わった後必ずDisableSecureEventInput()で状態解消すべきだと義務です。いくつかヘルパーアプリも、あるいはSecureEventInputを呼び起こしてからすぐ固まったアプリも、この状態になりやすいです。特に、他のアプリの画面へ切り替えたとしても、固まったアプリのSecureEventInput状態は自動的に解消できません。\n\n検出した該当プロセスは:";
|
||||
"i18n:securityAgentHelper.warningMessage.title" = "SecureEventInput の不正利用が検出";
|
||||
"i18n:settings.importFromKimoTxt.buttonText" = "Yahoo! KeyKey ユーザー辞書ファイルを読込";
|
||||
"i18n:settings.importFromKimoTxt.label" = "Yahoo! KeyKey ユーザー辞書ファイルを読込";
|
||||
"i18n:settings.importFromKimoTxt.DirectlyImport" = "直接読込";
|
||||
"i18n:settings.importFromKimoTxt.finishedCount:%@" = "新しい記録は %@ つ読み込みました。";
|
||||
"i18n:settings.shiftKeyASCIITogle.description" = "この機能の利用する NSEvent は、macOS 内蔵の入力アプリ共用モジュール「InputMethodKit」から提供した NSEvent のみであり、その NSEvent 文脈関係で「Shift キーは1回押したかどうか」と判断することはできる。この事実に疑いを持つ者は、本アプリのソースコードを審査するか、あるいは本アプリを逆向工程(分解工学, いわゆる「Reverse-Engineering」)するがよい。なお、Shiftキーによるこの切り替えは、CapsLockがONの時には効かぬ。";
|
||||
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "macOS 10.14 からのシステム内蔵機能としての同じ機能に影響しません。";
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"Candidate keys cannot contain space." = "选字键不得包含空格。";
|
||||
"Candidate Layout:" = "候选字窗布局:";
|
||||
"Candidate Size:" = "候选字窗字号:";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo Kimo IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "磁带模式类似于雅虎奇摩输入法的 CIN 支援模式,允许使用者借由 CIN 表格档案扩充自己想要的笔画输入法(比如五笔、仓颉、呒虾米,等)。然而,因为威注音不打算为了这个功能而牺牲注音输入的体验,所以这个磁带模式的体验对于已经习惯 RIME 或者 OpenVanilla 的人群而言可能会稍微麻烦一些。";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo! KeyKey IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "磁带模式类似于雅虎奇摩输入法的 CIN 支援模式,允许使用者借由 CIN 表格档案扩充自己想要的笔画输入法(比如五笔、仓颉、呒虾米,等)。然而,因为威注音不打算为了这个功能而牺牲注音输入的体验,所以这个磁带模式的体验对于已经习惯 RIME 或者 OpenVanilla 的人群而言可能会稍微麻烦一些。";
|
||||
"Cassette" = "磁带设定";
|
||||
"catAlphabets" = "字母";
|
||||
"catBracketedASCII" = "括英";
|
||||
|
@ -195,11 +195,14 @@
|
|||
"i18n:aboutWindow.OK_BUTTON" = "确定";
|
||||
"i18n:aboutWindow.WEBSITE_BUTTON" = "网站";
|
||||
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "无法将已挪作他用的按键设为选字键。";
|
||||
"i18n:KimoDataImportError.connectionFailure.errMsg" = "「直接汇入」功能失败:无法成功建立 NSConnection 跨执行绪通讯。\n\n- 在执行该步骤之前,请确保奇摩输入法有在运行。威注音输入法已经在此刻发起了一次对奇摩输入法的运行呼叫请求,于是您可以立刻再次重试。\n\n- 如果您当前运行的威注音输入法的程式包是您自己建置的话,请检查专案内的 Sandbox 权能组态设定档案(Entitlements)、看看是否发生了与此有关的内容变更。\n\n- 如果这台 Mac 并未使用 Intel CPU 的话,请先安装 Rosetta 2,否则奇摩输入法将无法运作。\n\n- 如果以上状况都被排除了的话,那么 __objc_empty_cache 这个 API 可能在当前版本的作业系统内被移除了。这个 API 对奇摩输入法而言至关重要。请检查您当前的作业系统内建的「系统监视程式 Console.app」,确认一下是否有与奇摩输入法有关的程式崩溃报告。";
|
||||
"i18n:KimoDataImportError.fileHandlerFailure.errMsg" = "没能将新的资料成功写入到使用者自订语汇辞典当中。";
|
||||
"i18n:kimoImportButton.DragFileToHere" = "请将档案拽到这边";
|
||||
"i18n:securityAgentHelper.warningMessage.footer" = "当这则讯息呈现出来的时候,威注音已经尝试呼叫 `DisableSecureEventInput()` 来试图解除这个状态。以下是威注音建议您采取的行动:\n\n0. 将这则讯息视窗留一份屏幕撷图、以备接下来的需要。\n\n1. 如果输入法选单内的威注音仍旧处于无法选取的状态(下文简称「灰色不可用状态」),则请考虑结束上述进程、以迫使其释放各自的 SecureEventInput 状态。这将立刻解除威注音的灰色不可用状态。\n\n2. 如果该进程所属的 App 来自于 Mac App Store 的话,请向 Apple 检举其对 SecureEventInput 的滥用。Apple 会在必要的情况下对这类 App 采取措施,比如:临时下架,直至软件开发者解决相关故障。\n\n3. 无论该进程是否来自于 Mac App Store,也都请您向相关的开发者/提供方提报该故障。您可以将这则讯息的屏幕撷图给他们看,因为里面已经包含了用以检测该故障的必要资讯。";
|
||||
"i18n:securityAgentHelper.warningMessage.header" = "威注音有检测到下述后台进程有在滥用 SecureEventInput。这种滥用会导致系统内的所有第三方输入法全都无法正常使用(在输入法选单内会变成灰色)。\n\n针对需要填写敏感数据的场合,使用 SecureEventInput 无可厚非。但是,用 EnableSecureEventInput() 开启该模式之后,就有义务在输入窗格失焦的那一刻呼叫 DisableSecureEventInput() 来结束这种状态。这种状态还常见于后台辅助 App 当中、或者某个 App 在叫出该模式之后失去响应(这样的话,哪怕被切换到后台,SecureEventInput 也不会自动解除)。\n\n被侦测到的进程如下:";
|
||||
"i18n:securityAgentHelper.warningMessage.title" = "检测到对 SecureEventInput 的滥用行为";
|
||||
"i18n:settings.importFromKimoTxt.buttonText" = "汇入奇摩输入法自订词资料库";
|
||||
"i18n:settings.importFromKimoTxt.label" = "汇入奇摩输入法自订词资料库";
|
||||
"i18n:settings.importFromKimoTxt.DirectlyImport" = "直接汇入";
|
||||
"i18n:settings.importFromKimoTxt.finishedCount:%@" = "汇入了 %@ 笔新记录。";
|
||||
"i18n:settings.shiftKeyASCIITogle.description" = "该功能只需要对借由 macOS 内建的输入法框架传来的 NSEvent 做上下文分析,自然没有「向使用者寻求系统全局键盘事件监听权限」之必要。您可自行审视敝输入法的原始程式码仓库、或对敝输入法逆向工程,以自行证实此处所言之真假。另注:这个 Shift 键切换开关在 CapsLock 灯亮时无效。";
|
||||
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "这不会影响到自 macOS 10.14 开始的系统内建的同名功能。";
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"Candidate keys cannot contain space." = "選字鍵不得包含空格。";
|
||||
"Candidate Layout:" = "候選字窗佈局:";
|
||||
"Candidate Size:" = "候選字窗字號:";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo Kimo IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "磁帶模式類似於雅虎奇摩輸入法的 CIN 支援模式,允許使用者藉由 CIN 表格檔案擴充自己想要的筆畫輸入法(比如五筆、倉頡、嘸蝦米,等)。然而,因為威注音不打算為了這個功能而犧牲注音輸入的體驗,所以這個磁帶模式的體驗對於已經習慣 RIME 或者 OpenVanilla 的人群而言可能會稍微麻煩一些。";
|
||||
"Cassette mode is similar to the CIN support of the Yahoo! KeyKey IME, allowing users to use their own CIN tables to implement their stroked-based input schema (e.g. Wubi, Cangjie, Boshiamy, etc.) as a plan-B in vChewing IME. However, since vChewing won't compromise its phonabet input mode experience for this cassette mode, users might not feel comfortable enough comparing to their experiences with RIME (recommended) or OpenVanilla (deprecated)." = "磁帶模式類似於雅虎奇摩輸入法的 CIN 支援模式,允許使用者藉由 CIN 表格檔案擴充自己想要的筆畫輸入法(比如五筆、倉頡、嘸蝦米,等)。然而,因為威注音不打算為了這個功能而犧牲注音輸入的體驗,所以這個磁帶模式的體驗對於已經習慣 RIME 或者 OpenVanilla 的人群而言可能會稍微麻煩一些。";
|
||||
"Cassette" = "磁帶設定";
|
||||
"catAlphabets" = "字母";
|
||||
"catBracketedASCII" = "括英";
|
||||
|
@ -195,11 +195,14 @@
|
|||
"i18n:aboutWindow.OK_BUTTON" = "確定";
|
||||
"i18n:aboutWindow.WEBSITE_BUTTON" = "網站";
|
||||
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "無法將已挪作他用的按鍵設為選字鍵。";
|
||||
"i18n:KimoDataImportError.connectionFailure.errMsg" = "「直接匯入」功能失敗:無法成功建立 NSConnection 跨執行緒通訊。\n\n- 在執行該步驟之前,請確保奇摩輸入法有在運行。威注音輸入法已經在此刻發起了一次對奇摩輸入法的運行呼叫請求,於是您可以立刻再次重試。\n\n- 如果您當前運行的威注音輸入法的程式包是您自己建置的話,請檢查專案內的 Sandbox 權能組態設定檔案(Entitlements)、看看是否發生了與此有關的內容變更。\n\n- 如果這台 Mac 並未使用 Intel CPU 的話,請先安裝 Rosetta 2,否則奇摩輸入法將無法運作。\n\n- 如果以上狀況都被排除了的話,那麼 __objc_empty_cache 這個 API 可能在當前版本的作業系統內被移除了。這個 API 對奇摩輸入法而言至關重要。請檢查您當前的作業系統內建的「系統監視程式 Console.app」,確認一下是否有與奇摩輸入法有關的程式崩潰報告。";
|
||||
"i18n:KimoDataImportError.fileHandlerFailure.errMsg" = "沒能將新的資料成功寫入到使用者自訂語彙辭典當中。";
|
||||
"i18n:kimoImportButton.DragFileToHere" = "請將檔案拽到這邊";
|
||||
"i18n:securityAgentHelper.warningMessage.footer" = "當這則訊息呈現出來的時候,威注音已經嘗試呼叫 `DisableSecureEventInput()` 來試圖解除這個狀態。以下是威注音建議您採取的行動:\n\n0. 將這則訊息視窗留一份螢幕擷圖、以備接下來的需要。\n\n1. 如果輸入法選單內的威注音仍舊處於無法選取的狀態(下文簡稱「灰色不可用狀態」),則請考慮結束上述執行緒、以迫使其釋放各自的 SecureEventInput 狀態。這將立刻解除威注音的灰色不可用狀態。\n\n2. 如果該執行緒所屬的 App 來自於 Mac App Store 的話,請向 Apple 檢舉其對 SecureEventInput 的濫用。Apple 會在必要的情況下對這類 App 採取措施,比如:臨時下架,直至軟體研發方解決相關故障。\n\n3. 無論該執行緒是否來自於 Mac App Store,也都請您向相關的研發方/提供方提報該故障。您可以將這則訊息的螢幕擷圖給他們看,因為裡面已經包含了用以偵測該故障的必要資訊。";
|
||||
"i18n:securityAgentHelper.warningMessage.header" = "威注音有偵測到下述後檯執行緒有在濫用 SecureEventInput。這種濫用會導致系統內的所有第三方輸入法全都無法正常使用(在輸入法選單內會變成灰色)。\n\n針對需要填寫敏感資料的場合,使用 SecureEventInput 無可厚非。但是,用 EnableSecureEventInput() 開啟該模式之後,就有義務在輸入窗格失焦的那一刻呼叫 DisableSecureEventInput() 來結束這種狀態。這種狀態還常見於後檯輔助 App 當中、或者某個 App 在叫出該模式之後失去回應(這樣的話,哪怕被切換到後檯,SecureEventInput 也不會自動解除)。\n\n被偵測到的執行緒如下:";
|
||||
"i18n:securityAgentHelper.warningMessage.title" = "偵測到對 SecureEventInput 的濫用行為";
|
||||
"i18n:settings.importFromKimoTxt.buttonText" = "匯入奇摩輸入法自訂詞資料庫";
|
||||
"i18n:settings.importFromKimoTxt.label" = "匯入奇摩輸入法自訂詞資料庫";
|
||||
"i18n:settings.importFromKimoTxt.DirectlyImport" = "直接匯入";
|
||||
"i18n:settings.importFromKimoTxt.finishedCount:%@" = "匯入了 %@ 筆新記錄。";
|
||||
"i18n:settings.shiftKeyASCIITogle.description" = "該功能只需要對藉由 macOS 內建的輸入法框架傳來的 NSEvent 做上下文分析,自然沒有「向使用者尋求系統全局鍵盤事件監聽權限」之必要。您可自行審視敝輸入法的原始程式碼倉庫、或對敝輸入法逆向工程,以自行證實此處所言之真假。另註:這個 Shift 鍵切換開關在 CapsLock 燈亮時無效。";
|
||||
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "這不會影響到自 macOS 10.14 開始的系統內建的同名功能。";
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
</array>
|
||||
<key>com.apple.security.temporary-exception.mach-register.global-name</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)_Connection</string>
|
||||
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
|
||||
<array>
|
||||
<string>YahooKeyKeyService</string>
|
||||
</array>
|
||||
<key>com.apple.security.temporary-exception.shared-preference.read-only</key>
|
||||
<string>org.atelierInmu.inputmethod.vChewing</string>
|
||||
</dict>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 60;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
|
@ -34,6 +34,7 @@
|
|||
5BC5E01E28DDE4770094E427 /* NotifierUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E01D28DDE4770094E427 /* NotifierUI */; };
|
||||
5BC5E02128DDEFE00094E427 /* TooltipUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02028DDEFE00094E427 /* TooltipUI */; };
|
||||
5BC5E02428DE07860094E427 /* PopupCompositionBuffer in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02328DE07860094E427 /* PopupCompositionBuffer */; };
|
||||
5BC8EB7E2B7E1CC1004F5101 /* KimoDataReader in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC8EB7D2B7E1CC1004F5101 /* KimoDataReader */; };
|
||||
5BDB7A3928D4824A001AC277 /* BookmarkManager in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3828D4824A001AC277 /* BookmarkManager */; };
|
||||
5BDB7A3B28D4824A001AC277 /* FolderMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3A28D4824A001AC277 /* FolderMonitor */; };
|
||||
5BDB7A3D28D4824A001AC277 /* Hotenka in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3C28D4824A001AC277 /* Hotenka */; };
|
||||
|
@ -129,6 +130,7 @@
|
|||
5B963CA128D5C22D00DCEE88 /* vChewing_SwiftExtension */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_SwiftExtension; path = Packages/vChewing_SwiftExtension; sourceTree = "<group>"; };
|
||||
5B98114628D6198000CBC605 /* vChewing_PinyinPhonaConverter */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_PinyinPhonaConverter; path = Packages/vChewing_PinyinPhonaConverter; sourceTree = "<group>"; };
|
||||
5BA8C30128DEFE4F004C5CC4 /* vChewing_CandidateWindow */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_CandidateWindow; path = Packages/vChewing_CandidateWindow; sourceTree = "<group>"; };
|
||||
5BAD29D12B7E1A1B0013D695 /* vChewing_KimoDataReader */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_KimoDataReader; path = Packages/vChewing_KimoDataReader; sourceTree = "<group>"; };
|
||||
5BAD67E12ADAB62D005A4842 /* HangarRash_SwiftyCapsLockToggler */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = HangarRash_SwiftyCapsLockToggler; path = Packages/HangarRash_SwiftyCapsLockToggler; sourceTree = "<group>"; };
|
||||
5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = "<group>"; };
|
||||
5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = "<group>"; };
|
||||
|
@ -193,6 +195,7 @@
|
|||
files = (
|
||||
5BC5E02428DE07860094E427 /* PopupCompositionBuffer in Frameworks */,
|
||||
5B65FB342A9518DA007EEFB0 /* MainAssembly in Frameworks */,
|
||||
5BC8EB7E2B7E1CC1004F5101 /* KimoDataReader in Frameworks */,
|
||||
5BDB7A4528D4824A001AC277 /* ShiftKeyUpChecker in Frameworks */,
|
||||
5BFC63CC28D49BBC004A77B7 /* UpdateSputnik in Frameworks */,
|
||||
5BDB7A4128D4824A001AC277 /* Megrez in Frameworks */,
|
||||
|
@ -341,6 +344,7 @@
|
|||
5B963C9B28D5BE4100DCEE88 /* vChewing_CocoaExtension */,
|
||||
5BDB7A3228D47587001AC277 /* vChewing_Hotenka */,
|
||||
5BFC63C728D49511004A77B7 /* vChewing_IMKUtils */,
|
||||
5BAD29D12B7E1A1B0013D695 /* vChewing_KimoDataReader */,
|
||||
5BFC63CD28D4AC98004A77B7 /* vChewing_LangModelAssembly */,
|
||||
5B65FB322A9518C9007EEFB0 /* vChewing_MainAssembly */,
|
||||
5BDB7A3328D47587001AC277 /* vChewing_Megrez */,
|
||||
|
@ -496,6 +500,7 @@
|
|||
5BA8C30228DF0360004C5CC4 /* CandidateWindow */,
|
||||
5B765F08293A253C00122315 /* PhraseEditorUI */,
|
||||
5B65FB332A9518DA007EEFB0 /* MainAssembly */,
|
||||
5BC8EB7D2B7E1CC1004F5101 /* KimoDataReader */,
|
||||
);
|
||||
productName = vChewing;
|
||||
productReference = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */;
|
||||
|
@ -556,6 +561,7 @@
|
|||
);
|
||||
mainGroup = 6A0D4E9215FC0CFA00ABF4B3;
|
||||
packageReferences = (
|
||||
5BC8EB7C2B7E1CC1004F5101 /* XCLocalSwiftPackageReference "Packages/vChewing_KimoDataReader" */,
|
||||
);
|
||||
productRefGroup = 6A0D4EA315FC0D2D00ABF4B3 /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -1129,6 +1135,13 @@
|
|||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCLocalSwiftPackageReference section */
|
||||
5BC8EB7C2B7E1CC1004F5101 /* XCLocalSwiftPackageReference "Packages/vChewing_KimoDataReader" */ = {
|
||||
isa = XCLocalSwiftPackageReference;
|
||||
relativePath = Packages/vChewing_KimoDataReader;
|
||||
};
|
||||
/* End XCLocalSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
5B40113828D7050D00A9D4CB /* Shared */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
|
@ -1174,6 +1187,10 @@
|
|||
isa = XCSwiftPackageProductDependency;
|
||||
productName = PopupCompositionBuffer;
|
||||
};
|
||||
5BC8EB7D2B7E1CC1004F5101 /* KimoDataReader */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = KimoDataReader;
|
||||
};
|
||||
5BDB7A3828D4824A001AC277 /* BookmarkManager */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = BookmarkManager;
|
||||
|
|
Loading…
Reference in New Issue