Repo // Add KimoDataReader using NSConnection.

This commit is contained in:
ShikiSuen 2024-02-15 17:19:41 +08:00
parent 424a736c8e
commit b479acf779
21 changed files with 620 additions and 38 deletions

View File

@ -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
---

View File

@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

View File

@ -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"]
),
]
)

View File

@ -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.

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,10 @@
@testable import ObjcKimoCommunicator
import XCTest
final class KimoDataReaderTests: XCTestCase {
//
func testExample() throws {
let shared = ObjcKimoCommunicator()
print(shared.establishConnection())
}
}

View File

@ -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 {} \;

View File

@ -21,6 +21,7 @@ let package = Package(
.package(path: "../vChewing_CocoaExtension"), .package(path: "../vChewing_CocoaExtension"),
.package(path: "../vChewing_Hotenka"), .package(path: "../vChewing_Hotenka"),
.package(path: "../vChewing_IMKUtils"), .package(path: "../vChewing_IMKUtils"),
.package(path: "../vChewing_KimoDataReader"),
.package(path: "../vChewing_LangModelAssembly"), .package(path: "../vChewing_LangModelAssembly"),
.package(path: "../vChewing_Megrez"), .package(path: "../vChewing_Megrez"),
.package(path: "../vChewing_NotifierUI"), .package(path: "../vChewing_NotifierUI"),
@ -43,6 +44,7 @@ let package = Package(
.product(name: "FolderMonitor", package: "DanielGalasko_FolderMonitor"), .product(name: "FolderMonitor", package: "DanielGalasko_FolderMonitor"),
.product(name: "Hotenka", package: "vChewing_Hotenka"), .product(name: "Hotenka", package: "vChewing_Hotenka"),
.product(name: "IMKUtils", package: "vChewing_IMKUtils"), .product(name: "IMKUtils", package: "vChewing_IMKUtils"),
.product(name: "KimoDataReader", package: "vChewing_KimoDataReader"),
.product(name: "LangModelAssembly", package: "vChewing_LangModelAssembly"), .product(name: "LangModelAssembly", package: "vChewing_LangModelAssembly"),
.product(name: "Megrez", package: "vChewing_Megrez"), .product(name: "Megrez", package: "vChewing_Megrez"),
.product(name: "NotifierUI", package: "vChewing_NotifierUI"), .product(name: "NotifierUI", package: "vChewing_NotifierUI"),

View File

@ -6,16 +6,78 @@
// marks, or product names of Contributor, except as required to fulfill notice // marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License. // requirements defined in MIT License.
import AppKit
import Foundation import Foundation
import KimoDataReader
import LineReader import LineReader
import Shared import Shared
public extension LMMgr { 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 /// 使 TXT
/// - Parameter rawString: TXT /// - Parameter rawString: TXT
/// - Returns: /// - Returns:
@discardableResult static func importYahooKeyKeyUserDictionary(text rawString: inout String) -> Int { @discardableResult static func importYahooKeyKeyUserDictionary(text rawString: inout String) throws -> Int {
var allPhrasesCHT = [UserPhrase]() var allPhrasesCHT = [UserPhrase]()
var allPhrasesCHS = [UserPhrase]()
rawString.enumerateLines { currentLine, _ in rawString.enumerateLines { currentLine, _ in
let cells = currentLine.split(separator: "\t") let cells = currentLine.split(separator: "\t")
guard cells.count >= 3, cells.first != "#", cells.first != "MJSR" else { return } 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.isValid, !phraseCHT.isDuplicated else { return }
guard !(phraseCHT.value.count == 1 && phraseCHT.keyArray.count == 1) else { return } guard !(phraseCHT.value.count == 1 && phraseCHT.keyArray.count == 1) else { return }
allPhrasesCHT.append(phraseCHT) 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 } guard !allPhrasesCHT.isEmpty else { return 0 }
let allPhrasesCHS = allPhrasesCHT.compactMap { chtPhrase in
let chsPhrase = chtPhrase.crossConverted guard Self.batchImportUserPhrasePairs(allPhrasesCHT: allPhrasesCHT, allPhrasesCHS: allPhrasesCHS) else {
return chsPhrase.isValid && !chsPhrase.isDuplicated ? chsPhrase : nil throw KimoDataImportError.fileHandlerFailure
}.deduplicated }
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 outputStrCHS = allPhrasesCHS.map(\.description).joined(separator: "\n")
let outputStrCHT = allPhrasesCHT.map(\.description).joined(separator: "\n") let outputStrCHT = allPhrasesCHT.map(\.description).joined(separator: "\n")
var outputDataCHS = "\(outputStrCHS)\n".data(using: .utf8) ?? .init([]) var outputDataCHS = "\(outputStrCHS)\n".data(using: .utf8) ?? .init([])
@ -40,7 +115,7 @@ public extension LMMgr {
let fileHandlerCHS = try? FileHandle(forUpdating: urlCHS) let fileHandlerCHS = try? FileHandle(forUpdating: urlCHS)
let fileHandlerCHT = try? FileHandle(forUpdating: urlCHT) 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 { defer {
fileHandlerCHS.closeFile() fileHandlerCHS.closeFile()
fileHandlerCHT.closeFile() fileHandlerCHT.closeFile()
@ -63,12 +138,7 @@ public extension LMMgr {
} }
fileHandlerCHT.seekToEndOfFile() fileHandlerCHT.seekToEndOfFile()
fileHandlerCHT.write(outputDataCHT) fileHandlerCHT.write(outputDataCHT)
return true
let result = allPhrasesCHT.count
if result > 0 {
Broadcaster.shared.eventForReloadingPhraseEditor = .init()
}
return result
} }
} }

View File

@ -66,9 +66,16 @@ public extension SettingsPanesCocoa {
NSStackView.buildSection(width: contentWidth) { NSStackView.buildSection(width: contentWidth) {
UserDef.kAllowBoostingSingleKanjiAsUserPhrase.render(fixWidth: contentWidth) UserDef.kAllowBoostingSingleKanjiAsUserPhrase.render(fixWidth: contentWidth)
NSStackView.build(.horizontal) { NSStackView.build(.horizontal) {
"i18n:settings.importFromKimoTxt.buttonText".makeNSLabel(fixWidth: contentWidth) "i18n:settings.importFromKimoTxt.label".makeNSLabel(fixWidth: contentWidth)
NSView() NSView()
importKimoDragButton() NSStackView.build(.horizontal, spacing: 4) {
importKimoDragButton()
NSButton(
"i18n:settings.importFromKimoTxt.DirectlyImport",
target: self,
action: #selector(importYahooKeyKeyUserDictionaryDataXPC(_:))
)
}
} }
}?.boxed() }?.boxed()
NSView().makeSimpleConstraint(.height, relation: .equal, value: NSFont.systemFontSize) NSView().makeSimpleConstraint(.height, relation: .equal, value: NSFont.systemFontSize)
@ -78,7 +85,8 @@ public extension SettingsPanesCocoa {
func importKimoDragButton() -> NSFileDragRetrieverButton { func importKimoDragButton() -> NSFileDragRetrieverButton {
dragRetrieverKimo.postDragHandler = { url in dragRetrieverKimo.postDragHandler = { url in
guard var rawString = try? String(contentsOf: 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
CtlSettingsCocoa.shared?.window.callAlert( CtlSettingsCocoa.shared?.window.callAlert(
title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description) 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) { @IBAction func importYahooKeyKeyUserDictionaryData(_: NSButton) {
guard #available(macOS 10.13, *) else { guard #available(macOS 10.13, *) else {
SettingsPanesCocoa.warnAboutComDlg32Inavailability() SettingsPanesCocoa.warnAboutComDlg32Inavailability()
@ -144,7 +166,7 @@ public extension SettingsPanesCocoa {
} }
let dlgOpenFile = NSOpenPanel() let dlgOpenFile = NSOpenPanel()
dlgOpenFile.title = NSLocalizedString( dlgOpenFile.title = NSLocalizedString(
"i18n:settings.importFromKimoTxt.buttonText", comment: "" "i18n:settings.importFromKimoTxt.label", comment: ""
) + ":" ) + ":"
dlgOpenFile.showsResizeIndicator = true dlgOpenFile.showsResizeIndicator = true
dlgOpenFile.showsHiddenFiles = true dlgOpenFile.showsHiddenFiles = true
@ -162,7 +184,8 @@ public extension SettingsPanesCocoa {
if result == NSApplication.ModalResponse.OK { if result == NSApplication.ModalResponse.OK {
guard let url = dlgOpenFile.url else { return } guard let url = dlgOpenFile.url else { return }
guard var rawString = try? String(contentsOf: 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)) window.callAlert(title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description))
} }
} }

View File

@ -186,12 +186,10 @@ public struct VwrSettingsPaneDictionary: View {
} }
Section { Section {
UserDef.kAllowBoostingSingleKanjiAsUserPhrase.bind($allowBoostingSingleKanjiAsUserPhrase).render() UserDef.kAllowBoostingSingleKanjiAsUserPhrase.bind($allowBoostingSingleKanjiAsUserPhrase).render()
} footer: { LabeledContent("i18n:settings.importFromKimoTxt.label") {
HStack { Button("") {
Spacer()
Button {
Self.dlgOpenFile.title = NSLocalizedString( Self.dlgOpenFile.title = NSLocalizedString(
"i18n:settings.importFromKimoTxt.buttonText", comment: "" "i18n:settings.importFromKimoTxt.label", comment: ""
) + ":" ) + ":"
Self.dlgOpenFile.showsResizeIndicator = true Self.dlgOpenFile.showsResizeIndicator = true
Self.dlgOpenFile.showsHiddenFiles = true Self.dlgOpenFile.showsHiddenFiles = true
@ -207,15 +205,27 @@ public struct VwrSettingsPaneDictionary: View {
defer { keykeyImportButtonDisabled = false } defer { keykeyImportButtonDisabled = false }
guard let url = Self.dlgOpenFile.url else { return } guard let url = Self.dlgOpenFile.url else { return }
guard var rawString = try? String(contentsOf: 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)) window.callAlert(title: String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description))
} }
} }
} }
} label: { }
Text(verbatim: "i18n:settings.importFromKimoTxt.buttonText".localized + " (TXT)…") Button("i18n:settings.importFromKimoTxt.DirectlyImport") {
}.disabled(keykeyImportButtonDisabled) 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() }.formStyled()
} }

View File

@ -351,7 +351,7 @@ public extension UserDef {
) )
case .kCassetteEnabled: return .init( case .kCassetteEnabled: return .init(
userDef: self, shortTitle: "Enable cassette mode, suppressing phonabet input", 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 .kCNS11643Enabled: return .init(userDef: self, shortTitle: "i18n:UserDef.kCNS11643Enabled.shortTitle")
case .kSymbolInputEnabled: return .init( case .kSymbolInputEnabled: return .init(

View File

@ -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.") print("[Kimo Import] Given file path is either invalid or not accessible. Read access is needed for this operation.")
exit(1) 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) let msg = String(format: "i18n:settings.importFromKimoTxt.finishedCount:%@".localized, count.description)
print("[Kimo Import] \(msg)") print("[Kimo Import] \(msg)")
exit(0) exit(0)

View File

@ -63,7 +63,7 @@
"Candidate keys cannot contain space." = "Candidate keys cannot contain space."; "Candidate keys cannot contain space." = "Candidate keys cannot contain space.";
"Candidate Layout:" = "Candidate Layout:"; "Candidate Layout:" = "Candidate Layout:";
"Candidate Size:" = "Candidate Size:"; "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"; "Cassette" = "Cassette";
"catAlphabets" = "Alphabets"; "catAlphabets" = "Alphabets";
"catBracketedASCII" = "BracketASCII"; "catBracketedASCII" = "BracketASCII";
@ -195,11 +195,14 @@
"i18n:aboutWindow.OK_BUTTON" = "I Accept"; "i18n:aboutWindow.OK_BUTTON" = "I Accept";
"i18n:aboutWindow.WEBSITE_BUTTON" = "Website"; "i18n:aboutWindow.WEBSITE_BUTTON" = "Website";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "Candidates cannot have those keys who are assigned for other purposes."; "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: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.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.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: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.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: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."; "i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "This won't affect the same feature offered by macOS since 10.14 Mojave and later.";

View File

@ -64,7 +64,7 @@
"Candidate Layout:" = "入力候補陳列の仕様"; "Candidate Layout:" = "入力候補陳列の仕様";
"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)." = "カセットモードは、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" = "カセ設定"; "Cassette" = "カセ設定";
"catAlphabets" = "字母"; "catAlphabets" = "字母";
"catBracketedASCII" = "括付英数"; "catBracketedASCII" = "括付英数";
@ -195,11 +195,14 @@
"i18n:aboutWindow.OK_BUTTON" = "うむ"; "i18n:aboutWindow.OK_BUTTON" = "うむ";
"i18n:aboutWindow.WEBSITE_BUTTON" = "公式HP"; "i18n:aboutWindow.WEBSITE_BUTTON" = "公式HP";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "他の用途に指定したキーは言選りには使えません。"; "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: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.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.header" = "威注音入力アプリ略称「威注音」は「他のバックグラウンド・プロセスがSecureEventInputを正しく利用していない」と検出しました。このような不正利用は「システム内蔵入力以外の全ての入力アプリがメニューで灰色状態で選べなくて使えない」の元凶です。\n\nセンシティブな資料の記入どころでSecureEventInputをEnableSecureEventInput()で使うのは当然ですが、「入力中」状態が終わった後必ずDisableSecureEventInput()で状態解消すべきだと義務です。いくつかヘルパーアプリも、あるいはSecureEventInputを呼び起こしてからすぐ固まったアプリも、この状態になりやすいです。特に、他のアプリの画面へ切り替えたとしても、固まったアプリのSecureEventInput状態は自動的に解消できません。\n\n検出した該当プロセスは:";
"i18n:securityAgentHelper.warningMessage.title" = "SecureEventInput の不正利用が検出"; "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.importFromKimoTxt.finishedCount:%@" = "新しい記録は %@ つ読み込みました。";
"i18n:settings.shiftKeyASCIITogle.description" = "この機能の利用する NSEvent は、macOS 内蔵の入力アプリ共用モジュール「InputMethodKit」から提供した NSEvent のみであり、その NSEvent 文脈関係で「Shift キーは1回押したかどうか」と判断することはできる。この事実に疑いを持つ者は、本アプリのソースコードを審査するか、あるいは本アプリを逆向工程(分解工学, いわゆる「Reverse-Engineering」するがよい。なお、Shiftキーによるこの切り替えは、CapsLockがONの時には効かぬ。"; "i18n:settings.shiftKeyASCIITogle.description" = "この機能の利用する NSEvent は、macOS 内蔵の入力アプリ共用モジュール「InputMethodKit」から提供した NSEvent のみであり、その NSEvent 文脈関係で「Shift キーは1回押したかどうか」と判断することはできる。この事実に疑いを持つ者は、本アプリのソースコードを審査するか、あるいは本アプリを逆向工程(分解工学, いわゆる「Reverse-Engineering」するがよい。なお、Shiftキーによるこの切り替えは、CapsLockがONの時には効かぬ。";
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "macOS 10.14 からのシステム内蔵機能としての同じ機能に影響しません。"; "i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "macOS 10.14 からのシステム内蔵機能としての同じ機能に影響しません。";

View File

@ -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)." = "磁带模式类似于雅虎奇摩输入法的 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" = "磁带设定"; "Cassette" = "磁带设定";
"catAlphabets" = "字母"; "catAlphabets" = "字母";
"catBracketedASCII" = "括英"; "catBracketedASCII" = "括英";
@ -195,11 +195,14 @@
"i18n:aboutWindow.OK_BUTTON" = "确定"; "i18n:aboutWindow.OK_BUTTON" = "确定";
"i18n:aboutWindow.WEBSITE_BUTTON" = "网站"; "i18n:aboutWindow.WEBSITE_BUTTON" = "网站";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "无法将已挪作他用的按键设为选字键。"; "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: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.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.header" = "威注音有检测到下述后台进程有在滥用 SecureEventInput。这种滥用会导致系统内的所有第三方输入法全都无法正常使用在输入法选单内会变成灰色。\n\n针对需要填写敏感数据的场合使用 SecureEventInput 无可厚非。但是,用 EnableSecureEventInput() 开启该模式之后,就有义务在输入窗格失焦的那一刻呼叫 DisableSecureEventInput() 来结束这种状态。这种状态还常见于后台辅助 App 当中、或者某个 App 在叫出该模式之后失去响应这样的话哪怕被切换到后台SecureEventInput 也不会自动解除)。\n\n被侦测到的进程如下:";
"i18n:securityAgentHelper.warningMessage.title" = "检测到对 SecureEventInput 的滥用行为"; "i18n:securityAgentHelper.warningMessage.title" = "检测到对 SecureEventInput 的滥用行为";
"i18n:settings.importFromKimoTxt.buttonText" = "汇入奇摩输入法自订词资料库"; "i18n:settings.importFromKimoTxt.label" = "汇入奇摩输入法自订词资料库";
"i18n:settings.importFromKimoTxt.DirectlyImport" = "直接汇入";
"i18n:settings.importFromKimoTxt.finishedCount:%@" = "汇入了 %@ 笔新记录。"; "i18n:settings.importFromKimoTxt.finishedCount:%@" = "汇入了 %@ 笔新记录。";
"i18n:settings.shiftKeyASCIITogle.description" = "该功能只需要对借由 macOS 内建的输入法框架传来的 NSEvent 做上下文分析,自然没有「向使用者寻求系统全局键盘事件监听权限」之必要。您可自行审视敝输入法的原始程式码仓库、或对敝输入法逆向工程,以自行证实此处所言之真假。另注:这个 Shift 键切换开关在 CapsLock 灯亮时无效。"; "i18n:settings.shiftKeyASCIITogle.description" = "该功能只需要对借由 macOS 内建的输入法框架传来的 NSEvent 做上下文分析,自然没有「向使用者寻求系统全局键盘事件监听权限」之必要。您可自行审视敝输入法的原始程式码仓库、或对敝输入法逆向工程,以自行证实此处所言之真假。另注:这个 Shift 键切换开关在 CapsLock 灯亮时无效。";
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "这不会影响到自 macOS 10.14 开始的系统内建的同名功能。"; "i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "这不会影响到自 macOS 10.14 开始的系统内建的同名功能。";

View File

@ -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)." = "磁帶模式類似於雅虎奇摩輸入法的 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" = "磁帶設定"; "Cassette" = "磁帶設定";
"catAlphabets" = "字母"; "catAlphabets" = "字母";
"catBracketedASCII" = "括英"; "catBracketedASCII" = "括英";
@ -195,11 +195,14 @@
"i18n:aboutWindow.OK_BUTTON" = "確定"; "i18n:aboutWindow.OK_BUTTON" = "確定";
"i18n:aboutWindow.WEBSITE_BUTTON" = "網站"; "i18n:aboutWindow.WEBSITE_BUTTON" = "網站";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "無法將已挪作他用的按鍵設為選字鍵。"; "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: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.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.header" = "威注音有偵測到下述後檯執行緒有在濫用 SecureEventInput。這種濫用會導致系統內的所有第三方輸入法全都無法正常使用在輸入法選單內會變成灰色。\n\n針對需要填寫敏感資料的場合使用 SecureEventInput 無可厚非。但是,用 EnableSecureEventInput() 開啟該模式之後,就有義務在輸入窗格失焦的那一刻呼叫 DisableSecureEventInput() 來結束這種狀態。這種狀態還常見於後檯輔助 App 當中、或者某個 App 在叫出該模式之後失去回應這樣的話哪怕被切換到後檯SecureEventInput 也不會自動解除)。\n\n被偵測到的執行緒如下:";
"i18n:securityAgentHelper.warningMessage.title" = "偵測到對 SecureEventInput 的濫用行為"; "i18n:securityAgentHelper.warningMessage.title" = "偵測到對 SecureEventInput 的濫用行為";
"i18n:settings.importFromKimoTxt.buttonText" = "匯入奇摩輸入法自訂詞資料庫"; "i18n:settings.importFromKimoTxt.label" = "匯入奇摩輸入法自訂詞資料庫";
"i18n:settings.importFromKimoTxt.DirectlyImport" = "直接匯入";
"i18n:settings.importFromKimoTxt.finishedCount:%@" = "匯入了 %@ 筆新記錄。"; "i18n:settings.importFromKimoTxt.finishedCount:%@" = "匯入了 %@ 筆新記錄。";
"i18n:settings.shiftKeyASCIITogle.description" = "該功能只需要對藉由 macOS 內建的輸入法框架傳來的 NSEvent 做上下文分析,自然沒有「向使用者尋求系統全局鍵盤事件監聽權限」之必要。您可自行審視敝輸入法的原始程式碼倉庫、或對敝輸入法逆向工程,以自行證實此處所言之真假。另註:這個 Shift 鍵切換開關在 CapsLock 燈亮時無效。"; "i18n:settings.shiftKeyASCIITogle.description" = "該功能只需要對藉由 macOS 內建的輸入法框架傳來的 NSEvent 做上下文分析,自然沒有「向使用者尋求系統全局鍵盤事件監聽權限」之必要。您可自行審視敝輸入法的原始程式碼倉庫、或對敝輸入法逆向工程,以自行證實此處所言之真假。另註:這個 Shift 鍵切換開關在 CapsLock 燈亮時無效。";
"i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "這不會影響到自 macOS 10.14 開始的系統內建的同名功能。"; "i18n:UserDef.kBypassNonAppleCapsLockHandling.description" = "這不會影響到自 macOS 10.14 開始的系統內建的同名功能。";

View File

@ -16,6 +16,10 @@
</array> </array>
<key>com.apple.security.temporary-exception.mach-register.global-name</key> <key>com.apple.security.temporary-exception.mach-register.global-name</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)_Connection</string> <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> <key>com.apple.security.temporary-exception.shared-preference.read-only</key>
<string>org.atelierInmu.inputmethod.vChewing</string> <string>org.atelierInmu.inputmethod.vChewing</string>
</dict> </dict>

View File

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 54; objectVersion = 60;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -34,6 +34,7 @@
5BC5E01E28DDE4770094E427 /* NotifierUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E01D28DDE4770094E427 /* NotifierUI */; }; 5BC5E01E28DDE4770094E427 /* NotifierUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E01D28DDE4770094E427 /* NotifierUI */; };
5BC5E02128DDEFE00094E427 /* TooltipUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02028DDEFE00094E427 /* TooltipUI */; }; 5BC5E02128DDEFE00094E427 /* TooltipUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02028DDEFE00094E427 /* TooltipUI */; };
5BC5E02428DE07860094E427 /* PopupCompositionBuffer in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02328DE07860094E427 /* PopupCompositionBuffer */; }; 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 */; }; 5BDB7A3928D4824A001AC277 /* BookmarkManager in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3828D4824A001AC277 /* BookmarkManager */; };
5BDB7A3B28D4824A001AC277 /* FolderMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3A28D4824A001AC277 /* FolderMonitor */; }; 5BDB7A3B28D4824A001AC277 /* FolderMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3A28D4824A001AC277 /* FolderMonitor */; };
5BDB7A3D28D4824A001AC277 /* Hotenka in Frameworks */ = {isa = PBXBuildFile; productRef = 5BDB7A3C28D4824A001AC277 /* Hotenka */; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = "<group>"; };
5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = "<group>"; }; 5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = "<group>"; };
@ -193,6 +195,7 @@
files = ( files = (
5BC5E02428DE07860094E427 /* PopupCompositionBuffer in Frameworks */, 5BC5E02428DE07860094E427 /* PopupCompositionBuffer in Frameworks */,
5B65FB342A9518DA007EEFB0 /* MainAssembly in Frameworks */, 5B65FB342A9518DA007EEFB0 /* MainAssembly in Frameworks */,
5BC8EB7E2B7E1CC1004F5101 /* KimoDataReader in Frameworks */,
5BDB7A4528D4824A001AC277 /* ShiftKeyUpChecker in Frameworks */, 5BDB7A4528D4824A001AC277 /* ShiftKeyUpChecker in Frameworks */,
5BFC63CC28D49BBC004A77B7 /* UpdateSputnik in Frameworks */, 5BFC63CC28D49BBC004A77B7 /* UpdateSputnik in Frameworks */,
5BDB7A4128D4824A001AC277 /* Megrez in Frameworks */, 5BDB7A4128D4824A001AC277 /* Megrez in Frameworks */,
@ -341,6 +344,7 @@
5B963C9B28D5BE4100DCEE88 /* vChewing_CocoaExtension */, 5B963C9B28D5BE4100DCEE88 /* vChewing_CocoaExtension */,
5BDB7A3228D47587001AC277 /* vChewing_Hotenka */, 5BDB7A3228D47587001AC277 /* vChewing_Hotenka */,
5BFC63C728D49511004A77B7 /* vChewing_IMKUtils */, 5BFC63C728D49511004A77B7 /* vChewing_IMKUtils */,
5BAD29D12B7E1A1B0013D695 /* vChewing_KimoDataReader */,
5BFC63CD28D4AC98004A77B7 /* vChewing_LangModelAssembly */, 5BFC63CD28D4AC98004A77B7 /* vChewing_LangModelAssembly */,
5B65FB322A9518C9007EEFB0 /* vChewing_MainAssembly */, 5B65FB322A9518C9007EEFB0 /* vChewing_MainAssembly */,
5BDB7A3328D47587001AC277 /* vChewing_Megrez */, 5BDB7A3328D47587001AC277 /* vChewing_Megrez */,
@ -496,6 +500,7 @@
5BA8C30228DF0360004C5CC4 /* CandidateWindow */, 5BA8C30228DF0360004C5CC4 /* CandidateWindow */,
5B765F08293A253C00122315 /* PhraseEditorUI */, 5B765F08293A253C00122315 /* PhraseEditorUI */,
5B65FB332A9518DA007EEFB0 /* MainAssembly */, 5B65FB332A9518DA007EEFB0 /* MainAssembly */,
5BC8EB7D2B7E1CC1004F5101 /* KimoDataReader */,
); );
productName = vChewing; productName = vChewing;
productReference = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */; productReference = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */;
@ -556,6 +561,7 @@
); );
mainGroup = 6A0D4E9215FC0CFA00ABF4B3; mainGroup = 6A0D4E9215FC0CFA00ABF4B3;
packageReferences = ( packageReferences = (
5BC8EB7C2B7E1CC1004F5101 /* XCLocalSwiftPackageReference "Packages/vChewing_KimoDataReader" */,
); );
productRefGroup = 6A0D4EA315FC0D2D00ABF4B3 /* Products */; productRefGroup = 6A0D4EA315FC0D2D00ABF4B3 /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -1129,6 +1135,13 @@
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
5BC8EB7C2B7E1CC1004F5101 /* XCLocalSwiftPackageReference "Packages/vChewing_KimoDataReader" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Packages/vChewing_KimoDataReader;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
5B40113828D7050D00A9D4CB /* Shared */ = { 5B40113828D7050D00A9D4CB /* Shared */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
@ -1174,6 +1187,10 @@
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = PopupCompositionBuffer; productName = PopupCompositionBuffer;
}; };
5BC8EB7D2B7E1CC1004F5101 /* KimoDataReader */ = {
isa = XCSwiftPackageProductDependency;
productName = KimoDataReader;
};
5BDB7A3828D4824A001AC277 /* BookmarkManager */ = { 5BDB7A3828D4824A001AC277 /* BookmarkManager */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = BookmarkManager; productName = BookmarkManager;