1.8.4 // Numeric pad, etc. Merge Gitee PR!67 from upd/1.8.4

This commit is contained in:
ShikiSuen 2022-07-25 11:28:46 +00:00 committed by Gitee
commit 1962455ed2
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
45 changed files with 1400 additions and 1208 deletions

@ -1 +1 @@
Subproject commit 91a12bb5a355b56456beceec42cb001dea036b2b
Subproject commit 94b215d444e1c43e81ad173e9c28e6769f74c330

View File

@ -34,7 +34,7 @@ enum KeyCode: UInt16 {
case kCarriageReturn = 36 // Renamed from "kReturn" to avoid nomenclatural confusions.
case kTab = 48
case kSpace = 49
case kSymbolMenuPhysicalKey = 50 // vChewing Specific
case kSymbolMenuPhysicalKeyIntl = 50 // vChewing Specific (Non-JIS)
case kBackSpace = 51 // Renamed from "kDelete" to avoid nomenclatural confusions.
case kEscape = 53
case kCommand = 55
@ -54,6 +54,7 @@ enum KeyCode: UInt16 {
case kF18 = 79
case kF19 = 80
case kF20 = 90
case kSymbolMenuPhysicalKeyJIS = 94 // vChewing Specific (JIS)
case kF5 = 96
case kF6 = 97
case kF7 = 98
@ -109,6 +110,11 @@ enum KeyCodeBlackListed: UInt16 {
case kF1 = 122
}
/// KeyCode
///
/// 95 Key Code JIS
let arrNumpadKeyCodes: [UInt16] = [65, 67, 69, 71, 75, 78, 81, 82, 83, 84, 85, 86, 87, 88, 89, 91, 92, 95]
// CharCodes: https://theasciicode.com.ar/ascii-control-characters/horizontal-tab-ascii-code-9.html
enum CharCode: UInt16 {
case yajuusenpaiA = 114
@ -255,6 +261,11 @@ struct InputSignal: CustomStringConvertible {
return code.rawValue != KeyCode.kNone.rawValue
}
/// flags KeyCode
var isNumericPadAreaKey: Bool {
arrNumpadKeyCodes.contains(keyCode)
}
var isTab: Bool {
KeyCode(rawValue: keyCode) == KeyCode.kTab
}
@ -338,13 +349,13 @@ struct InputSignal: CustomStringConvertible {
var isUpperCaseASCIILetterKey: Bool {
// flags == .shift Shift
charCode >= 65 && charCode <= 90 && flags == .shift
(65...90).contains(charCode) && flags == .shift
}
var isSymbolMenuPhysicalKey: Bool {
// KeyCode macOS Apple
// ![input isShift] 使 Shift
KeyCode(rawValue: keyCode) == KeyCode.kSymbolMenuPhysicalKey
[KeyCode.kSymbolMenuPhysicalKeyIntl, KeyCode.kSymbolMenuPhysicalKeyJIS].contains(KeyCode(rawValue: keyCode))
}
}

View File

@ -188,7 +188,7 @@ class KeyHandler {
//
currentUOM.observe(
walkedAnchors: walkedAnchors, cursorIndex: adjustedCursor, candidate: theCandidate.value,
timestamp: NSDate().timeIntervalSince1970
timestamp: NSDate().timeIntervalSince1970, saveCallback: { mgrLangModel.saveUserOverrideModelData() }
)
}
}
@ -236,7 +236,7 @@ class KeyHandler {
// / JIS
//
//
arrCandidates.append(.init(key: currentCandidate.key, value: currentCandidate.value))
arrCandidates.append(currentCandidate)
}
// 調
if !mgrPrefs.fetchSuggestionsFromUserOverrideModel || mgrPrefs.useSCPCTypingMode || fixOrder {

View File

@ -78,7 +78,12 @@ extension KeyHandler {
// MARK: Enter
if input.isEnter {
delegate!.keyHandler(
if state is InputState.AssociatedPhrases, !mgrPrefs.alsoConfirmAssociatedCandidatesByEnter {
clear()
stateCallback(InputState.EmptyIgnoringPreviousState())
return true
}
delegate?.keyHandler(
self,
didSelectCandidateAt: ctlCandidateCurrent.selectedCandidateIndex,
ctlCandidate: ctlCandidateCurrent
@ -271,6 +276,7 @@ extension KeyHandler {
} else {
ctlCandidateCurrent.selectedCandidateIndex = candidates.count - 1
}
return true
}
}
@ -297,7 +303,7 @@ extension KeyHandler {
if index != NSNotFound {
let candidateIndex = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(index)
if candidateIndex != Int.max {
delegate!.keyHandler(
delegate?.keyHandler(
self, didSelectCandidateAt: candidateIndex, ctlCandidate: ctlCandidateCurrent
)
return true
@ -337,7 +343,7 @@ extension KeyHandler {
if shouldAutoSelectCandidate {
let candidateIndex = ctlCandidateCurrent.candidateIndexAtKeyLabelIndex(0)
if candidateIndex != Int.max {
delegate!.keyHandler(
delegate?.keyHandler(
self,
didSelectCandidateAt: candidateIndex,
ctlCandidate: ctlCandidateCurrent

View File

@ -108,9 +108,12 @@ extension KeyHandler {
// MARK: (Numeric Pad Processing)
if input.isNumericPad {
if !input.isLeft, !input.isRight, !input.isDown,
!input.isUp, !input.isSpace, charCode.isPrintableASCII
// isNumericPadAreaKey KeyCode
//
//
if input.isNumericPadAreaKey {
if !(state is InputState.ChoosingCandidate || state is InputState.AssociatedPhrases
|| state is InputState.SymbolTable)
{
clear()
stateCallback(InputState.Empty())
@ -184,12 +187,12 @@ extension KeyHandler {
// 使 OVMandarin調
composer.receiveKey(fromString: " ")
}
let reading = composer.getComposition() //
let readingKey = composer.getComposition() //
//
//
if !currentLM.hasUnigramsFor(key: reading) {
IME.prtDebugIntel("B49C0979語彙庫內無「\(reading)」的匹配記錄。")
if !currentLM.hasUnigramsFor(key: readingKey) {
IME.prtDebugIntel("B49C0979語彙庫內無「\(readingKey)」的匹配記錄。")
errorCallback()
composer.clear()
//
@ -198,7 +201,7 @@ extension KeyHandler {
}
//
compositor.insertReading(reading)
compositor.insertReading(readingKey)
//
let textToCommit = commitOverflownCompositionAndWalk
@ -359,7 +362,8 @@ extension KeyHandler {
return handleInlineCandidateRotation(
state: state, reverseModifier: false, stateCallback: stateCallback, errorCallback: errorCallback
)
} else if input.isExtraChooseCandidateKeyReverse {
}
if input.isExtraChooseCandidateKeyReverse {
return handleInlineCandidateRotation(
state: state, reverseModifier: true, stateCallback: stateCallback, errorCallback: errorCallback
)
@ -471,6 +475,17 @@ extension KeyHandler {
}
}
// MARK: / (Full-Width / Half-Width Space)
/// 使
if state is InputState.Empty {
if input.isSpace, !input.isOptionHold, !input.isFunctionKeyHold, !input.isControlHold, !input.isCommandHold {
stateCallback(InputState.Committing(textToCommit: input.isShiftHold ? " " : " "))
}
stateCallback(InputState.Empty())
return true
}
// MARK: - (Still Nothing)
/// ctlInputMethod

View File

@ -77,6 +77,7 @@ extension KeyHandler {
///
switch compositor.cursor {
case compositor.readings.count...:
// compositor.cursor readings.count Megrez
tooltipParameterRef[0] = compositor.readings[compositor.cursor - 1]
case 0:
tooltipParameterRef[1] = compositor.readings[compositor.cursor]
@ -328,7 +329,7 @@ extension KeyHandler {
)
if candidateState.candidates.count == 1 {
clear()
if let candidateToCommit: (String, String) = candidateState.candidates.first {
if let candidateToCommit: (String, String) = candidateState.candidates.first, !candidateToCommit.1.isEmpty {
stateCallback(InputState.Committing(textToCommit: candidateToCommit.1))
stateCallback(InputState.Empty())
} else {

View File

@ -151,6 +151,9 @@ extension ctlInputMethod {
{
commit(text: previous.composingBuffer)
}
//
ctlInputMethod.ctlCandidateCurrent.visible = false
ctlInputMethod.tooltipController.hide()
clearInlineDisplay()
}

View File

@ -59,6 +59,7 @@ struct UserDef {
static let kFetchSuggestionsFromUserOverrideModel = "FetchSuggestionsFromUserOverrideModel"
static let kUseFixecCandidateOrderOnSelection = "UseFixecCandidateOrderOnSelection"
static let kAutoCorrectReadingCombination = "AutoCorrectReadingCombination"
static let kAlsoConfirmAssociatedCandidatesByEnter = "AlsoConfirmAssociatedCandidatesByEnter"
static let kCandidateTextFontName = "CandidateTextFontName"
static let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
@ -282,6 +283,9 @@ public enum mgrPrefs {
UserDefaults.standard.setDefault(
mgrPrefs.autoCorrectReadingCombination, forKey: UserDef.kAutoCorrectReadingCombination
)
UserDefaults.standard.setDefault(
mgrPrefs.alsoConfirmAssociatedCandidatesByEnter, forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter
)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeySCPC, forKey: UserDef.kUsingHotKeySCPC)
UserDefaults.standard.setDefault(mgrPrefs.usingHotKeyAssociates, forKey: UserDef.kUsingHotKeyAssociates)
@ -367,6 +371,9 @@ public enum mgrPrefs {
@UserDefault(key: UserDef.kAutoCorrectReadingCombination, defaultValue: true)
static var autoCorrectReadingCombination: Bool
@UserDefault(key: UserDef.kAlsoConfirmAssociatedCandidatesByEnter, defaultValue: true)
static var alsoConfirmAssociatedCandidatesByEnter: Bool
static var minCandidateLength: Int {
mgrPrefs.allowBoostingSingleKanjiAsUserPhrase ? 1 : 2
}
@ -601,6 +608,7 @@ extension mgrPrefs {
UserDef.kAssociatedPhrasesEnabled, UserDef.kPhraseReplacementEnabled, UserDef.kUsingHotKeySCPC,
UserDef.kUsingHotKeyAssociates, UserDef.kUsingHotKeyCNS, UserDef.kUsingHotKeyKangXi, UserDef.kUsingHotKeyJIS,
UserDef.kUsingHotKeyHalfWidthASCII, UserDef.kUseFixecCandidateOrderOnSelection,
UserDef.kAutoCorrectReadingCombination, UserDef.kAlsoConfirmAssociatedCandidatesByEnter,
]
}

View File

@ -248,14 +248,6 @@ extension vChewing {
return !unigramsFor(key: key).isEmpty
}
public func associatedPhrasesFor(key: String) -> [String] {
lmAssociates.valuesFor(key: key)
}
public func hasAssociatedPhrasesFor(key: String) -> Bool {
lmAssociates.hasValuesFor(key: key)
}
public func associatedPhrasesFor(pair: Megrez.KeyValuePaired) -> [String] {
lmAssociates.valuesFor(pair: pair)
}

View File

@ -100,6 +100,7 @@ class SymbolNode {
private static let defaultSymbolRoot: SymbolNode = .init(
"/",
[
SymbolNode(" "),
SymbolNode(""),
SymbolNode(catCommonSymbols, symbols: ",、。.?!;:‧‥﹐﹒˙·‘’“”〝〞‵′〃~$%@&#*"),
SymbolNode(catHoriBrackets, symbols: "()「」〔〕{}〈〉『』《》【】﹙﹚﹝﹞﹛﹜"),

View File

@ -42,7 +42,7 @@ extension vChewing {
!rangeMap.isEmpty
}
internal func cnvNgramKeyFromPinyinToPhona(target: String) -> String {
internal func cnvNGramKeyFromPinyinToPhona(target: String) -> String {
guard target.contains("("), target.contains(","), target.contains(")") else {
return target
}
@ -69,7 +69,7 @@ extension vChewing {
if !theKey.isEmpty, theKey.first != "#" {
for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() {
if i == 0 { continue }
rangeMap[cnvNgramKeyFromPinyinToPhona(target: theKey), default: []].append(($0, i))
rangeMap[cnvNGramKeyFromPinyinToPhona(target: theKey), default: []].append(($0, i))
}
}
}
@ -94,22 +94,6 @@ extension vChewing {
// This function will be implemented only if further hard-necessity comes.
}
public func valuesFor(key: String) -> [String] {
var pairs: [String] = []
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[key] {
for (netaRange, index) in arrRangeRecords {
let neta = strData[netaRange].split(separator: " ")
let theValue: String = .init(neta[index])
pairs.append(theValue)
}
}
return pairs
}
public func hasValuesFor(key: String) -> Bool {
rangeMap[key] != nil
}
public func valuesFor(pair: Megrez.KeyValuePaired) -> [String] {
var pairs: [String] = []
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pair.toNGramKey] {

View File

@ -51,10 +51,10 @@ extension vChewing {
///
///
/// - parameters:
/// - reverse:
/// - consolidate: 使
/// - defaultScore:
/// - forceDefaultScore:
/// - reverse:
/// - consolidate: 使
/// - defaultScore:
/// - forceDefaultScore:
public init(
reverse: Bool = false, consolidate: Bool = false, defaultScore scoreDefault: Double = 0,
forceDefaultScore: Bool = false
@ -73,7 +73,7 @@ extension vChewing {
///
/// - parameters:
/// - path:
/// - path:
@discardableResult public mutating func open(_ path: String) -> Bool {
if isLoaded() {
return false
@ -135,8 +135,8 @@ extension vChewing {
///
///
/// - parameters:
/// - precedingKey:
/// - key:
/// - precedingKey:
/// - key:
public func bigramsFor(precedingKey: String, key: String) -> [Megrez.Bigram] {
// Swift
// [Megrez.Bigram]()
@ -145,7 +145,7 @@ extension vChewing {
/// strData
/// - parameters:
/// - key:
/// - key:
public func unigramsFor(key: String) -> [Megrez.Unigram] {
var grams: [Megrez.Unigram] = []
if let arrRangeRecords: [Range<String.Index>] = rangeMap[key] {
@ -168,7 +168,7 @@ extension vChewing {
///
/// - parameters:
/// - key:
/// - key:
public func hasUnigramsFor(key: String) -> Bool {
rangeMap[key] != nil
}

View File

@ -52,10 +52,10 @@ extension vChewing {
/// LMCoreNS 便
///
/// - parameters:
/// - reverse:
/// - consolidate: 使
/// - defaultScore:
/// - forceDefaultScore:
/// - reverse:
/// - consolidate: 使
/// - defaultScore:
/// - forceDefaultScore:
public init(
reverse: Bool = false, consolidate: Bool = false, defaultScore scoreDefault: Double = 0,
forceDefaultScore: Bool = false
@ -74,7 +74,7 @@ extension vChewing {
///
/// - parameters:
/// - path:
/// - path:
@discardableResult public mutating func open(_ path: String) -> Bool {
if isLoaded() {
return false
@ -128,8 +128,8 @@ extension vChewing {
///
///
/// - parameters:
/// - precedingKey:
/// - key:
/// - precedingKey:
/// - key:
public func bigramsFor(precedingKey: String, key: String) -> [Megrez.Bigram] {
// Swift
// [Megrez.Bigram]()
@ -138,7 +138,7 @@ extension vChewing {
/// UTF8
/// - parameters:
/// - key:
/// - key:
public func unigramsFor(key: String) -> [Megrez.Unigram] {
var grams: [Megrez.Unigram] = []
if let arrRangeRecords: [Data] = rangeMap[cnvPhonabetToASCII(key)] {
@ -162,7 +162,7 @@ extension vChewing {
///
/// - parameters:
/// - key:
/// - key:
public func hasUnigramsFor(key: String) -> Bool {
rangeMap[cnvPhonabetToASCII(key)] != nil
}
@ -173,7 +173,7 @@ extension vChewing {
///
/// ASCII
/// - parameters:
/// - incoming:
/// - incoming:
func cnvPhonabetToASCII(_ incoming: String) -> String {
let dicPhonabet2ASCII = [
"": "b", "": "p", "": "m", "": "f", "": "d", "": "t", "": "n", "": "l", "": "g", "": "k", "": "h",
@ -194,7 +194,7 @@ extension vChewing {
///
/// ASCII
/// - parameters:
/// - incoming:
/// - incoming:
func restorePhonabetFromASCII(_ incoming: String) -> String {
let dicPhonabet4ASCII = [
"b": "", "p": "", "m": "", "f": "", "d": "", "t": "", "n": "", "l": "", "g": "", "k": "", "h": "",

View File

@ -33,9 +33,11 @@ extension vChewing {
var mutDecayExponent: Double
var mutLRUList: [KeyObservationPair] = []
var mutLRUMap: [String: KeyObservationPair] = [:]
let kDecayThreshold: Double = 1.0 / 1_048_576.0
let kDecayThreshold: Double = 1.0 / 1_048_576.0 //
public init(capacity: Int = 500, decayConstant: Double = 5400.0) {
public static let kObservedOverrideHalfLife: Double = 3600.0 * 6 // 6
public init(capacity: Int = 500, decayConstant: Double = LMUserOverride.kObservedOverrideHalfLife) {
mutCapacity = max(capacity, 1) // Ensures that this integer value is always > 0.
mutDecayExponent = log(0.5) / decayConstant
}
@ -44,7 +46,8 @@ extension vChewing {
walkedAnchors: [Megrez.NodeAnchor],
cursorIndex: Int,
candidate: String,
timestamp: Double
timestamp: Double,
saveCallback: @escaping () -> Void
) {
let key = convertKeyFrom(walkedAnchors: walkedAnchors, cursorIndex: cursorIndex)
guard !key.isEmpty else { return }
@ -64,24 +67,35 @@ extension vChewing {
mutLRUList.removeLast()
}
IME.prtDebugIntel("UOM: Observation finished with new observation: \(key)")
mgrLangModel.saveUserOverrideModelData()
saveCallback()
return
}
//
if var theNeta = mutLRUMap[key] {
theNeta.observation.update(candidate: candidate, timestamp: timestamp)
mutLRUList.insert(theNeta, at: 0)
mutLRUMap[key] = theNeta
IME.prtDebugIntel("UOM: Observation finished with existing observation: \(key)")
mgrLangModel.saveUserOverrideModelData()
_ = suggest(
walkedAnchors: walkedAnchors, cursorIndex: cursorIndex, timestamp: timestamp,
decayCallback: {
theNeta.observation.update(candidate: candidate, timestamp: timestamp)
self.mutLRUList.insert(theNeta, at: 0)
self.mutLRUMap[key] = theNeta
IME.prtDebugIntel("UOM: Observation finished with existing observation: \(key)")
saveCallback()
}
)
}
}
public func suggest(
walkedAnchors: [Megrez.NodeAnchor],
cursorIndex: Int,
timestamp: Double
timestamp: Double,
decayCallback: @escaping () -> Void = {}
) -> [Megrez.Unigram] {
let key = convertKeyFrom(walkedAnchors: walkedAnchors, cursorIndex: cursorIndex)
guard !key.isEmpty else {
IME.prtDebugIntel("UOM: Blank key generated on suggestion, aborting suggestion.")
return .init()
}
let currentReadingKey = convertKeyFrom(walkedAnchors: walkedAnchors, cursorIndex: cursorIndex, readingOnly: true)
guard let koPair = mutLRUMap[key] else {
IME.prtDebugIntel("UOM: mutLRUMap[key] is nil, throwing blank suggestion for key: \(key).")
@ -94,6 +108,7 @@ extension vChewing {
var currentHighScore = 0.0
for overrideNeta in Array(observation.overrides) {
let override: Override = overrideNeta.value
let overrideScore: Double = getScore(
eventCount: override.count,
totalCount: observation.count,
@ -102,6 +117,16 @@ extension vChewing {
lambda: mutDecayExponent
)
if (0...currentHighScore).contains(overrideScore) { continue }
let overrideDetectionScore: Double = getScore(
eventCount: override.count,
totalCount: observation.count,
eventTimestamp: override.timestamp,
timestamp: timestamp,
lambda: mutDecayExponent * 2
)
if (0...currentHighScore).contains(overrideDetectionScore) { decayCallback() }
let newUnigram = Megrez.Unigram(
keyValue: .init(key: currentReadingKey, value: overrideNeta.key), score: overrideScore
)
@ -270,13 +295,13 @@ extension vChewing.LMUserOverride {
extension vChewing.LMUserOverride {
/// LRU
public func bleachUnigrams() {
public func bleachUnigrams(saveCallback: @escaping () -> Void) {
for key in mutLRUMap.keys {
if !key.contains("(),()") { continue }
mutLRUMap.removeValue(forKey: key)
}
resetMRUList()
mgrLangModel.saveUserOverrideModelData()
saveCallback()
}
internal func resetMRUList() {

View File

@ -325,7 +325,8 @@ enum mgrLangModel {
if !ensureFileExists(userPhrasesDataURL(mode), populateWithTemplate: kTemplateNameUserPhrases)
|| !ensureFileExists(
userAssociatesDataURL(mode),
populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT)
populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT
)
|| !ensureFileExists(userFilteredDataURL(mode), populateWithTemplate: kTemplateNameUserExclusions)
|| !ensureFileExists(userReplacementsDataURL(mode), populateWithTemplate: kTemplateNameUserReplacements)
|| !ensureFileExists(userSymbolDataURL(mode), populateWithTemplate: kTemplateNameUserSymbolPhrases)
@ -480,16 +481,20 @@ enum mgrLangModel {
}
static func saveUserOverrideModelData() {
gUserOverrideModelCHT.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHT))
gUserOverrideModelCHS.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHS))
DispatchQueue.main.async {
gUserOverrideModelCHT.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHT))
}
DispatchQueue.main.async {
gUserOverrideModelCHS.saveData(toURL: userOverrideModelDataURL(InputMode.imeModeCHS))
}
}
static func removeUnigramsFromUserOverrideModel(_ mode: InputMode) {
switch mode {
case .imeModeCHS:
gUserOverrideModelCHT.bleachUnigrams()
gUserOverrideModelCHT.bleachUnigrams(saveCallback: { mgrLangModel.saveUserOverrideModelData() })
case .imeModeCHT:
gUserOverrideModelCHS.bleachUnigrams()
gUserOverrideModelCHS.bleachUnigrams(saveCallback: { mgrLangModel.saveUserOverrideModelData() })
case .imeModeNULL:
break
}

View File

@ -85,6 +85,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)Space:";
"Allow boosting / excluding a candidate of single kanji" = "Allow boosting / excluding a candidate of single kanji";
"Allow using Enter key to confirm associated candidate selection" = "Allow using Enter key to confirm associated candidate selection";
"Always use fixed listing order in candidate window" = "Always use fixed listing order in candidate window";
"An accomodation for elder computer users." = "An accomodation for elder computer users.";
"Apple ABC (equivalent to English US)" = "Apple ABC (equivalent to English US)";
@ -118,7 +119,7 @@
"Debug Mode" = "Debug Mode";
"Dictionary" = "Dictionary";
"Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode";
"Enable CNS11643 Support (2022-06-15)" = "Enable CNS11643 Support (2022-06-15)";
"Enable CNS11643 Support (2022-07-20)" = "Enable CNS11643 Support (2022-07-20)";
"Enable Space key for calling candidate window" = "Enable Space key for calling candidate window";
"Enable symbol input support (incl. certain emoji symbols)" = "Enable symbol input support (incl. certain emoji symbols)";
"English" = "English";

View File

@ -85,6 +85,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)Space:";
"Allow boosting / excluding a candidate of single kanji" = "Allow boosting / excluding a candidate of single kanji";
"Allow using Enter key to confirm associated candidate selection" = "Allow using Enter key to confirm associated candidate selection";
"Always use fixed listing order in candidate window" = "Always use fixed listing order in candidate window";
"An accomodation for elder computer users." = "An accomodation for elder computer users.";
"Apple ABC (equivalent to English US)" = "Apple ABC (equivalent to English US)";
@ -118,7 +119,7 @@
"Debug Mode" = "Debug Mode";
"Dictionary" = "Dictionary";
"Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode";
"Enable CNS11643 Support (2022-06-15)" = "Enable CNS11643 Support (2022-06-15)";
"Enable CNS11643 Support (2022-07-20)" = "Enable CNS11643 Support (2022-07-20)";
"Enable Space key for calling candidate window" = "Enable Space key for calling candidate window";
"Enable symbol input support (incl. certain emoji symbols)" = "Enable symbol input support (incl. certain emoji symbols)";
"English" = "English";

View File

@ -85,6 +85,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)Space:";
"Allow boosting / excluding a candidate of single kanji" = "即排除/即最優先にできる候補の文字数の最低限は1字とする";
"Allow using Enter key to confirm associated candidate selection" = "Enter キーを連想語彙候補の確認のために使う";
"Always use fixed listing order in candidate window" = "候補文字を固定順番で陳列する";
"An accomodation for elder computer users." = "年配なるユーザーのために提供した機能である。";
"Apple ABC (equivalent to English US)" = "Apple ABC (Apple U.S. キーボードと同じ)";
@ -118,7 +119,7 @@
"Debug Mode" = "欠陥辿着モード";
"Dictionary" = "辞書設定";
"Emulating select-candidate-per-character mode" = "漢字1つづつ全候補選択入力モード";
"Enable CNS11643 Support (2022-06-15)" = "全字庫モード // 入力可能な漢字数を倍増す (2022-06-15)";
"Enable CNS11643 Support (2022-07-20)" = "全字庫モード // 入力可能な漢字数を倍増す (2022-07-20)";
"Enable Space key for calling candidate window" = "Space キーで入力候補を呼び出す";
"Enable symbol input support (incl. certain emoji symbols)" = "僅かなる絵文字も含む符号入力サポートを起用";
"English" = "英語";

View File

@ -85,6 +85,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)空格键:";
"Allow boosting / excluding a candidate of single kanji" = "将可以就地升权/排除的候选字词的最短词长设为单个汉字";
"Allow using Enter key to confirm associated candidate selection" = "允许使用 Enter 确认当前选中的联想词";
"Always use fixed listing order in candidate window" = "以固定顺序来陈列选字窗内的候选字";
"An accomodation for elder computer users." = "针对年长使用者的习惯而提供。";
"Apple ABC (equivalent to English US)" = "Apple ABC (与 Apple 美规键盘等价)";
@ -118,7 +119,7 @@
"Debug Mode" = "侦错模式";
"Dictionary" = "辞典";
"Emulating select-candidate-per-character mode" = "模拟 90 年代前期注音逐字选字输入风格";
"Enable CNS11643 Support (2022-06-15)" = "启用 CNS11643 全字库支援 (2022-06-15)";
"Enable CNS11643 Support (2022-07-20)" = "启用 CNS11643 全字库支援 (2022-07-20)";
"Enable Space key for calling candidate window" = "敲空格键以呼出候选字窗";
"Enable symbol input support (incl. certain emoji symbols)" = "启用包括少许绘文字在内的符号输入支援";
"English" = "英语";

View File

@ -85,6 +85,7 @@
// SwiftUI Preferences
"(Shift+)Space:" = "(Shift+)空格鍵:";
"Allow boosting / excluding a candidate of single kanji" = "將可以就地升權/排除的候選字詞的最短詞長設為單個漢字";
"Allow using Enter key to confirm associated candidate selection" = "允許使用 Enter 確認當前選中的聯想詞";
"Always use fixed listing order in candidate window" = "以固定順序來陳列選字窗內的候選字";
"An accomodation for elder computer users." = "針對年長使用者的習慣而提供。";
"Apple ABC (equivalent to English US)" = "Apple ABC (與 Apple 美規鍵盤等價)";
@ -118,7 +119,7 @@
"Debug Mode" = "偵錯模式";
"Dictionary" = "辭典";
"Emulating select-candidate-per-character mode" = "模擬 90 年代前期注音逐字選字輸入風格";
"Enable CNS11643 Support (2022-06-15)" = "啟用 CNS11643 全字庫支援 (2022-06-15)";
"Enable CNS11643 Support (2022-07-20)" = "啟用 CNS11643 全字庫支援 (2022-07-20)";
"Enable Space key for calling candidate window" = "敲空格鍵以呼出候選字窗";
"Enable symbol input support (incl. certain emoji symbols)" = "啟用包括少許繪文字在內的符號輸入支援";
"English" = "英語";

View File

@ -101,7 +101,7 @@ struct suiPrefPaneDictionary: View {
return
}
}
} // End If self.window != nil
}
} label: {
Text("...")
}
@ -120,7 +120,7 @@ struct suiPrefPaneDictionary: View {
}
Divider()
Toggle(
LocalizedStringKey("Enable CNS11643 Support (2022-06-15)"),
LocalizedStringKey("Enable CNS11643 Support (2022-07-20)"),
isOn: $selEnableCNS11643
)
.onChange(of: selEnableCNS11643) { value in

View File

@ -48,6 +48,8 @@ struct suiPrefPaneExperience: View {
@State private var selComposingBufferSize = UserDefaults.standard.integer(forKey: UserDef.kComposingBufferSize)
@State private var selAutoCorrectReadingCombination = UserDefaults.standard.bool(
forKey: UserDef.kAutoCorrectReadingCombination)
@State private var selAlsoConfirmAssociatedCandidatesByEnter = UserDefaults.standard.bool(
forKey: UserDef.kAlsoConfirmAssociatedCandidatesByEnter)
private let contentWidth: Double = {
switch mgrPrefs.appleLanguages[0] {
case "ja":
@ -180,6 +182,12 @@ struct suiPrefPaneExperience: View {
}
Text(LocalizedStringKey("An accomodation for elder computer users."))
.preferenceDescription()
Toggle(
LocalizedStringKey("Allow using Enter key to confirm associated candidate selection"),
isOn: $selAlsoConfirmAssociatedCandidatesByEnter
).onChange(of: selAlsoConfirmAssociatedCandidatesByEnter) { value in
mgrPrefs.alsoConfirmAssociatedCandidatesByEnter = value
}
}
}
}

View File

@ -57,8 +57,14 @@ class ctlAboutWindow: NSWindowController {
)
}
@IBAction func btnWiki(_: NSButton) {
if let url = URL(string: "https://gitee.com/vchewing/vChewing-macOS/wikis") {
@IBAction func btnBugReport(_ sender: NSButton) {
if let url = URL(string: "https://vchewing.github.io/BUGREPORT.html") {
NSWorkspace.shared.open(url)
}
}
@IBAction func btnWebsite(_ sender: NSButton) {
if let url = URL(string: "https://vchewing.github.io/") {
NSWorkspace.shared.open(url)
}
}

View File

@ -27,9 +27,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import Carbon
import Cocoa
private let kWindowTitleHeight: CGFloat = 78
extension NSToolbarItem.Identifier {
fileprivate static let ofGeneral = NSToolbarItem.Identifier(rawValue: "tabGeneral")
fileprivate static let ofExperience = NSToolbarItem.Identifier(rawValue: "tabExperience")
fileprivate static let ofDictionary = NSToolbarItem.Identifier(rawValue: "tabDictionary")
fileprivate static let ofKeyboard = NSToolbarItem.Identifier(rawValue: "tabKeyboard")
}
// Please note that the class should be exposed using the same class name
// in Objective-C in order to let IMK to see the same class name as
// the "InputMethodServerPreferencesWindowControllerClass" in Info.plist.
@objc(ctlPrefWindow)
class ctlPrefWindow: NSWindowController {
@IBOutlet var fontSizePopUpButton: NSPopUpButton!
@IBOutlet var uiLanguageButton: NSPopUpButton!
@ -39,11 +49,34 @@ class ctlPrefWindow: NSWindowController {
@IBOutlet var chkTrad2JISShinjitai: NSButton!
@IBOutlet var lblCurrentlySpecifiedUserDataFolder: NSTextFieldCell!
@IBOutlet var vwrGeneral: NSView!
@IBOutlet var vwrExperience: NSView!
@IBOutlet var vwrDictionary: NSView!
@IBOutlet var vwrKeyboard: NSView!
var currentLanguageSelectItem: NSMenuItem?
override func windowDidLoad() {
super.windowDidLoad()
var preferencesTitleName = NSLocalizedString("vChewing Preferences…", comment: "")
preferencesTitleName.removeLast()
let toolbar = NSToolbar(identifier: "preference toolbar")
toolbar.allowsUserCustomization = false
toolbar.autosavesConfiguration = false
toolbar.sizeMode = .default
toolbar.delegate = self
toolbar.selectedItemIdentifier = .ofGeneral
toolbar.showsBaselineSeparator = true
window?.titlebarAppearsTransparent = false
if #available(macOS 11.0, *) {
window?.toolbarStyle = .preference
}
window?.toolbar = toolbar
window?.title = preferencesTitleName
use(view: vwrGeneral)
lblCurrentlySpecifiedUserDataFolder.placeholderString = mgrLangModel.dataFolderPath(
isDefaultFolder: true)
@ -254,6 +287,7 @@ class ctlPrefWindow: NSWindowController {
}
@IBAction func chooseUserDataFolderToSpecify(_: Any) {
guard let window = window else { return }
IME.dlgOpenPath.title = NSLocalizedString(
"Choose your desired user data folder.", comment: ""
)
@ -265,33 +299,136 @@ class ctlPrefWindow: NSWindowController {
let bolPreviousFolderValidity = mgrLangModel.checkIfSpecifiedUserDataFolderValid(
mgrPrefs.userDataFolderSpecified.expandingTildeInPath)
if window != nil {
IME.dlgOpenPath.beginSheetModal(for: window!) { result in
if result == NSApplication.ModalResponse.OK {
if IME.dlgOpenPath.url != nil {
// CommonDialog
//
var newPath = IME.dlgOpenPath.url!.path
newPath.ensureTrailingSlash()
if mgrLangModel.checkIfSpecifiedUserDataFolderValid(newPath) {
mgrPrefs.userDataFolderSpecified = newPath
IME.initLangModels(userOnly: true)
(NSApplication.shared.delegate as! AppDelegate).updateStreamHelperPath()
} else {
clsSFX.beep()
if !bolPreviousFolderValidity {
mgrPrefs.resetSpecifiedUserDataFolder()
}
return
IME.dlgOpenPath.beginSheetModal(for: window) { result in
if result == NSApplication.ModalResponse.OK {
if IME.dlgOpenPath.url != nil {
// CommonDialog
//
var newPath = IME.dlgOpenPath.url!.path
newPath.ensureTrailingSlash()
if mgrLangModel.checkIfSpecifiedUserDataFolderValid(newPath) {
mgrPrefs.userDataFolderSpecified = newPath
IME.initLangModels(userOnly: true)
(NSApplication.shared.delegate as! AppDelegate).updateStreamHelperPath()
} else {
clsSFX.beep()
if !bolPreviousFolderValidity {
mgrPrefs.resetSpecifiedUserDataFolder()
}
return
}
} else {
if !bolPreviousFolderValidity {
mgrPrefs.resetSpecifiedUserDataFolder()
}
return
}
} else {
if !bolPreviousFolderValidity {
mgrPrefs.resetSpecifiedUserDataFolder()
}
return
}
} // End If self.window != nil
}
} // End IBAction
}
extension ctlPrefWindow: NSToolbarDelegate {
func use(view: NSView) {
guard let window = window else {
return
}
window.contentView?.subviews.first?.removeFromSuperview()
let viewFrame = view.frame
var windowRect = window.frame
windowRect.size.height = kWindowTitleHeight + viewFrame.height
windowRect.size.width = viewFrame.width
windowRect.origin.y = window.frame.maxY - (viewFrame.height + kWindowTitleHeight)
window.setFrame(windowRect, display: true, animate: true)
window.contentView?.frame = view.bounds
window.contentView?.addSubview(view)
}
func toolbarDefaultItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] {
[.ofGeneral, .ofExperience, .ofDictionary, .ofKeyboard]
}
func toolbarAllowedItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] {
[.ofGeneral, .ofExperience, .ofDictionary, .ofKeyboard]
}
func toolbarSelectableItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] {
[.ofGeneral, .ofExperience, .ofDictionary, .ofKeyboard]
}
@objc func showGeneralView(_: Any?) {
use(view: vwrGeneral)
window?.toolbar?.selectedItemIdentifier = .ofGeneral
}
@objc func showExperienceView(_: Any?) {
use(view: vwrExperience)
window?.toolbar?.selectedItemIdentifier = .ofExperience
}
@objc func showDictionaryView(_: Any?) {
use(view: vwrDictionary)
window?.toolbar?.selectedItemIdentifier = .ofDictionary
}
@objc func showKeyboardView(_: Any?) {
use(view: vwrKeyboard)
window?.toolbar?.selectedItemIdentifier = .ofKeyboard
}
func toolbar(
_: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier,
willBeInsertedIntoToolbar _: Bool
) -> NSToolbarItem? {
let item = NSToolbarItem(itemIdentifier: itemIdentifier)
item.target = self
switch itemIdentifier {
case .ofGeneral:
let title = NSLocalizedString("General", comment: "")
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(
systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences")
} else {
item.image = NSImage(named: NSImage.homeTemplateName)
}
item.action = #selector(showGeneralView(_:))
case .ofExperience:
let title = NSLocalizedString("Experience", comment: "")
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(
systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences")
} else {
item.image = NSImage(named: NSImage.flowViewTemplateName)
}
item.action = #selector(showExperienceView(_:))
case .ofDictionary:
let title = NSLocalizedString("Dictionary", comment: "")
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(
systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences")
} else {
item.image = NSImage(named: NSImage.bookmarksTemplateName)
}
item.action = #selector(showDictionaryView(_:))
case .ofKeyboard:
let title = NSLocalizedString("Keyboard", comment: "")
item.label = title
if #available(macOS 11.0, *) {
item.image = NSImage(systemSymbolName: "keyboard.macwindow", accessibilityDescription: "Keyboard Preferences")
} else {
item.image = NSImage(named: NSImage.slideshowTemplateName)
}
item.action = #selector(showKeyboardView(_:))
default:
return nil
}
return item
}
}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="20037" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="20037"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@ -155,12 +155,22 @@ DQ
</scrollView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8WL-H4-o1O">
<rect key="frame" x="382" y="69" width="143" height="32"/>
<buttonCell key="cell" type="push" title="Wiki" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="xCD-lx-zY7">
<buttonCell key="cell" type="push" title="Website" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="xCD-lx-zY7">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btnWiki:" target="-2" id="ond-bM-3LE"/>
<action selector="btnWebsite:" target="-1" id="KjF-Ja-Vhz"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="OZj-DU-Oam">
<rect key="frame" x="382" y="42" width="143" height="32"/>
<buttonCell key="cell" type="push" title="Bug Report" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7SW-k9-sId">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btnBugReport:" target="-1" id="ub1-rB-AED"/>
</connections>
</button>
</subviews>
@ -174,6 +184,8 @@ DQ
<constraint firstItem="8M8-3C-BZO" firstAttribute="top" secondItem="8Ju-DR-2C8" secondAttribute="bottom" constant="8" symbolic="YES" id="82T-Pc-3db"/>
<constraint firstItem="2Gh-nq-Mng" firstAttribute="top" secondItem="bAv-ZO-Ihw" secondAttribute="bottom" constant="7" id="8EG-DW-AZM"/>
<constraint firstItem="Srh-ua-uQD" firstAttribute="top" secondItem="6Dx-DY-UG1" secondAttribute="bottom" constant="1" id="91b-Oo-tsv"/>
<constraint firstItem="OZj-DU-Oam" firstAttribute="top" secondItem="8WL-H4-o1O" secondAttribute="bottom" constant="7" id="AeY-Pq-7ZD"/>
<constraint firstItem="OZj-DU-Oam" firstAttribute="trailing" secondItem="8WL-H4-o1O" secondAttribute="trailing" id="BXO-np-u7F"/>
<constraint firstItem="d81-Fe-uNT" firstAttribute="top" secondItem="2Gh-nq-Mng" secondAttribute="bottom" constant="8" symbolic="YES" id="C6S-3S-QcT"/>
<constraint firstItem="2Gh-nq-Mng" firstAttribute="leading" secondItem="d81-Fe-uNT" secondAttribute="leading" id="CBk-Lx-b1d"/>
<constraint firstItem="bSu-np-tPT" firstAttribute="leading" secondItem="d81-Fe-uNT" secondAttribute="trailing" constant="18" id="E2b-7Z-Yjw"/>
@ -190,6 +202,7 @@ DQ
<constraint firstItem="8Ju-DR-2C8" firstAttribute="leading" secondItem="8M8-3C-BZO" secondAttribute="leading" id="UrF-M2-wpG"/>
<constraint firstItem="eYM-F7-drf" firstAttribute="top" secondItem="8M8-3C-BZO" secondAttribute="bottom" constant="8" symbolic="YES" id="WIZ-YQ-chM"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="2Gh-nq-Mng" secondAttribute="bottom" constant="134" id="WJK-gw-zR7"/>
<constraint firstItem="OZj-DU-Oam" firstAttribute="leading" secondItem="8WL-H4-o1O" secondAttribute="leading" id="Xhu-4a-33O"/>
<constraint firstItem="8WL-H4-o1O" firstAttribute="trailing" secondItem="bSu-np-tPT" secondAttribute="trailing" id="aEs-t7-H6v"/>
<constraint firstItem="9Pk-k3-0cO" firstAttribute="leading" secondItem="6Dx-DY-UG1" secondAttribute="trailing" constant="3" id="c3v-ZJ-usi"/>
<constraint firstItem="JkD-J1-Yeu" firstAttribute="top" secondItem="eYM-F7-drf" secondAttribute="bottom" constant="8" symbolic="YES" id="eqh-Gi-fS2"/>

File diff suppressed because it is too large Load Diff

View File

@ -25,3 +25,7 @@
/* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */
"lblCredits.title" = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen.";
"xCD-lx-zY7.title" = "Website";
"7SW-k9-sId.title" = "Bug Report";

View File

@ -20,7 +20,7 @@
"29.title" = "Candidate UI font size:";
"2iG-Ic-gbl.label" = "Dictionary";
"2pS-nv-te4.title" = "Choose which keys you prefer for selecting candidates.";
"2Y6-Am-WM1.title" = "General Settings";
"xibGeneralSettings.title" = "General Settings";
"5.title" = "OtherViews";
"6.title" = "Microsoft, Dachen, Wang, etc.";
"62u-jY-BRh.title" = "Stop farting (when typed phonetic combination is invalid, etc.)";
@ -41,6 +41,7 @@
"BSK-bH-Gct.title" = "Auto-convert traditional Chinese glyphs to KangXi characters";
"cf2-se-PDO.title" = "Dictionary and Language Models";
"chkAllowBoostingSingleKanjiAsUserPhrase.title" = "Allow boosting / excluding a candidate of single kanji";
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "Allow using Enter key to confirm associated candidate selection";
"chkAutoCorrectReadingCombination.title" = "Automatically correct reading combinations when typing";
"chkFetchSuggestionsFromUserOverrideModel.title" = "Applying typing suggestions from half-life user override model";
"chkUseFixecCandidateOrderOnSelection.title" = "Always use fixed listing order in candidate window";
@ -73,8 +74,8 @@
"sZx-18-8dO.title" = "Debug Mode";
"TXr-FF-ehw.title" = "Traditional Chinese";
"ueU-Rz-a1C.title" = "Choose the behavior of (Shift+)Tab key in the candidate window.";
"Uyz-xL-TVN.title" = "Output Settings";
"W24-T4-cg0.title" = "Enable CNS11643 Support (2022-06-15)";
"xibOutputSettings.title" = "Output Settings";
"W24-T4-cg0.title" = "Enable CNS11643 Support (2022-07-20)";
"wFR-zX-M8H.title" = "Show Hanyu-Pinyin in the inline composition buffer & tooltip";
"wN3-k3-b2a.title" = "Choose your desired user data folder path. Will be omitted if invalid.";
"wQ9-px-b07.title" = "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional.";

View File

@ -25,3 +25,7 @@
/* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */
"lblCredits.title" = "macOS 版威注音の開発Shiki Suen, Isaac Xen, Hiraku Wang, など。\n威注音語彙データの維持Shiki Suen。";
"xCD-lx-zY7.title" = "公式HP";
"7SW-k9-sId.title" = "支障を報告";

View File

@ -20,7 +20,7 @@
"29.title" = "候補文字の字号:";
"2iG-Ic-gbl.label" = "辞書";
"2pS-nv-te4.title" = "お好きなる言選り用キー陣列をお選びください。";
"2Y6-Am-WM1.title" = "全般設定";
"xibGeneralSettings.title" = "全般設定";
"5.title" = "OtherViews";
"6.title" = "大千配列Microsoft 標準・王安など)";
"62u-jY-BRh.title" = "マナーモード // 外すと入力間違の時に変な音が出る";
@ -41,6 +41,7 @@
"BSK-bH-Gct.title" = "入力した繁体字を康熙字体と自動変換";
"cf2-se-PDO.title" = "辞書と言語モデル";
"chkAllowBoostingSingleKanjiAsUserPhrase.title" = "即排除/即最優先にできる候補の文字数の最低限は1字とする";
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "Enter キーを連想語彙候補の確認のために使う";
"chkAutoCorrectReadingCombination.title" = "入力中で打ち間違った発音組み合わせを自動的に訂正する";
"chkFetchSuggestionsFromUserOverrideModel.title" = "入力中で臨時記憶モジュールからお薦めの候補を自動的に選ぶ";
"chkUseFixecCandidateOrderOnSelection.title" = "候補文字を固定順番で陳列する";
@ -73,8 +74,8 @@
"sZx-18-8dO.title" = "欠陥辿着モード";
"TXr-FF-ehw.title" = "繁体中国語";
"ueU-Rz-a1C.title" = "入力候補陳列での (Shift+)Tab キーの輪番切替対象をご指定ください。";
"Uyz-xL-TVN.title" = "出力設定";
"W24-T4-cg0.title" = "全字庫モード // 入力可能の漢字数倍増 (2022-06-15)";
"xibOutputSettings.title" = "出力設定";
"W24-T4-cg0.title" = "全字庫モード // 入力可能の漢字数倍増 (2022-07-20)";
"wFR-zX-M8H.title" = "弁音合併入力(入力緩衝列とヒントで音読みを漢語弁音に)";
"wN3-k3-b2a.title" = "欲しがるユーザー辞書保存先をご指定ください。無効の保存先設定は効かぬ。";
"wQ9-px-b07.title" = "Apple 動態注音キーボード (大千と倚天伝統) を使うには、共通語分析器の注音配列を大千と設定すべきである。";

View File

@ -25,3 +25,7 @@
/* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */
"lblCredits.title" = "威注音 macOS 程式研发Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护Shiki Suen。";
"xCD-lx-zY7.title" = "网站";
"7SW-k9-sId.title" = "故障提报";

View File

@ -20,7 +20,7 @@
"29.title" = "字型大小设定:";
"2iG-Ic-gbl.label" = "辞典";
"2pS-nv-te4.title" = "选择您所偏好的用来选字的按键组合。";
"2Y6-Am-WM1.title" = "一般设定";
"xibGeneralSettings.title" = "一般设定";
"5.title" = "OtherViews";
"6.title" = "微软/大千/王安/国乔/零壹/仲鼎";
"62u-jY-BRh.title" = "廉耻模式 // 取消勾选的话,敲错字时会有异音";
@ -35,12 +35,13 @@
"96.title" = "18";
"98.title" = "24";
"99.title" = "32";
"9DS-Rc-TXq.title" = "接口语言设定:";
"9DS-Rc-TXq.title" = "界面语言设定:";
"akC-2g-ybz.title" = "简体中文";
"ArK-Vk-OoT.title" = "仿真 90 年代前期注音逐字选字输入风格";
"BSK-bH-Gct.title" = "自动将繁体中文字转换为康熙正体字";
"cf2-se-PDO.title" = "辞典&語言模型";
"chkAllowBoostingSingleKanjiAsUserPhrase.title" = "将可以就地升权/排除的候选字词的最短词长设为单个汉字";
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "允许使用 Enter 确认当前选中的联想词";
"chkAutoCorrectReadingCombination.title" = "敲字时自动纠正读音组合";
"chkFetchSuggestionsFromUserOverrideModel.title" = "在敲字时自动套用来自半衰记忆模组的建议";
"chkUseFixecCandidateOrderOnSelection.title" = "以固定顺序来陈列选字窗内的候选字";
@ -73,8 +74,8 @@
"sZx-18-8dO.title" = "侦错模式";
"TXr-FF-ehw.title" = "繁体中文";
"ueU-Rz-a1C.title" = "指定 (Shift+)Tab 热键在选字窗内的轮替操作对象。";
"Uyz-xL-TVN.title" = "输出设定";
"W24-T4-cg0.title" = "启用 CNS11643 全字库支援 (2022-06-15)";
"xibOutputSettings.title" = "输出设定";
"W24-T4-cg0.title" = "启用 CNS11643 全字库支援 (2022-07-20)";
"wFR-zX-M8H.title" = "拼音并击(组字区与工具提示内显示汉语拼音)";
"wN3-k3-b2a.title" = "请在此指定您想指定的使用者语汇档案目录。无效值会被忽略。";
"wQ9-px-b07.title" = "Apple 动态注音键盘布局(大千与倚天)要求普通话/国音分析器的注音排列得配置为大千排列。";
@ -92,4 +93,4 @@
"XqL-rf-X6d.title" = "Space 换下一页Shift+Space 换选下一个候选字。";
"xrE-8T-WKO.label" = "进阶";
"Z9t-P0-BLF.title" = "自动检查软件更新";
"ZEv-Q2-mYL.title" = "变更使用者接口语言,会自动重新启动输入法。";
"ZEv-Q2-mYL.title" = "变更使用者界面语言,会自动重新启动输入法。";

View File

@ -25,3 +25,7 @@
/* Class = "NSTextFieldCell"; title = "vChewing macOS Development: Shiki Suen, Isaac Xen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */
"lblCredits.title" = "威注音 macOS 程式研发Shiki Suen, Isaac Xen, Hiraku Wang, 等。\n威注音词库维护Shiki Suen。";
"xCD-lx-zY7.title" = "網站";
"7SW-k9-sId.title" = "故障提報";

View File

@ -20,7 +20,7 @@
"29.title" = "字型大小設定:";
"2iG-Ic-gbl.label" = "辭典";
"2pS-nv-te4.title" = "選擇您所偏好的用來選字的按鍵組合。";
"2Y6-Am-WM1.title" = "一般設定";
"xibGeneralSettings.title" = "一般設定";
"5.title" = "OtherViews";
"6.title" = "微軟/大千/王安/國喬/零壹/仲鼎";
"62u-jY-BRh.title" = "廉恥模式 // 取消勾選的話,敲錯字時會有異音";
@ -41,6 +41,7 @@
"BSK-bH-Gct.title" = "自動將繁體中文字轉換為康熙正體字";
"cf2-se-PDO.title" = "辭典&語言模型";
"chkAllowBoostingSingleKanjiAsUserPhrase.title" = "將可以就地升權/排除的候選字詞的最短詞長設為單個漢字";
"chkAlsoConfirmAssociatedCandidatesByEnter.title" = "允許使用 Enter 確認當前選中的聯想詞";
"chkAutoCorrectReadingCombination.title" = "敲字時自動糾正讀音組合";
"chkFetchSuggestionsFromUserOverrideModel.title" = "在敲字時自動套用來自半衰記憶模組的建議";
"chkUseFixecCandidateOrderOnSelection.title" = "以固定順序來陳列選字窗內的候選字";
@ -48,7 +49,7 @@
"E1l-m8-xgb.title" = "進階設定";
"eia-1F-Do0.title" = "自動將繁體中文字轉換為日本簡化字JIS 新字體)";
"f2j-xD-4xK.title" = "敲 ESC 鍵以清空整個輸入緩衝區";
"f8i-69-zxm.title" = "自動重新載入變更過的使用者數據內容";
"f8i-69-zxm.title" = "自動重新載入變更過的使用者資料內容";
"FnD-oH-El5.title" = "選字鍵:";
"FSG-lN-CJO.title" = "英文";
"FVC-br-H57.title" = "輪替候選字";
@ -73,8 +74,8 @@
"sZx-18-8dO.title" = "偵錯模式";
"TXr-FF-ehw.title" = "繁體中文";
"ueU-Rz-a1C.title" = "指定 (Shift+)Tab 熱鍵在選字窗內的輪替操作對象。";
"Uyz-xL-TVN.title" = "輸出設定";
"W24-T4-cg0.title" = "啟用 CNS11643 全字庫支援 (2022-06-15)";
"xibOutputSettings.title" = "輸出設定";
"W24-T4-cg0.title" = "啟用 CNS11643 全字庫支援 (2022-07-20)";
"wFR-zX-M8H.title" = "拼音並擊(組字區與工具提示內顯示漢語拼音)";
"wN3-k3-b2a.title" = "請在此指定您想指定的使用者語彙檔案目錄。無效值會被忽略。";
"wQ9-px-b07.title" = "Apple 動態注音鍵盤佈局(大千與倚天)要求普通話/國音分析器的注音排列得配置為大千排列。";

View File

@ -3,9 +3,9 @@
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>1.8.3</string>
<string>1.8.4</string>
<key>CFBundleVersion</key>
<string>1983</string>
<string>1984</string>
<key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key>

View File

@ -157,10 +157,13 @@ DQ
</scrollView>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="fbv-c6-gW8">
<rect key="frame" x="382" y="69" width="143" height="32"/>
<buttonCell key="cell" type="push" title="Wiki" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ImH-h2-3FG">
<buttonCell key="cell" type="push" title="Website" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="ImH-h2-3FG">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btnWebsite:" target="-1" id="WNO-E7-7UJ"/>
</connections>
</button>
</subviews>
<constraints>

View File

@ -25,3 +25,5 @@
/* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */
"ttlAboutWindow.title" = "About vChewing Phrase Editor for macOS";
"ImH-h2-3FG.title" = "Website";

View File

@ -25,3 +25,5 @@
/* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */
"ttlAboutWindow.title" = "macOS 版威注音辞書データ編集アプリについて";
"ImH-h2-3FG.title" = "公式HP";

View File

@ -25,3 +25,5 @@
/* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */
"ttlAboutWindow.title" = "关于 macOS 版「威注音语汇编辑器」";
"ImH-h2-3FG.title" = "网站";

View File

@ -25,3 +25,5 @@
/* Class = "NSWindow"; title = "About vChewing Phrase Editor for macOS"; ObjectID = "ttlAboutWindow"; */
"ttlAboutWindow.title" = "關於 macOS 版「威注音語彙編輯器」";
"ImH-h2-3FG.title" = "網站";

View File

@ -57,8 +57,8 @@ import Cocoa
)
}
@IBAction func btnWiki(_: NSButton) {
if let url = URL(string: "https://gitee.com/vchewing/vChewing-macOS/wikis") {
@IBAction func btnWebsite(_ sender: NSButton) {
if let url = URL(string: "https://vchewing.github.io/") {
NSWorkspace.shared.open(url)
}
}

View File

@ -726,7 +726,7 @@
<key>USE_HFS+_COMPRESSION</key>
<false/>
<key>VERSION</key>
<string>1.8.3</string>
<string>1.8.4</string>
</dict>
<key>TYPE</key>
<integer>0</integer>

View File

@ -1389,7 +1389,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
@ -1399,7 +1399,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1428,13 +1428,13 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1465,7 +1465,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
DEAD_CODE_STRIPPING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
@ -1486,7 +1486,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1515,7 +1515,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
DEAD_CODE_STRIPPING = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1532,7 +1532,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1646,7 +1646,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1674,7 +1674,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1701,7 +1701,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
@ -1723,7 +1723,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -1745,7 +1745,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1765,7 +1765,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1787,7 +1787,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1983;
CURRENT_PROJECT_VERSION = 1984;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1801,7 +1801,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.8.3;
MARKETING_VERSION = 1.8.4;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -337,7 +337,7 @@ class KeyHandlerTestsNormalCHS: XCTestCase {
let enabled = mgrPrefs.halfWidthPunctuationEnabled
mgrPrefs.halfWidthPunctuationEnabled = false
let input = InputSignal(
inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: [],
inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: [],
isVerticalTyping: false
)
var state: InputStateProtocol = InputState.Empty()
@ -354,7 +354,7 @@ class KeyHandlerTestsNormalCHS: XCTestCase {
let enabled = mgrPrefs.halfWidthPunctuationEnabled
mgrPrefs.halfWidthPunctuationEnabled = false
let input = InputSignal(
inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: .option,
inputText: " ", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: .option,
isVerticalTyping: false
)
var state: InputStateProtocol = InputState.Empty()

View File

@ -75,7 +75,7 @@ class KeyHandlerTestsSCPCCHT: XCTestCase {
func testPunctuationTable() {
let input = InputSignal(
inputText: "`", keyCode: KeyCode.kSymbolMenuPhysicalKey.rawValue, charCode: 0, flags: .option
inputText: "`", keyCode: KeyCode.kSymbolMenuPhysicalKeyIntl.rawValue, charCode: 0, flags: .option
)
var state: InputStateProtocol = InputState.Empty()
_ = handler.handle(input: input, state: state) { newState in