From fc7981a0453463e195a29b6c1e3e65f6d16c5e53 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 19:02:46 +0800 Subject: [PATCH 01/24] Repo // Redirect UpdateInfoSite to the Releases page. --- Source/Resources/IME-Info.plist | 2 +- Update-Info.plist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Resources/IME-Info.plist b/Source/Resources/IME-Info.plist index b2aea635..220b7cd1 100644 --- a/Source/Resources/IME-Info.plist +++ b/Source/Resources/IME-Info.plist @@ -126,7 +126,7 @@ UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite - https://gitee.com/vchewing/vChewing-macOS + https://gitee.com/vChewing/vChewing-macOS/releases tsInputMethodCharacterRepertoireKey Hans diff --git a/Update-Info.plist b/Update-Info.plist index dc3e903d..e189ccff 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -5,7 +5,7 @@ UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite - https://gitee.com/vchewing/vChewing-macOS + https://gitee.com/vChewing/vChewing-macOS/releases CFBundleVersion 1923 CFBundleShortVersionString From dc89c562bc651112f57c15e76406523cfe82f11f Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 14:58:42 +0800 Subject: [PATCH 02/24] Gramambular // Boost MaximumBuildSpanLength to 10. --- .../Modules/LanguageParsers/Gramambular/BlockReadingBuilder.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Modules/LanguageParsers/Gramambular/BlockReadingBuilder.h b/Source/Modules/LanguageParsers/Gramambular/BlockReadingBuilder.h index 07fc9add..a74a79f4 100644 --- a/Source/Modules/LanguageParsers/Gramambular/BlockReadingBuilder.h +++ b/Source/Modules/LanguageParsers/Gramambular/BlockReadingBuilder.h @@ -57,8 +57,8 @@ protected: std::vector::const_iterator end, const std::string& separator); - // 最多使用六個字組成一個詞 - static const size_t MaximumBuildSpanLength = 6; + // 規定最多可以組成的詞的字數上限為 10 + static const size_t MaximumBuildSpanLength = 10; size_t m_cursorIndex; std::vector m_readings; From bf695f098dab777ba53ed148448f646c248f8bb7 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 16:21:27 +0800 Subject: [PATCH 03/24] KeyHandlerInput // Use KeyCode in lieu of CharCode as much as possible. - KeyCode recognition won't be affected by macOS Base Keyboard Layouts (but CharCode will, always). --- .../ControllerModules/KeyHandlerInput.swift | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandlerInput.swift b/Source/Modules/ControllerModules/KeyHandlerInput.swift index 96df1979..dc087714 100644 --- a/Source/Modules/ControllerModules/KeyHandlerInput.swift +++ b/Source/Modules/ControllerModules/KeyHandlerInput.swift @@ -19,12 +19,16 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH import Cocoa +// Use KeyCodes as much as possible since its recognition won't be affected by macOS Base Keyboard Layouts. // KeyCodes: https://eastmanreference.com/complete-list-of-applescript-key-codes enum KeyCode: UInt16 { case none = 0 + case space = 49 + case backSpace = 51 case esc = 53 case tab = 48 - case enter = 76 + case enterLF = 76 + case enterCR = 36 case up = 126 case down = 125 case left = 123 @@ -38,10 +42,6 @@ enum KeyCode: UInt16 { // CharCodes: https://theasciicode.com.ar/ascii-control-characters/horizontal-tab-ascii-code-9.html enum CharCode: UInt16 { - case space = 32 - case backSpace = 8 - case enter = 13 - case esc = 27 case symbolMenuKey_ABC = 96 } @@ -150,7 +150,7 @@ class KeyHandlerInput: NSObject { } @objc var isEnter: Bool { - (CharCode(rawValue: charCode) == CharCode.enter) || (KeyCode(rawValue: keyCode) == KeyCode.enter) + (KeyCode(rawValue: keyCode) == KeyCode.enterCR) || (KeyCode(rawValue: keyCode) == KeyCode.enterLF) } @objc var isUp: Bool { @@ -178,15 +178,15 @@ class KeyHandlerInput: NSObject { } @objc var isSpace: Bool { - CharCode(rawValue: charCode) == CharCode.space + KeyCode(rawValue: keyCode) == KeyCode.space } @objc var isBackSpace: Bool { - CharCode(rawValue: charCode) == CharCode.backSpace + KeyCode(rawValue: keyCode) == KeyCode.backSpace } @objc var isESC: Bool { - (CharCode(rawValue: charCode) == CharCode.esc) || (KeyCode(rawValue: keyCode) == KeyCode.esc) + KeyCode(rawValue: keyCode) == KeyCode.esc } @objc var isHome: Bool { @@ -226,6 +226,7 @@ class KeyHandlerInput: NSObject { } @objc var isSymbolMenuKey: Bool { + // 這裡用 CharCode 更合適,不然就無法輸入波浪鍵了。 CharCode(rawValue: charCode) == CharCode.symbolMenuKey_ABC } From a8257168af13936a814edf0e81aea07649ba6c04 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 19:38:10 +0800 Subject: [PATCH 04/24] AppDelegate // Make Debug Print Function Global, etc. --- Source/Modules/AppDelegate.swift | 23 +++++- .../Modules/ControllerModules/KeyHandler.mm | 81 +++++++++---------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/Source/Modules/AppDelegate.swift b/Source/Modules/AppDelegate.swift index 461b836b..3c5133b1 100644 --- a/Source/Modules/AppDelegate.swift +++ b/Source/Modules/AppDelegate.swift @@ -24,6 +24,7 @@ private let kCheckUpdateAutomatically = "CheckUpdateAutomatically" private let kNextUpdateCheckDateKey = "NextUpdateCheckDate" private let kUpdateInfoEndpointKey = "UpdateInfoEndpoint" private let kUpdateInfoSiteKey = "UpdateInfoSite" +private let kVersionDescription = "VersionDescription" private let kNextCheckInterval: TimeInterval = 86400.0 private let kTimeoutInterval: TimeInterval = 60.0 @@ -93,21 +94,23 @@ struct VersionUpdateApi { DispatchQueue.main.async { forced ? callback(.success(.noNeedToUpdate)) : callback(.success(.ignored)) } + IME.prtDebugIntel("vChewingDebug: Update // Order is not Ascending, assuming that there's no new version available.") return } - + IME.prtDebugIntel("vChewingDebug: Update // New version detected, proceeding to the next phase.") guard let siteInfoURLString = plist[kUpdateInfoSiteKey] as? String, let siteInfoURL = URL(string: siteInfoURLString) else { DispatchQueue.main.async { forced ? callback(.success(.noNeedToUpdate)) : callback(.success(.ignored)) } + IME.prtDebugIntel("vChewingDebug: Update // Failed from retrieving / parsing URL intel.") return } - + IME.prtDebugIntel("vChewingDebug: Update // URL intel retrieved, proceeding to the next phase.") var report = VersionUpdateReport(siteUrl: siteInfoURL) var versionDescription = "" - let versionDescriptions = plist["Description"] as? [AnyHashable: Any] + let versionDescriptions = plist[kVersionDescription] as? [AnyHashable: Any] if let versionDescriptions = versionDescriptions { var locale = "en" let supportedLocales = ["en", "zh-Hant", "zh-Hans", "ja"] @@ -128,6 +131,7 @@ struct VersionUpdateApi { DispatchQueue.main.async { callback(.success(.shouldUpdate(report: report))) } + IME.prtDebugIntel("vChewingDebug: Update // Callbck Complete.") } catch { DispatchQueue.main.async { forced ? callback(.success(.noNeedToUpdate)) : callback(.success(.ignored)) @@ -248,6 +252,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega report.remoteShortVersion, report.remoteVersion, report.versionDescription) + IME.prtDebugIntel("vChewingDebug: \(content)") ctlNonModalAlertWindow.shared.show(title: NSLocalizedString("New Version Available", comment: ""), content: content, confirmButtonTitle: NSLocalizedString("Visit Website", comment: ""), cancelButtonTitle: NSLocalizedString("Not Now", comment: ""), cancelAsDefault: false, delegate: self) case .noNeedToUpdate, .ignored: break @@ -258,6 +263,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega let title = NSLocalizedString("Update Check Failed", comment: "") let content = String(format: NSLocalizedString("There may be no internet connection or the server failed to respond.\n\nError message: %@", comment: ""), message) let buttonTitle = NSLocalizedString("Dismiss", comment: "") + IME.prtDebugIntel("vChewingDebug: \(content)") ctlNonModalAlertWindow.shared.show(title: title, content: content, confirmButtonTitle: buttonTitle, cancelButtonTitle: nil, cancelAsDefault: false, delegate: nil) default: break @@ -276,10 +282,19 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega func ctlNonModalAlertWindowDidCancel(_ controller: ctlNonModalAlertWindow) { updateNextStepURL = nil } - + // New About Window @IBAction func about(_ sender: Any) { (NSApp.delegate as? AppDelegate)?.showAbout() NSApplication.shared.activate(ignoringOtherApps: true) } } + +@objc public class IME: NSObject { + // Print debug information to the console. + @objc static func prtDebugIntel(_ strPrint: String) { + if Preferences.isDebugModeEnabled { + NSLog("vChewingErrorCallback: %@", strPrint) + } + } +} diff --git a/Source/Modules/ControllerModules/KeyHandler.mm b/Source/Modules/ControllerModules/KeyHandler.mm index e81d5b5d..82770558 100644 --- a/Source/Modules/ControllerModules/KeyHandler.mm +++ b/Source/Modules/ControllerModules/KeyHandler.mm @@ -354,7 +354,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; // see if we have a unigram for this if (!_languageModel->hasUnigramsForKey(reading)) { - [self errorCallbackConsolePrint:@"B49C0979"]; + [IME prtDebugIntel:@"B49C0979"]; errorCallback(); InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState]; stateCallback(inputting); @@ -578,7 +578,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; // strange behavior if we don't do this, "thinking" the key is not // actually consumed) if ([state isKindOfClass:[InputStateNotEmpty class]] || !_bpmfReadingBuffer->isEmpty()) { - [self errorCallbackConsolePrint:@"A9BFF20E"]; + [IME prtDebugIntel:@"A9BFF20E"]; errorCallback(); stateCallback(state); return YES; @@ -629,7 +629,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; } if (!_bpmfReadingBuffer->isEmpty()) { - [self errorCallbackConsolePrint:@"6ED95318"]; + [IME prtDebugIntel:@"6ED95318"]; errorCallback(); stateCallback(state); return YES; @@ -645,7 +645,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; marking.tooltipForInputting = currentState.tooltip; stateCallback(marking); } else { - [self errorCallbackConsolePrint:@"D326DEA3"]; + [IME prtDebugIntel:@"D326DEA3"]; errorCallback(); stateCallback(state); } @@ -655,7 +655,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState]; stateCallback(inputting); } else { - [self errorCallbackConsolePrint:@"7045E6F3"]; + [IME prtDebugIntel:@"7045E6F3"]; errorCallback(); stateCallback(state); } @@ -670,7 +670,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; } if (!_bpmfReadingBuffer->isEmpty()) { - [self errorCallbackConsolePrint:@"B3BA5257"]; + [IME prtDebugIntel:@"B3BA5257"]; errorCallback(); stateCallback(state); return YES; @@ -686,7 +686,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; marking.tooltipForInputting = currentState.tooltip; stateCallback(marking); } else { - [self errorCallbackConsolePrint:@"BB7F6DB9"]; + [IME prtDebugIntel:@"BB7F6DB9"]; errorCallback(); stateCallback(state); } @@ -696,7 +696,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState]; stateCallback(inputting); } else { - [self errorCallbackConsolePrint:@"A96AAD58"]; + [IME prtDebugIntel:@"A96AAD58"]; errorCallback(); stateCallback(state); } @@ -712,7 +712,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; } if (!_bpmfReadingBuffer->isEmpty()) { - [self errorCallbackConsolePrint:@"ABC44080"]; + [IME prtDebugIntel:@"ABC44080"]; errorCallback(); stateCallback(state); return YES; @@ -723,7 +723,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState]; stateCallback(inputting); } else { - [self errorCallbackConsolePrint:@"66D97F90"]; + [IME prtDebugIntel:@"66D97F90"]; errorCallback(); stateCallback(state); } @@ -738,7 +738,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; } if (!_bpmfReadingBuffer->isEmpty()) { - [self errorCallbackConsolePrint:@"9B69908D"]; + [IME prtDebugIntel:@"9B69908D"]; errorCallback(); stateCallback(state); return YES; @@ -749,7 +749,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; InputStateInputting *inputting = (InputStateInputting *)[self buildInputtingState]; stateCallback(inputting); } else { - [self errorCallbackConsolePrint:@"9B69908E"]; + [IME prtDebugIntel:@"9B69908E"]; errorCallback(); stateCallback(state); } @@ -764,7 +764,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; } if (!_bpmfReadingBuffer->isEmpty()) { - [self errorCallbackConsolePrint:@"9B6F908D"]; + [IME prtDebugIntel:@"9B6F908D"]; errorCallback(); } stateCallback(state); @@ -782,7 +782,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; _builder->deleteReadingBeforeCursor(); [self _walk]; } else { - [self errorCallbackConsolePrint:@"9D69908D"]; + [IME prtDebugIntel:@"9D69908D"]; errorCallback(); stateCallback(state); return YES; @@ -819,12 +819,12 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; stateCallback(inputting); } } else { - [self errorCallbackConsolePrint:@"9B69938D"]; + [IME prtDebugIntel:@"9B69938D"]; errorCallback(); stateCallback(state); } } else { - [self errorCallbackConsolePrint:@"9C69908D"]; + [IME prtDebugIntel:@"9C69908D"]; errorCallback(); stateCallback(state); } @@ -878,7 +878,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; _builder->insertReadingAtCursor(customPunctuation); poppedText = [self _popOverflowComposingTextAndWalk]; } else { // If there is still unfinished bpmf reading, ignore the punctuation - [self errorCallbackConsolePrint:@"A9B69908D"]; + [IME prtDebugIntel:@"A9B69908D"]; errorCallback(); stateCallback(state); return YES; @@ -920,7 +920,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; // Enter if ([input isEnter]) { if (![self.delegate keyHandler:self didRequestWriteUserPhraseWithState:state]) { - [self errorCallbackConsolePrint:@"5B69CC8D"]; + [IME prtDebugIntel:@"5B69CC8D"]; errorCallback(); return YES; } @@ -945,7 +945,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; stateCallback(marking); } } else { - [self errorCallbackConsolePrint:@"1149908D"]; + [IME prtDebugIntel:@"1149908D"]; errorCallback(); stateCallback(state); } @@ -967,7 +967,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; stateCallback(marking); } } else { - [self errorCallbackConsolePrint:@"9B51408D"]; + [IME prtDebugIntel:@"9B51408D"]; errorCallback(); stateCallback(state); } @@ -984,8 +984,6 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; { NSString *inputText = input.inputText; UniChar charCode = input.charCode; - NSString *char2Print = [NSString stringWithCharacters:&charCode length:1]; - NSLog(@"vChewingCandidateKeyDebug: %@", char2Print); VTCandidateController *gCurrentCandidateController = [self.delegate candidateControllerForKeyHandler:self]; BOOL cancelCandidateKey = [input isBackSpace] || [input isESC] || [input isDelete]; @@ -1032,7 +1030,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; ([input isShiftHold] ? [gCurrentCandidateController highlightPreviousCandidate] : [gCurrentCandidateController highlightNextCandidate]) ; if (!updated) { - [self errorCallbackConsolePrint:@"9B691919"]; + [IME prtDebugIntel:@"9B691919"]; errorCallback(); } return YES; @@ -1041,7 +1039,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([input isSpace] || [input isPageDown] || input.emacsKey == vChewingEmacsKeyNextPage) { BOOL updated = [gCurrentCandidateController showNextPage]; if (!updated) { - [self errorCallbackConsolePrint:@"9B691919"]; + [IME prtDebugIntel:@"9B691919"]; errorCallback(); } return YES; @@ -1050,7 +1048,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([input isPageUp]) { BOOL updated = [gCurrentCandidateController showPreviousPage]; if (!updated) { - [self errorCallbackConsolePrint:@"9569955D"]; + [IME prtDebugIntel:@"9569955D"]; errorCallback(); } return YES; @@ -1060,13 +1058,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) { BOOL updated = [gCurrentCandidateController highlightPreviousCandidate]; if (!updated) { - [self errorCallbackConsolePrint:@"1145148D"]; + [IME prtDebugIntel:@"1145148D"]; errorCallback(); } } else { BOOL updated = [gCurrentCandidateController showPreviousPage]; if (!updated) { - [self errorCallbackConsolePrint:@"1919810D"]; + [IME prtDebugIntel:@"1919810D"]; errorCallback(); } } @@ -1076,7 +1074,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if (input.emacsKey == vChewingEmacsKeyBackward) { BOOL updated = [gCurrentCandidateController highlightPreviousCandidate]; if (!updated) { - [self errorCallbackConsolePrint:@"9B89308D"]; + [IME prtDebugIntel:@"9B89308D"]; errorCallback(); } return YES; @@ -1086,13 +1084,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) { BOOL updated = [gCurrentCandidateController highlightNextCandidate]; if (!updated) { - [self errorCallbackConsolePrint:@"9B65138D"]; + [IME prtDebugIntel:@"9B65138D"]; errorCallback(); } } else { BOOL updated = [gCurrentCandidateController showNextPage]; if (!updated) { - [self errorCallbackConsolePrint:@"9244908D"]; + [IME prtDebugIntel:@"9244908D"]; errorCallback(); } } @@ -1102,7 +1100,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if (input.emacsKey == vChewingEmacsKeyForward) { BOOL updated = [gCurrentCandidateController highlightNextCandidate]; if (!updated) { - [self errorCallbackConsolePrint:@"9B2428D"]; + [IME prtDebugIntel:@"9B2428D"]; errorCallback(); } return YES; @@ -1112,13 +1110,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) { BOOL updated = [gCurrentCandidateController showPreviousPage]; if (!updated) { - [self errorCallbackConsolePrint:@"9B614524"]; + [IME prtDebugIntel:@"9B614524"]; errorCallback(); } } else { BOOL updated = [gCurrentCandidateController highlightPreviousCandidate]; if (!updated) { - [self errorCallbackConsolePrint:@"ASD9908D"]; + [IME prtDebugIntel:@"ASD9908D"]; errorCallback(); } } @@ -1129,13 +1127,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([gCurrentCandidateController isKindOfClass:[VTHorizontalCandidateController class]]) { BOOL updated = [gCurrentCandidateController showNextPage]; if (!updated) { - [self errorCallbackConsolePrint:@"92B990DD"]; + [IME prtDebugIntel:@"92B990DD"]; errorCallback(); } } else { BOOL updated = [gCurrentCandidateController highlightNextCandidate]; if (!updated) { - [self errorCallbackConsolePrint:@"6B99908D"]; + [IME prtDebugIntel:@"6B99908D"]; errorCallback(); } } @@ -1144,7 +1142,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if ([input isHome] || input.emacsKey == vChewingEmacsKeyHome) { if (gCurrentCandidateController.selectedCandidateIndex == 0) { - [self errorCallbackConsolePrint:@"9B6EDE8D"]; + [IME prtDebugIntel:@"9B6EDE8D"]; errorCallback(); } else { gCurrentCandidateController.selectedCandidateIndex = 0; @@ -1167,7 +1165,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; if (([input isEnd] || input.emacsKey == vChewingEmacsKeyEnd) && candidates.count > 0) { if (gCurrentCandidateController.selectedCandidateIndex == candidates.count - 1) { - [self errorCallbackConsolePrint:@"9B69AAAD"]; + [IME prtDebugIntel:@"9B69AAAD"]; errorCallback(); } else { gCurrentCandidateController.selectedCandidateIndex = candidates.count - 1; @@ -1245,7 +1243,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; } } - [self errorCallbackConsolePrint:@"172A0F81"]; + [IME prtDebugIntel:@"172A0F81"]; errorCallback(); return YES; } @@ -1443,11 +1441,4 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; return nil; } --(void)errorCallbackConsolePrint:(NSString *)strPrint -{ - if (Preferences.isDebugModeEnabled) { - NSLog(@"vChewingErrorCallback: %@", strPrint); - } -} - @end From d7115a42df0cd77fa195ebf59a62c8fd5431fdaf Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 20:44:39 +0800 Subject: [PATCH 05/24] ctlAlertWindow // Make the NonModalAlertWindow work again. - A bug was introduced when filenames were rebranded, leading to the failure of calling the correct XIB window. This commit fixes this issue. --- Source/WindowControllers/ctlNonModalAlertWindow.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/WindowControllers/ctlNonModalAlertWindow.swift b/Source/WindowControllers/ctlNonModalAlertWindow.swift index 2097ea4c..a9ed42a3 100644 --- a/Source/WindowControllers/ctlNonModalAlertWindow.swift +++ b/Source/WindowControllers/ctlNonModalAlertWindow.swift @@ -26,7 +26,7 @@ import Cocoa class ctlNonModalAlertWindow: NSWindowController { @objc(sharedInstance) - static let shared = ctlNonModalAlertWindow(windowNibName: "ctlNonModalAlertWindow") + static let shared = ctlNonModalAlertWindow(windowNibName: "frmNonModalAlertWindow") @IBOutlet weak var titleTextField: NSTextField! @IBOutlet weak var contentTextField: NSTextField! From 566b83c2c08232dc00b8d593b83e94f04f437523 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 20:58:52 +0800 Subject: [PATCH 06/24] LMInstantiator // Flip the priority sequence in UserPhrasesLM. --- Source/Modules/LangModelRelated/LMInstantiator.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Modules/LangModelRelated/LMInstantiator.mm b/Source/Modules/LangModelRelated/LMInstantiator.mm index 871206d7..6f61e65c 100644 --- a/Source/Modules/LangModelRelated/LMInstantiator.mm +++ b/Source/Modules/LangModelRelated/LMInstantiator.mm @@ -125,6 +125,9 @@ const std::vector LMInstantiator::unigramsForKey(c if (m_userPhrases.hasUnigramsForKey(key)) { std::vector rawUserUnigrams = m_userPhrases.unigramsForKey(key); + // 用這句指令讓使用者語彙檔案內的詞條優先順序隨著行數增加而逐漸增高。 + // 這樣一來就可以在就地新增語彙時徹底複寫優先權。 + std::reverse(rawUserUnigrams.begin(), rawUserUnigrams.end()); userUnigrams = filterAndTransformUnigrams(rawUserUnigrams, excludedValues, insertedValues); } From 1e7ada1598dd17add92eda7adb31882afff8402a Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 21:05:05 +0800 Subject: [PATCH 07/24] InputState // Revert "Fix the term used for overriding candidate rates." - This reverts commit 55bfcefaa81715f016443600e472987670bfce9d. - Reason: In the previous commit we ensured that the priority boost function works well in UserPhrasesLM by flipping its vector in the LMInstantiator. --- Source/Modules/ControllerModules/InputState.swift | 2 +- Source/Resources/Base.lproj/Localizable.strings | 2 +- Source/Resources/en.lproj/Localizable.strings | 2 +- Source/Resources/ja.lproj/Localizable.strings | 2 +- Source/Resources/zh-Hans.lproj/Localizable.strings | 2 +- Source/Resources/zh-Hant.lproj/Localizable.strings | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Modules/ControllerModules/InputState.swift b/Source/Modules/ControllerModules/InputState.swift index babd93b4..e488c15e 100644 --- a/Source/Modules/ControllerModules/InputState.swift +++ b/Source/Modules/ControllerModules/InputState.swift @@ -184,7 +184,7 @@ class InputState: NSObject { let joined = selectedReadings.joined(separator: "-") let exist = mgrLangModel.checkIfUserPhraseExist(userPhrase: text, mode: ctlInputMethod.currentKeyHandler.inputMode, key: joined) if exist { - return String(format: NSLocalizedString("\"%@\" already exists, ENTER to override its priority.", comment: ""), text) + return String(format: NSLocalizedString("\"%@\" already exists, ENTER to boost its priority.", comment: ""), text) } return String(format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: ""), text) diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index 0600f2b2..fac28d72 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -24,7 +24,7 @@ "\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase."; "\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase."; "\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase."; -"\"%@\" already exists, ENTER to override its priority." = "\"%@\" already exists, ENTER to override its priority."; +"\"%@\" already exists, ENTER to boost its priority." = "\"%@\" already exists, ENTER to boost its priority."; "Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…"; "Use Phrase Replacement" = "Use Phrase Replacement"; "Candidates keys cannot be empty." = "Candidates keys cannot be empty."; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 0600f2b2..fac28d72 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -24,7 +24,7 @@ "\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase."; "\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase."; "\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase."; -"\"%@\" already exists, ENTER to override its priority." = "\"%@\" already exists, ENTER to override its priority."; +"\"%@\" already exists, ENTER to boost its priority." = "\"%@\" already exists, ENTER to boost its priority."; "Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…"; "Use Phrase Replacement" = "Use Phrase Replacement"; "Candidates keys cannot be empty." = "Candidates keys cannot be empty."; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index 6d599f13..00026872 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -24,7 +24,7 @@ "\"%@\" length must ≥ 2 for a user phrase." = "「%@」もう1つ文字のお選びを。"; "\"%@\" length should ≤ %d for a user phrase." = "「%@」文字数過剰で登録不可、%d 文字以内にして下さい。"; "\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。"; -"\"%@\" already exists, ENTER to override its priority." = "「%@」は既存語彙であり、ENTER で優先順位を再調整。"; +"\"%@\" already exists, ENTER to boost its priority." = "「%@」は既存語彙であり、ENTER で最優先にする。"; "Edit Phrase Replacement Table…" = "言葉置換表を編集…"; "Use Phrase Replacement" = "言葉置換機能"; "Candidates keys cannot be empty." = "言選り用キー陣列に何かキーをご登録ください。"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index 8d811d21..bee4cf8e 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -24,7 +24,7 @@ "\"%@\" length must ≥ 2 for a user phrase." = "「%@」字数不足以自订语汇。"; "\"%@\" length should ≤ %d for a user phrase." = "「%@」字数超过 %d、无法自订。"; "\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。"; -"\"%@\" already exists, ENTER to override its priority." = "「%@」已存在,敲 ENTER 以覆写其权重。"; +"\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其权重。"; "Edit Phrase Replacement Table…" = "编辑语汇置换表…"; "Use Phrase Replacement" = "使用语汇置换"; "Candidates keys cannot be empty." = "您必须指定选字键。"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index 44db7b42..3a1b9998 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -24,7 +24,7 @@ "\"%@\" length must ≥ 2 for a user phrase." = "「%@」字數不足以自訂語彙。"; "\"%@\" length should ≤ %d for a user phrase." = "「%@」字數超過 %d、無法自訂。"; "\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。"; -"\"%@\" already exists, ENTER to override its priority." = "「%@」已存在,敲 ENTER 以覆寫其權重。"; +"\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其權重。"; "Edit Phrase Replacement Table…" = "編輯語彙置換表…"; "Use Phrase Replacement" = "使用語彙置換"; "Candidates keys cannot be empty." = "您必須指定選字鍵。"; From 10126d2239e9a73bd498d31a770209e0c6ef4c8d Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 21:24:40 +0800 Subject: [PATCH 08/24] Repo // Use Xcode to manage miscellaneous root files. --- vChewing.xcodeproj/project.pbxproj | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 5a07061b..cb1d74fb 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -164,6 +164,12 @@ 5B05A47F27AFF84200437698 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmAboutWindow.strings; sourceTree = ""; }; 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleKeyboardConverter.swift; sourceTree = ""; }; + 5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHS.txt"; sourceTree = ""; }; + 5B18BA7027C7BD8B0056EB19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; + 5B18BA7127C7BD8B0056EB19 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 5B18BA7227C7BD8B0056EB19 /* LICENSE.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; }; + 5B18BA7327C7BD8C0056EB19 /* LICENSE-JPN.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-JPN.txt"; sourceTree = ""; }; + 5B18BA7427C7BD8C0056EB19 /* LICENSE-CHT.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHT.txt"; sourceTree = ""; }; 5B2DB16D27AF6891006D874E /* data-chs.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "data-chs.txt"; path = "Data/data-chs.txt"; sourceTree = ""; }; 5B2DB16E27AF6891006D874E /* data-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "data-cht.txt"; path = "Data/data-cht.txt"; sourceTree = ""; }; 5B2DB17127AF8771006D874E /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Data/Makefile; sourceTree = ""; }; @@ -337,6 +343,18 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 5B18BA7527C7BF6D0056EB19 /* MiscRootFiles */ = { + isa = PBXGroup; + children = ( + 5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */, + 5B18BA7427C7BD8C0056EB19 /* LICENSE-CHT.txt */, + 5B18BA7327C7BD8C0056EB19 /* LICENSE-JPN.txt */, + 5B18BA7227C7BD8B0056EB19 /* LICENSE.txt */, + 5B18BA7127C7BD8B0056EB19 /* README.md */, + ); + name = MiscRootFiles; + sourceTree = ""; + }; 5B62A30127AE732800A19448 /* 3rdParty */ = { isa = PBXGroup; children = ( @@ -644,12 +662,14 @@ isa = PBXGroup; children = ( 5BBD627827B6C4D900271480 /* Update-Info.plist */, + 5B18BA7027C7BD8B0056EB19 /* Makefile */, 6ACA41E715FC1D9000935EF6 /* Installer */, 6A0D4EC215FC0D3C00ABF4B3 /* Source */, 5BD05BB927B2A429004C4F1D /* UserPhraseEditor */, - 5BDC5CB127C28E8B00E1CCE2 /* KeyboardExtension */, 6A0D4EA315FC0D2D00ABF4B3 /* Products */, D47D73C127A7200500255A50 /* Frameworks */, + 5BDC5CB127C28E8B00E1CCE2 /* KeyboardExtension */, + 5B18BA7527C7BF6D0056EB19 /* MiscRootFiles */, ); sourceTree = ""; }; From ed50045fc6f9a5c82ed931cc76a6f2f88dcc9a8d Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 21:24:09 +0800 Subject: [PATCH 09/24] LICENSE // Fix the EOF. --- LICENSE-JPN.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE-JPN.txt b/LICENSE-JPN.txt index 126f3e06..c7b8afff 100644 --- a/LICENSE-JPN.txt +++ b/LICENSE-JPN.txt @@ -11,4 +11,4 @@ vChewing macOS: MIT商標不許可ライセンス (MIT-NTL License) ロ)上記の通知要件を満たすために必要な場合を除き、コントリビューターの商号、商標、サービスマーク、または製品名を使用するための商標ライセンスは付与されていません。 -ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もなく提供されます。ここでいう保証とは、商品性、特定の目的への適合性、および権利非侵害についての保証も含みますが、それに限定されるものではありません。 作者または著作権者は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切の請求、損害、その他の義務について何らの責任も負わないものとします。 \ No newline at end of file +ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もなく提供されます。ここでいう保証とは、商品性、特定の目的への適合性、および権利非侵害についての保証も含みますが、それに限定されるものではありません。 作者または著作権者は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切の請求、損害、その他の義務について何らの責任も負わないものとします。 From 8a6ea8e0e7a3b3c8358f14b0ef800e86c94dac5c Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 22:33:17 +0800 Subject: [PATCH 10/24] LMConsolidator // Do not hurt the latest override information. --- Source/Modules/FileHandlers/LMConsolidator.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Modules/FileHandlers/LMConsolidator.mm b/Source/Modules/FileHandlers/LMConsolidator.mm index 1cb685df..f0a3cbb6 100644 --- a/Source/Modules/FileHandlers/LMConsolidator.mm +++ b/Source/Modules/FileHandlers/LMConsolidator.mm @@ -98,7 +98,9 @@ bool LMConsolidator::ConsolidateContent(const char *path, bool shouldCheckPragma } } // 在第二遍 for 運算之前,針對 vecEntry 去除重複條目。 + std::reverse(vecEntry.begin(), vecEntry.end()); // 先首尾顛倒,免得破壞最新的 override 資訊。 vecEntry.erase(unique(vecEntry.begin(), vecEntry.end()), vecEntry.end()); // 去重複。 + std::reverse(vecEntry.begin(), vecEntry.end()); // 再顛倒回來。 // 統整完畢。開始將統整過的內容寫入檔案。 ofstream zfdContentConsolidatorOutput(path); // 這裡是要從頭開始重寫檔案內容,所以不需要「 ios_base::app 」。 if (!LMConsolidator::CheckPragma(path)){ From 028aab03b8620399060f9ac20bf2252f54df9a78 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 22:27:48 +0800 Subject: [PATCH 11/24] UPE // Do not hurt the latest override information. --- UserPhraseEditor/StringExtension.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/UserPhraseEditor/StringExtension.swift b/UserPhraseEditor/StringExtension.swift index 7a7ae15e..1007a53d 100644 --- a/UserPhraseEditor/StringExtension.swift +++ b/UserPhraseEditor/StringExtension.swift @@ -491,15 +491,16 @@ extension String { // Step 4: Deduplication. arrData = strProcessed.components(separatedBy: "\n") strProcessed = "" // Reset its value - let arrDataDeduplicated = Array(NSOrderedSet(array: arrData).array as! [String]) - for lineData in arrDataDeduplicated { + // 下面兩行的 reversed 是首尾顛倒,免得破壞最新的 override 資訊。 + let arrDataDeduplicated = Array(NSOrderedSet(array: arrData.reversed()).array as! [String]) + for lineData in arrDataDeduplicated.reversed() { strProcessed += lineData strProcessed += "\n" } // Step 5: Remove duplicated newlines at the end of the file. strProcessed.regReplace(pattern: "\\n\\n", replaceWith: "\n") - + // Step 6: Commit Formatted Contents. self = strProcessed } From 9a8c720632bea85afce18d53152542ec720404db Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 22:33:08 +0800 Subject: [PATCH 12/24] UPE // No toleration to consecutive new lines. --- UserPhraseEditor/StringExtension.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UserPhraseEditor/StringExtension.swift b/UserPhraseEditor/StringExtension.swift index 1007a53d..8a7c703e 100644 --- a/UserPhraseEditor/StringExtension.swift +++ b/UserPhraseEditor/StringExtension.swift @@ -499,7 +499,7 @@ extension String { } // Step 5: Remove duplicated newlines at the end of the file. - strProcessed.regReplace(pattern: "\\n\\n", replaceWith: "\n") + strProcessed.regReplace(pattern: "\\n+", replaceWith: "\n") // Step 6: Commit Formatted Contents. self = strProcessed From f971339f3e8d9f17da3680ca5a35842206f4a4d1 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 26 Feb 2022 14:28:03 +0800 Subject: [PATCH 13/24] UPE // UTF8 Surrogate Pair Issue Fix. - We don't use RegEx to remove the trailing spaces of each lines anymore. Reason: Swift built-in RegEx relies on NSRange which has no UTF8 surrogate pair support, leading to incorrectly-calculated modification spot when dealing with lines that contains surrogate-pair characters. - Also optimized the format-consolidating process. --- UserPhraseEditor/StringExtension.swift | 33 +++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/UserPhraseEditor/StringExtension.swift b/UserPhraseEditor/StringExtension.swift index 8a7c703e..70faf0f0 100644 --- a/UserPhraseEditor/StringExtension.swift +++ b/UserPhraseEditor/StringExtension.swift @@ -28,26 +28,31 @@ extension String { } mutating func formatConsolidate(HYPY2BPMF: Bool) { // Step 1: Consolidating formats per line. - var arrData = self.components(separatedBy: "\n") - var varLineData = "" - var strProcessed = "" - for lineData in arrData { - varLineData = lineData - varLineData.regReplace(pattern: " ", replaceWith: " ") // CJKWhiteSpace to ASCIISpace - varLineData.regReplace(pattern: " ", replaceWith: " ") // NonBreakWhiteSpace to ASCIISpace - varLineData.regReplace(pattern: "\\s+", replaceWith: " ") // Consolidating Consecutive Spaves - varLineData.regReplace(pattern: "^\\s", replaceWith: "") // Trim Leading Space - varLineData.regReplace(pattern: "\\s$", replaceWith: "") // Trim Trailing Space - strProcessed += varLineData - strProcessed += "\n" + var strProcessed = self + // 預處理格式 + strProcessed = strProcessed.replacingOccurrences(of: " #MACOS", with: "") // 去掉 macOS 標記 + strProcessed = strProcessed.replacingOccurrences(of: " ", with: " ") // CJKWhiteSpace (\x{3000}) to ASCII Space + strProcessed = strProcessed.replacingOccurrences(of: " ", with: " ") // NonBreakWhiteSpace (\x{A0}) to ASCII Space + strProcessed = strProcessed.replacingOccurrences(of: "\t", with: " ") // Tab to ASCII Space + strProcessed.regReplace(pattern: "\\f", replaceWith: "\n") // Form Feed to LF + strProcessed = strProcessed.replacingOccurrences(of: "\r", with: "\n") // CR to LF + strProcessed.regReplace(pattern: " +", replaceWith: " ") // 統整連續空格為一個 ASCII 空格 + strProcessed.regReplace(pattern: "\\n+", replaceWith: "\n") // 統整連續 LF 為一個 LF + strProcessed = strProcessed.replacingOccurrences(of: " \n", with: "\n") // 去除行尾空格 + strProcessed = strProcessed.replacingOccurrences(of: "\n ", with: "\n") // 去除行首空格 + if strProcessed.prefix(1) == " " { // 去除檔案開頭空格 + strProcessed.removeFirst() } - + if strProcessed.suffix(1) == " " { // 去除檔案結尾空格 + strProcessed.removeLast() + } + var arrData = [""] if HYPY2BPMF { // Step 0: Convert HanyuPinyin to Bopomofo. arrData = strProcessed.components(separatedBy: "\n") strProcessed = "" // Reset its value for lineData in arrData { - varLineData = lineData + var varLineData = lineData // 漢語拼音轉注音,得先從最長的可能的拼音組合開始轉起, // 這樣等轉換到更短的可能的漢語拼音組合時就不會出錯。 // 依此類推,聲調放在最後來轉換。 From d65052338749db6601dfb00691314e2c4a1744a0 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 26 Feb 2022 02:57:03 +0800 Subject: [PATCH 14/24] CoreLM // Implementing step-based debug prints. --- .../LangModelRelated/SubLanguageModels/CoreLM.mm | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Source/Modules/LangModelRelated/SubLanguageModels/CoreLM.mm b/Source/Modules/LangModelRelated/SubLanguageModels/CoreLM.mm index 683106ce..42cf9aae 100644 --- a/Source/Modules/LangModelRelated/SubLanguageModels/CoreLM.mm +++ b/Source/Modules/LangModelRelated/SubLanguageModels/CoreLM.mm @@ -123,6 +123,7 @@ start: c = *head; // \s -> error if (c == ' ') { + syslog(LOG_CONS, "vChewingDebug: CoreLM // Start: \\s -> error"); goto error; } // \n -> start @@ -139,12 +140,14 @@ start: state1: // EOF -> error if (head == end) { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 1: EOF -> error"); goto error; } c = *head; // \n -> error if (c == '\n') { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 1: \\n -> error"); goto error; } // \s -> state2 + zero out ending + record column start @@ -162,12 +165,14 @@ state1: state2: // eof -> error if (head == end) { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 2: EOF -> error"); goto error; } c = *head; // \n, \s -> error if (c == '\n' || c == ' ') { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 2: \\n \\s -> error"); goto error; } @@ -179,6 +184,7 @@ state2: state3: // eof -> error if (head == end) { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 3: EOF -> error"); goto error; } @@ -186,6 +192,7 @@ state3: // \n -> error if (c == '\n') { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 3: \\n -> error"); goto error; } // \s -> state4 + zero out ending + record column start @@ -203,12 +210,14 @@ state3: state4: // eof -> error if (head == end) { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 4: EOF -> error"); goto error; } c = *head; // \n, \s -> error if (c == '\n' || c == ' ') { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 4: \\n \\s -> error"); goto error; } @@ -221,12 +230,14 @@ state4: state5: // eof -> error if (head == end) { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 5: EOF -> error"); goto error; } c = *head; // \s -> error if (c == ' ') { + syslog(LOG_CONS, "vChewingDebug: CoreLM // state 5: \\s -> error"); goto error; } // \n -> start @@ -253,7 +264,7 @@ end: emptyRow.value = space; emptyRow.logProbability = zero; keyRowMap[space].push_back(emptyRow); - + syslog(LOG_CONS, "vChewingDebug: CoreLM // File Load Complete."); return true; } From 693fc9e7d1623abf7de0f664add8e985a1e5fe9a Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 23:49:01 +0800 Subject: [PATCH 15/24] Data // Preparing for DataCompiler. --- vChewing.xcodeproj/project.pbxproj | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index cb1d74fb..fdbd60be 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -163,6 +163,7 @@ 5B05A47C27AFF7CF00437698 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 5B05A47F27AFF84200437698 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/frmAboutWindow.strings; sourceTree = ""; }; 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; + 5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dataCompiler.swift; sourceTree = ""; }; 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleKeyboardConverter.swift; sourceTree = ""; }; 5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHS.txt"; sourceTree = ""; }; 5B18BA7027C7BD8B0056EB19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; @@ -343,6 +344,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 5B0C5EDE27C7D94C0078037C /* DataCompiler */ = { + isa = PBXGroup; + children = ( + 5B0C5EDF27C7D9870078037C /* dataCompiler.swift */, + ); + path = DataCompiler; + sourceTree = ""; + }; 5B18BA7527C7BF6D0056EB19 /* MiscRootFiles */ = { isa = PBXGroup; children = ( @@ -663,6 +672,7 @@ children = ( 5BBD627827B6C4D900271480 /* Update-Info.plist */, 5B18BA7027C7BD8B0056EB19 /* Makefile */, + 5B0C5EDE27C7D94C0078037C /* DataCompiler */, 6ACA41E715FC1D9000935EF6 /* Installer */, 6A0D4EC215FC0D3C00ABF4B3 /* Source */, 5BD05BB927B2A429004C4F1D /* UserPhraseEditor */, From 6f5ac531eee548e48439dd2880c4082c9fea3609 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 23:49:09 +0800 Subject: [PATCH 16/24] IME // Introducing DataCompiler. - We included this file in vChewing main repo for further research purposes. - The one in the data submodule is what we are actually using. --- DataCompiler/dataCompiler.swift | 409 ++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 DataCompiler/dataCompiler.swift diff --git a/DataCompiler/dataCompiler.swift b/DataCompiler/dataCompiler.swift new file mode 100644 index 00000000..7565a568 --- /dev/null +++ b/DataCompiler/dataCompiler.swift @@ -0,0 +1,409 @@ +// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). +/* +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +2. 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 above. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +import Foundation + +// MARK: - 前導工作 +fileprivate extension String { + mutating func regReplace(pattern: String, replaceWith: String = "") { + do { + let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive) + let range = NSRange(location: 0, length: count) + self = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replaceWith) + } catch { return } + } +} + +fileprivate func getDocumentsDirectory() -> URL { + let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + return paths[0] +} + +// MARK: - 引入小數點位數控制函數 +// Ref: https://stackoverflow.com/a/32581409/4162914 +fileprivate extension Float { + func rounded(toPlaces places:Int) -> Float { + let divisor = pow(10.0, Float(places)) + return (self * divisor).rounded() / divisor + } +} + +// MARK: - 引入幂乘函數 +// Ref: https://stackoverflow.com/a/41581695/4162914 +precedencegroup ExponentiationPrecedence { + associativity: right + higherThan: MultiplicationPrecedence +} + +infix operator ** : ExponentiationPrecedence + +func ** (_ base: Double, _ exp: Double) -> Double { + return pow(base, exp) +} + +func ** (_ base: Float, _ exp: Float) -> Float { + return pow(base, exp) +} + +// MARK: - 定義檔案結構 + +struct Entry { + var valPhone: String = "" + var valPhrase: String = "" + var valWeight: Float = -1.0 + var valCount: Int = 0 +} + +// MARK: - 登記全局根常數變數 + +fileprivate let urlCurrentFolder = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + +fileprivate let url_CHS_Custom: String = "./components/chs/phrases-custom-chs.txt" +fileprivate let url_CHS_MCBP: String = "./components/chs/phrases-mcbp-chs.txt" +fileprivate let url_CHS_MOE: String = "./components/chs/phrases-moe-chs.txt" +fileprivate let url_CHS_VCHEW: String = "./components/chs/phrases-vchewing-chs.txt" + +fileprivate let url_CHT_Custom: String = "./components/cht/phrases-custom-cht.txt" +fileprivate let url_CHT_MCBP: String = "./components/cht/phrases-mcbp-cht.txt" +fileprivate let url_CHT_MOE: String = "./components/cht/phrases-moe-cht.txt" +fileprivate let url_CHT_VCHEW: String = "./components/cht/phrases-vchewing-cht.txt" + +fileprivate let urlKanjiCore: String = "./components/common/char-kanji-core.txt" +fileprivate let urlPunctuation: String = "./components/common/data-punctuations.txt" +fileprivate let urlMiscBPMF: String = "./components/common/char-misc-bpmf.txt" +fileprivate let urlMiscNonKanji: String = "./components/common/char-misc-nonkanji.txt" + +fileprivate let urlOutputCHS: String = "./data-chs.txt" +fileprivate let urlOutputCHT: String = "./data-cht.txt" + +// MARK: - 載入詞組檔案且輸出數組 + +func rawDictForPhrases(isCHS: Bool) -> [Entry] { + var arrEntryRAW: [Entry] = [] + var strRAW: String = "" + let urlCustom: String = isCHS ? url_CHS_Custom : url_CHT_Custom + let urlMCBP: String = isCHS ? url_CHS_MCBP : url_CHT_MCBP + let urlMOE: String = isCHS ? url_CHS_MOE : url_CHT_MOE + let urlVCHEW: String = isCHS ? url_CHS_VCHEW : url_CHT_VCHEW + let i18n: String = isCHS ? "簡體中文" : "繁體中文" + // 讀取內容 + do { + strRAW += try String(contentsOfFile: urlCustom, encoding: .utf8) + strRAW += "\n" + strRAW += try String(contentsOfFile: urlMCBP, encoding: .utf8) + strRAW += "\n" + strRAW += try String(contentsOfFile: urlMOE, encoding: .utf8) + strRAW += "\n" + strRAW += try String(contentsOfFile: urlVCHEW, encoding: .utf8) + } + catch { + NSLog(" - Exception happened when reading raw phrases data.") + return [] + } + // 預處理格式 + strRAW = strRAW.replacingOccurrences(of: " #MACOS", with: "") // 去掉 macOS 標記 + strRAW = strRAW.replacingOccurrences(of: " ", with: " ") // CJKWhiteSpace (\x{3000}) to ASCII Space + strRAW = strRAW.replacingOccurrences(of: " ", with: " ") // NonBreakWhiteSpace (\x{A0}) to ASCII Space + strRAW = strRAW.replacingOccurrences(of: "\t", with: " ") // Tab to ASCII Space + strRAW.regReplace(pattern: "\\f", replaceWith: "\n") // Form Feed to LF + strRAW = strRAW.replacingOccurrences(of: "\r", with: "\n") // CR to LF + strRAW.regReplace(pattern: " +", replaceWith: " ") // 統整連續空格為一個 ASCII 空格 + // strRAW.regReplace(pattern: "\\n+", replaceWith: "\n") // 統整連續 LF 為一個 LF + // (不需要處理純空行,因為空記錄不會被轉為 Entry) + strRAW = strRAW.replacingOccurrences(of: " \n", with: "\n") // 去除行尾空格 + strRAW = strRAW.replacingOccurrences(of: "\n ", with: "\n") // 去除行首空格 + if strRAW.prefix(1) == " " { // 去除檔案開頭空格 + strRAW.removeFirst() + } + if strRAW.suffix(1) == " " { // 去除檔案結尾空格 + strRAW.removeLast() + } + // 正式整理格式,現在就開始去重複: + let arrData = Array(NSOrderedSet(array: strRAW.components(separatedBy: "\n")).array as! [String]) + var varLineData: String = "" + for lineData in arrData { + varLineData = lineData + // 先完成某兩步需要分行處理才能完成的格式整理。 + varLineData.regReplace(pattern: "^#.*$", replaceWith: "") // 以#開頭的行都淨空 + varLineData.regReplace(pattern: "^.*#WIN32.*$", replaceWith: "") // 去掉所有 WIN32 特有的行 + // 第三欄開始是注音 + let arrLineData = varLineData.components(separatedBy: " ") + var varLineDataProcessed: String = "" + var count = 0 + for currentCell in arrLineData { + count += 1 + if count < 3 { + varLineDataProcessed += currentCell + "\t" + } else if count < arrLineData.count { + varLineDataProcessed += currentCell + "-" + } else { + varLineDataProcessed += currentCell + } + } + // 然後直接乾脆就轉成 Entry 吧。 + let arrCells : [String] = varLineDataProcessed.components(separatedBy: "\t") + count = 0 // 不需要再定義,因為之前已經有定義過了。 + var phone = "" + var phrase = "" + var occurrence = 0 + for cell in arrCells { + count += 1 + switch count { + case 1: phrase = cell + case 3: phone = cell + case 2: occurrence = Int(cell) ?? 0 + default: break + } + } + if phrase != "" { // 廢掉空數據;之後無須再這樣處理。 + arrEntryRAW += [Entry.init(valPhone: phone, valPhrase: phrase, valWeight: 0.0, valCount: occurrence)] + } + } + NSLog(" - \(i18n): 成功生成詞語語料辭典(權重待計算)。") + return arrEntryRAW +} + +// MARK: - 載入單字檔案且輸出數組 + +func rawDictForKanjis(isCHS: Bool) -> [Entry] { + var arrEntryRAW: [Entry] = [] + var strRAW: String = "" + let i18n: String = isCHS ? "簡體中文" : "繁體中文" + // 讀取內容 + do { + strRAW += try String(contentsOfFile: urlKanjiCore, encoding: .utf8) + } + catch { + NSLog(" - Exception happened when reading raw core kanji data.") + return [] + } + // 預處理格式 + strRAW = strRAW.replacingOccurrences(of: " #MACOS", with: "") // 去掉 macOS 標記 + strRAW = strRAW.replacingOccurrences(of: " ", with: " ") // CJKWhiteSpace (\x{3000}) to ASCII Space + strRAW = strRAW.replacingOccurrences(of: " ", with: " ") // NonBreakWhiteSpace (\x{A0}) to ASCII Space + strRAW = strRAW.replacingOccurrences(of: "\t", with: " ") // Tab to ASCII Space + strRAW.regReplace(pattern: "\\f", replaceWith: "\n") // Form Feed to LF + strRAW = strRAW.replacingOccurrences(of: "\r", with: "\n") // CR to LF + strRAW.regReplace(pattern: " +", replaceWith: " ") // 統整連續空格為一個 ASCII 空格 + // strRAW.regReplace(pattern: "\\n+", replaceWith: "\n") // 統整連續 LF 為一個 LF + // (不需要處理純空行,因為空記錄不會被轉為 Entry) + strRAW = strRAW.replacingOccurrences(of: " \n", with: "\n") // 去除行尾空格 + strRAW = strRAW.replacingOccurrences(of: "\n ", with: "\n") // 去除行首空格 + if strRAW.prefix(1) == " " { // 去除檔案開頭空格 + strRAW.removeFirst() + } + if strRAW.suffix(1) == " " { // 去除檔案結尾空格 + strRAW.removeLast() + } + // 正式整理格式,現在就開始去重複: + let arrData = Array(NSOrderedSet(array: strRAW.components(separatedBy: "\n")).array as! [String]) + var varLineData: String = "" + for lineData in arrData { + varLineData = lineData + // 先完成某兩步需要分行處理才能完成的格式整理。 + varLineData.regReplace(pattern: "^#.*$", replaceWith: "") // 以#開頭的行都淨空 + varLineData.regReplace(pattern: "^.*#WIN32.*$", replaceWith: "") // 去掉所有 WIN32 特有的行 + // 簡體中文的話,提取 1,2,4;繁體中文的話,提取 1,3,4。 + let varLineDataPre = varLineData.components(separatedBy: " ").prefix(isCHS ? 2 : 1).joined(separator: "\t") + let varLineDataPost = varLineData.components(separatedBy: " ").suffix(isCHS ? 1 : 2).joined(separator: "\t") + varLineData = varLineDataPre + "\t" + varLineDataPost + let arrLineData = varLineData.components(separatedBy: " ") + var varLineDataProcessed: String = "" + var count = 0 + for currentCell in arrLineData { + count += 1 + if count < 3 { + varLineDataProcessed += currentCell + "\t" + } else if count < arrLineData.count { + varLineDataProcessed += currentCell + "-" + } else { + varLineDataProcessed += currentCell + } + } + // 然後直接乾脆就轉成 Entry 吧。 + let arrCells : [String] = varLineDataProcessed.components(separatedBy: "\t") + count = 0 // 不需要再定義,因為之前已經有定義過了。 + var phone = "" + var phrase = "" + var occurrence = 0 + for cell in arrCells { + count += 1 + switch count { + case 1: phrase = cell + case 3: phone = cell + case 2: occurrence = Int(cell) ?? 0 + default: break + } + } + if phrase != "" { // 廢掉空數據;之後無須再這樣處理。 + arrEntryRAW += [Entry.init(valPhone: phone, valPhrase: phrase, valWeight: 0.0, valCount: occurrence)] + } + } + NSLog(" - \(i18n): 成功生成單字語料辭典(權重待計算)。") + return arrEntryRAW +} + +// MARK: - 載入非漢字檔案且輸出數組 + +func rawDictForNonKanjis(isCHS: Bool) -> [Entry] { + var arrEntryRAW: [Entry] = [] + var strRAW: String = "" + let i18n: String = isCHS ? "簡體中文" : "繁體中文" + // 讀取內容 + do { + strRAW += try String(contentsOfFile: urlMiscBPMF, encoding: .utf8) + strRAW += "\n" + strRAW += try String(contentsOfFile: urlMiscNonKanji, encoding: .utf8) + } + catch { + NSLog(" - Exception happened when reading raw core kanji data.") + return [] + } + // 預處理格式 + strRAW = strRAW.replacingOccurrences(of: " #MACOS", with: "") // 去掉 macOS 標記 + strRAW = strRAW.replacingOccurrences(of: " ", with: " ") // CJKWhiteSpace (\x{3000}) to ASCII Space + strRAW = strRAW.replacingOccurrences(of: " ", with: " ") // NonBreakWhiteSpace (\x{A0}) to ASCII Space + strRAW = strRAW.replacingOccurrences(of: "\t", with: " ") // Tab to ASCII Space + strRAW.regReplace(pattern: "\\f", replaceWith: "\n") // Form Feed to LF + strRAW = strRAW.replacingOccurrences(of: "\r", with: "\n") // CR to LF + strRAW.regReplace(pattern: " +", replaceWith: " ") // 統整連續空格為一個 ASCII 空格 + // strRAW.regReplace(pattern: "\\n+", replaceWith: "\n") // 統整連續 LF 為一個 LF + // (不需要處理純空行,因為空記錄不會被轉為 Entry) + strRAW = strRAW.replacingOccurrences(of: " \n", with: "\n") // 去除行尾空格 + strRAW = strRAW.replacingOccurrences(of: "\n ", with: "\n") // 去除行首空格 + if strRAW.prefix(1) == " " { // 去除檔案開頭空格 + strRAW.removeFirst() + } + if strRAW.suffix(1) == " " { // 去除檔案結尾空格 + strRAW.removeLast() + } + // 正式整理格式,現在就開始去重複: + let arrData = Array(NSOrderedSet(array: strRAW.components(separatedBy: "\n")).array as! [String]) + var varLineData: String = "" + for lineData in arrData { + varLineData = lineData + // 先完成某兩步需要分行處理才能完成的格式整理。 + varLineData.regReplace(pattern: "^#.*$", replaceWith: "") // 以#開頭的行都淨空 + varLineData.regReplace(pattern: "^.*#WIN32.*$", replaceWith: "") // 去掉所有 WIN32 特有的行 + varLineData = varLineData.components(separatedBy: " ").prefix(3).joined(separator: "\t") // 提取前三欄的內容。 + let arrLineData = varLineData.components(separatedBy: " ") + var varLineDataProcessed: String = "" + var count = 0 + for currentCell in arrLineData { + count += 1 + if count < 3 { + varLineDataProcessed += currentCell + "\t" + } else if count < arrLineData.count { + varLineDataProcessed += currentCell + "-" + } else { + varLineDataProcessed += currentCell + } + } + // 然後直接乾脆就轉成 Entry 吧。 + let arrCells : [String] = varLineDataProcessed.components(separatedBy: "\t") + count = 0 // 不需要再定義,因為之前已經有定義過了。 + var phone = "" + var phrase = "" + var occurrence = 0 + for cell in arrCells { + count += 1 + switch count { + case 1: phrase = cell + case 3: phone = cell + case 2: occurrence = Int(cell) ?? 0 + default: break + } + } + if phrase != "" { // 廢掉空數據;之後無須再這樣處理。 + arrEntryRAW += [Entry.init(valPhone: phone, valPhrase: phrase, valWeight: 0.0, valCount: occurrence)] + } + } + NSLog(" - \(i18n): 成功生成非漢字語料辭典(權重待計算)。") + return arrEntryRAW +} + +func weightAndSort(_ arrStructUncalculated: [Entry], isCHS: Bool) -> [Entry] { + let i18n: String = isCHS ? "簡體中文" : "繁體中文" + var arrStructCalculated: [Entry] = [] + let fscale: Float = 2.7 + var norm: Float = 0.0 + for entry in arrStructUncalculated { + norm += fscale**(Float(entry.valPhrase.count) / 3.0 - 1.0) * Float(entry.valCount) // Credit: MJHsieh. + } + // norm 計算完畢,開始將 norm 作為新的固定常數來為每個詞條記錄計算權重。 + // 將新酷音的詞語出現次數數據轉換成小麥引擎可讀的數據形式。 + // 對出現次數小於 1 的詞條,將 0 當成 0.5 來處理、以防止除零。 + // 統計公式著作權歸 MJHsieh 所有(MIT License)。 + for entry in arrStructUncalculated { + let weight: Float = (entry.valCount < 1) ? + log10(fscale**(Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.5 / norm) // Credit: MJHsieh. + : + log10(fscale**(Float(entry.valPhrase.count) / 3.0 - 1.0) * Float(entry.valCount) / norm) // Credit: MJHsieh. + let weightRounded: Float = weight.rounded(toPlaces: 3) // 為了節省生成的檔案體積,僅保留小數點後三位。 + arrStructCalculated += [Entry.init(valPhone: entry.valPhone, valPhrase: entry.valPhrase, valWeight: weightRounded, valCount: entry.valCount)] + } + NSLog(" - \(i18n): 成功計算權重。") + // ========================================== + // 接下來是排序,先按照注音遞減排序一遍、再按照權重遞減排序一遍。 + let arrStructSorted: [Entry] = arrStructCalculated.sorted(by: {(lhs, rhs) -> Bool in return (lhs.valPhone, rhs.valCount) < (rhs.valPhone, lhs.valCount)}) + NSLog(" - \(i18n): 排序整理完畢,準備編譯要寫入的檔案內容。") + return arrStructSorted +} + +func fileOutput(isCHS: Bool) { + let i18n: String = isCHS ? "簡體中文" : "繁體中文" + let pathOutput = urlCurrentFolder.appendingPathComponent(isCHS ? urlOutputCHS : urlOutputCHT) + var strPrintLine = "" + // 讀取標點內容 + do { + strPrintLine += try String(contentsOfFile: urlPunctuation, encoding: .utf8) + } + catch { + NSLog(" - \(i18n): Exception happened when reading raw punctuation data.") + } + NSLog(" - \(i18n): 成功插入標點符號與西文字母數據。") + // 統合辭典內容 + var arrStructUnified: [Entry] = [] + arrStructUnified += rawDictForKanjis(isCHS: isCHS) + arrStructUnified += rawDictForNonKanjis(isCHS: isCHS) + arrStructUnified += rawDictForPhrases(isCHS: isCHS) + // 計算權重且排序 + arrStructUnified = weightAndSort(arrStructUnified, isCHS: isCHS) + + for entry in arrStructUnified { + strPrintLine += entry.valPhone + " " + entry.valPhrase + " " + String(entry.valWeight) + "\n" + } + NSLog(" - \(i18n): 要寫入檔案的內容編譯完畢。") + do { + try strPrintLine.write(to: pathOutput, atomically: false, encoding: .utf8) + } + catch { + NSLog(" - \(i18n): Error on writing strings to file: \(error)") + } + NSLog(" - \(i18n): 寫入完成。") +} + +// MARK: - 主执行绪 +func main() { + NSLog("// 準備編譯繁體中文核心語料檔案。") + fileOutput(isCHS: false) + NSLog("// 準備編譯簡體中文核心語料檔案。") + fileOutput(isCHS: true) +} + +main() From d3576fc8853d022bea02361fb0cc23733a312f79 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 17:00:47 +0800 Subject: [PATCH 17/24] Submodule // Implementing Swift-based data compiler. - Also with tweaked data structure for the current macOS build of vChewing. - Add certain common currency support (as punctuations) outside of the symbol menu. --- Source/Data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Data b/Source/Data index e4238c51..4d01ae8b 160000 --- a/Source/Data +++ b/Source/Data @@ -1 +1 @@ -Subproject commit e4238c5193173d82397a5dd96c91b6e50c7641b0 +Subproject commit 4d01ae8b9bd650c4f501b3ef4f5294b7e217ef9a From 8fe16957d9f8402e79dd2d192ab152c9336eb3d5 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 25 Feb 2022 20:59:55 +0800 Subject: [PATCH 18/24] CNSLM // Instantiation with -11.0 value. --- .../SubLanguageModels/CNSLM.mm | 150 ------------------ .../{ => InstantiatedModels}/CNSLM.h | 32 +--- .../SubLanguageModels/UserPhrasesLM.h | 10 +- .../SubLanguageModels/UserPhrasesLM.mm | 8 +- vChewing.xcodeproj/project.pbxproj | 14 +- 5 files changed, 31 insertions(+), 183 deletions(-) delete mode 100644 Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.mm rename Source/Modules/LangModelRelated/SubLanguageModels/{ => InstantiatedModels}/CNSLM.h (67%) diff --git a/Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.mm b/Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.mm deleted file mode 100644 index 6c4ddcad..00000000 --- a/Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.mm +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are (c) 2021 and onwards The vChewing Project (MIT-NTL License). -/* -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and -to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -2. 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 above. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#include "CNSLM.h" - -#include -#include -#include -#include -#include -#include - -#include "KeyValueBlobReader.h" - -namespace vChewing { - -CNSLM::CNSLM() - : fd(-1) - , data(0) - , length(0) -{ -} - -CNSLM::~CNSLM() -{ - if (data) { - close(); - } -} - -bool CNSLM::isLoaded() -{ - if (data) { - return true; - } - return false; -} - -bool CNSLM::open(const char *path) -{ - if (data) { - syslog(LOG_CONS, "CNSLM: Failed at Open Step 1.\n"); - return false; - } - - fd = ::open(path, O_RDONLY); - if (fd == -1) { - syslog(LOG_CONS, "CNSLM: Failed at Open Step 2.\n"); - printf("open:: file not exist"); - return false; - } - - struct stat sb; - if (fstat(fd, &sb) == -1) { - syslog(LOG_CONS, "CNSLM: Failed at Open Step 3.\n"); - printf("open:: cannot open file"); - return false; - } - - length = (size_t)sb.st_size; - - data = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0); - if (!data) { - ::close(fd); - syslog(LOG_CONS, "CNSLM: Failed at Open Step 4.\n"); - return false; - } - - KeyValueBlobReader reader(static_cast(data), length); - KeyValueBlobReader::KeyValue keyValue; - KeyValueBlobReader::State state; - while ((state = reader.Next(&keyValue)) == KeyValueBlobReader::State::HAS_PAIR) { - // We invert the key and value, since in user phrases, "key" is the phrase value, and "value" is the BPMF reading. - keyRowMap[keyValue.value].emplace_back(keyValue.value, keyValue.key); - } - // 下面這一段或許可以做成開關、來詢問是否對使用者語彙採取寬鬆策略(哪怕有行內容寫錯也會放行) - if (state == KeyValueBlobReader::State::ERROR) { - // close(); - syslog(LOG_CONS, "CNSLM: Failed at Open Step 5. On Error Resume Next.\n"); - // return false; - } - return true; -} - -void CNSLM::close() -{ - if (data) { - munmap(data, length); - ::close(fd); - data = 0; - } - - keyRowMap.clear(); -} - -void CNSLM::dump() -{ - for (const auto& entry : keyRowMap) { - const std::vector& rows = entry.second; - for (const auto& row : rows) { - std::cerr << row.key << " " << row.value << "\n"; - } - } -} - -const std::vector CNSLM::bigramsForKeys(const std::string& preceedingKey, const std::string& key) -{ - return std::vector(); -} - -const std::vector CNSLM::unigramsForKey(const std::string& key) -{ - std::vector v; - auto iter = keyRowMap.find(key); - if (iter != keyRowMap.end()) { - const std::vector& rows = iter->second; - for (const auto& row : rows) { - Taiyan::Gramambular::Unigram g; - g.keyValue.key = row.key; - g.keyValue.value = row.value; - g.score = -17.0; - v.push_back(g); - } - } - - return v; -} - -bool CNSLM::hasUnigramsForKey(const std::string& key) -{ - return keyRowMap.find(key) != keyRowMap.end(); -} - -}; // namespace vChewing diff --git a/Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.h b/Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/CNSLM.h similarity index 67% rename from Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.h rename to Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/CNSLM.h index d15bc734..80c47b96 100644 --- a/Source/Modules/LangModelRelated/SubLanguageModels/CNSLM.h +++ b/Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/CNSLM.h @@ -24,35 +24,19 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH #include #include #include "LanguageModel.h" +#include "UserPhrasesLM.h" namespace vChewing { -class CNSLM : public Taiyan::Gramambular::LanguageModel +class CNSLM: public UserPhrasesLM { public: - CNSLM(); - ~CNSLM(); - - bool isLoaded(); - bool open(const char *path); - void close(); - void dump(); - - virtual const std::vector bigramsForKeys(const std::string& preceedingKey, const std::string& key); - virtual const std::vector unigramsForKey(const std::string& key); - virtual bool hasUnigramsForKey(const std::string& key); - -protected: - struct Row { - Row(std::string_view& k, std::string_view& v) : key(k), value(v) {} - std::string_view key; - std::string_view value; - }; - - std::map> keyRowMap; - int fd; - void *data; - size_t length; + virtual bool allowConsolidation() override { + return false; + } + virtual float overridedValue() override { + return -11.0; + } }; } diff --git a/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.h b/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.h index 6d0f30d6..33d57c61 100644 --- a/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.h +++ b/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.h @@ -37,7 +37,15 @@ public: bool open(const char *path); void close(); void dump(); - + + virtual bool allowConsolidation() { + return true; + } + + virtual float overridedValue() { + return 0.0; + } + virtual const std::vector bigramsForKeys(const std::string& preceedingKey, const std::string& key); virtual const std::vector unigramsForKey(const std::string& key); virtual bool hasUnigramsForKey(const std::string& key); diff --git a/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.mm b/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.mm index cd82d11c..6ae55429 100644 --- a/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.mm +++ b/Source/Modules/LangModelRelated/SubLanguageModels/UserPhrasesLM.mm @@ -59,8 +59,10 @@ bool UserPhrasesLM::open(const char *path) return false; } - LMConsolidator::FixEOF(path); - LMConsolidator::ConsolidateContent(path, true); + if (allowConsolidation()) { + LMConsolidator::FixEOF(path); + LMConsolidator::ConsolidateContent(path, true); + } fd = ::open(path, O_RDONLY); if (fd == -1) { @@ -134,7 +136,7 @@ const std::vector UserPhrasesLM::unigramsForKey(co Taiyan::Gramambular::Unigram g; g.keyValue.key = row.key; g.keyValue.value = row.value; - g.score = 0.0; + g.score = overridedValue(); v.push_back(g); } } diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index fdbd60be..41a88e28 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -18,7 +18,6 @@ 5B62A31B27AE73A700A19448 /* SSZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A31327AE73A700A19448 /* SSZipArchive.m */; }; 5B62A31C27AE73A700A19448 /* AWFileHash.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A31627AE73A700A19448 /* AWFileHash.m */; }; 5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */; }; - 5B62A32E27AE78B000A19448 /* CNSLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32A27AE78B000A19448 /* CNSLM.mm */; }; 5B62A32F27AE78B000A19448 /* CoreLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32D27AE78B000A19448 /* CoreLM.mm */; }; 5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33127AE792F00A19448 /* InputSourceHelper.swift */; }; 5B62A33627AE795800A19448 /* PreferencesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33527AE795800A19448 /* PreferencesModule.swift */; }; @@ -191,7 +190,6 @@ 5B62A32627AE77BB00A19448 /* LMConsolidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LMConsolidator.h; sourceTree = ""; }; 5B62A32727AE77BB00A19448 /* LMConsolidator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LMConsolidator.mm; sourceTree = ""; }; 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FSEventStreamHelper.swift; sourceTree = ""; }; - 5B62A32A27AE78B000A19448 /* CNSLM.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CNSLM.mm; sourceTree = ""; }; 5B62A32B27AE78B000A19448 /* CNSLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNSLM.h; sourceTree = ""; }; 5B62A32C27AE78B000A19448 /* CoreLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CoreLM.h; sourceTree = ""; }; 5B62A32D27AE78B000A19448 /* CoreLM.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = CoreLM.mm; sourceTree = ""; }; @@ -364,6 +362,14 @@ name = MiscRootFiles; sourceTree = ""; }; + 5B4D47B627C9186900220DDC /* InstantiatedModels */ = { + isa = PBXGroup; + children = ( + 5B62A32B27AE78B000A19448 /* CNSLM.h */, + ); + path = InstantiatedModels; + sourceTree = ""; + }; 5B62A30127AE732800A19448 /* 3rdParty */ = { isa = PBXGroup; children = ( @@ -495,8 +501,7 @@ 5B62A32527AE758000A19448 /* SubLanguageModels */ = { isa = PBXGroup; children = ( - 5B62A32B27AE78B000A19448 /* CNSLM.h */, - 5B62A32A27AE78B000A19448 /* CNSLM.mm */, + 5B4D47B627C9186900220DDC /* InstantiatedModels */, 5B62A32C27AE78B000A19448 /* CoreLM.h */, 5B62A32D27AE78B000A19448 /* CoreLM.mm */, D41355DC278EA3ED005E5CBD /* UserPhrasesLM.mm */, @@ -1054,7 +1059,6 @@ 5B62A34A27AE7CD900A19448 /* NotifierController.swift in Sources */, 5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */, 5B62A31827AE73A700A19448 /* zip.m in Sources */, - 5B62A32E27AE78B000A19448 /* CNSLM.mm in Sources */, D41355DB278E6D17005E5CBD /* LMInstantiator.mm in Sources */, 5B62A31A27AE73A700A19448 /* mztools.m in Sources */, 5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */, From 81f5e0dec108af9021798efde8c04007928f6a9b Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 25 Feb 2022 23:05:12 +0800 Subject: [PATCH 19/24] LM // Add SymbolLM, plus Re-Enable CoreLM. --- .../Modules/LangModelRelated/LMInstantiator.h | 16 +++++++ .../LangModelRelated/LMInstantiator.mm | 41 ++++++++++++++++ .../InstantiatedModels/SymbolLM.h | 44 +++++++++++++++++ .../Modules/LangModelRelated/mgrLangModel.h | 2 +- .../Modules/LangModelRelated/mgrLangModel.mm | 47 ++++++++++++++----- vChewing.xcodeproj/project.pbxproj | 10 ++++ 6 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/SymbolLM.h diff --git a/Source/Modules/LangModelRelated/LMInstantiator.h b/Source/Modules/LangModelRelated/LMInstantiator.h index d4f49eb9..594cbe23 100644 --- a/Source/Modules/LangModelRelated/LMInstantiator.h +++ b/Source/Modules/LangModelRelated/LMInstantiator.h @@ -21,9 +21,11 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH #define LMInstantiator_H #include "AssociatedPhrases.h" +#include "CoreLM.h" #include "CNSLM.h" #include "ParselessLM.h" #include "PhraseReplacementMap.h" +#include "SymbolLM.h" #include "UserPhrasesLM.h" #include #include @@ -65,6 +67,18 @@ public: /// If the data model is already loaded. bool isDataModelLoaded(); + /// Asks to load the primary language model at the given path. + /// @param miscDataPath The path of the misc data model. + void loadMiscData(const char* miscDataPath); + /// If the data model is already loaded. + bool isMiscDataLoaded(); + + /// Asks to load the primary language model at the given path. + /// @param symbolDataPath The path of the symbol data model. + void loadSymbolData(const char* symbolDataPath); + /// If the data model is already loaded. + bool isSymbolDataLoaded(); + /// Asks to load the primary language model at the given path. /// @param cnsDataPath The path of the CNS data model. void loadCNSData(const char* cnsDataPath); @@ -126,6 +140,8 @@ protected: std::unordered_set& insertedValues); ParselessLM m_languageModel; + CoreLM m_miscModel; + SymbolLM m_symbolModel; CNSLM m_cnsModel; UserPhrasesLM m_userPhrases; UserPhrasesLM m_excludedPhrases; diff --git a/Source/Modules/LangModelRelated/LMInstantiator.mm b/Source/Modules/LangModelRelated/LMInstantiator.mm index 6f61e65c..4fe8d376 100644 --- a/Source/Modules/LangModelRelated/LMInstantiator.mm +++ b/Source/Modules/LangModelRelated/LMInstantiator.mm @@ -30,6 +30,7 @@ LMInstantiator::LMInstantiator() LMInstantiator::~LMInstantiator() { m_languageModel.close(); + m_miscModel.close(); m_userPhrases.close(); m_cnsModel.close(); m_excludedPhrases.close(); @@ -63,6 +64,32 @@ bool LMInstantiator::isCNSDataLoaded() return m_cnsModel.isLoaded(); } +void LMInstantiator::loadMiscData(const char* miscDataPath) +{ + if (miscDataPath) { + m_miscModel.close(); + m_miscModel.open(miscDataPath); + } +} + +bool LMInstantiator::isMiscDataLoaded() +{ + return m_miscModel.isLoaded(); +} + +void LMInstantiator::loadSymbolData(const char* symbolDataPath) +{ + if (symbolDataPath) { + m_symbolModel.close(); + m_symbolModel.open(symbolDataPath); + } +} + +bool LMInstantiator::isSymbolDataLoaded() +{ + return m_symbolModel.isLoaded(); +} + void LMInstantiator::loadUserPhrases(const char* userPhrasesDataPath, const char* excludedPhrasesDataPath) { @@ -110,6 +137,8 @@ const std::vector LMInstantiator::unigramsForKey(c } std::vector allUnigrams; + std::vector miscUnigrams; + std::vector symbolUnigrams; std::vector userUnigrams; std::vector cnsUnigrams; @@ -136,6 +165,16 @@ const std::vector LMInstantiator::unigramsForKey(c allUnigrams = filterAndTransformUnigrams(rawGlobalUnigrams, excludedValues, insertedValues); } + if (m_miscModel.hasUnigramsForKey(key)) { + std::vector rawMiscUnigrams = m_miscModel.unigramsForKey(key); + miscUnigrams = filterAndTransformUnigrams(rawMiscUnigrams, excludedValues, insertedValues); + } + + if (m_symbolModel.hasUnigramsForKey(key)) { + std::vector rawSymbolUnigrams = m_symbolModel.unigramsForKey(key); + symbolUnigrams = filterAndTransformUnigrams(rawSymbolUnigrams, excludedValues, insertedValues); + } + if (m_cnsModel.hasUnigramsForKey(key) && m_cnsEnabled) { std::vector rawCNSUnigrams = m_cnsModel.unigramsForKey(key); cnsUnigrams = filterAndTransformUnigrams(rawCNSUnigrams, excludedValues, insertedValues); @@ -143,6 +182,8 @@ const std::vector LMInstantiator::unigramsForKey(c allUnigrams.insert(allUnigrams.begin(), userUnigrams.begin(), userUnigrams.end()); allUnigrams.insert(allUnigrams.end(), cnsUnigrams.begin(), cnsUnigrams.end()); + allUnigrams.insert(allUnigrams.begin(), miscUnigrams.begin(), miscUnigrams.end()); + allUnigrams.insert(allUnigrams.end(), symbolUnigrams.begin(), symbolUnigrams.end()); return allUnigrams; } diff --git a/Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/SymbolLM.h b/Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/SymbolLM.h new file mode 100644 index 00000000..e2402f91 --- /dev/null +++ b/Source/Modules/LangModelRelated/SubLanguageModels/InstantiatedModels/SymbolLM.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). +// All possible vChewing-specific modifications are (c) 2021 and onwards The vChewing Project (MIT-NTL License). +/* +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and +to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +2. 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 above. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef SYMBOLLM_H +#define SYMBOLLM_H + +#include +#include +#include +#include "LanguageModel.h" +#include "UserPhrasesLM.h" + +namespace vChewing { + +class SymbolLM: public UserPhrasesLM +{ +public: + virtual bool allowConsolidation() override { + return false; + } + virtual float overridedValue() override { + return -12.0; + } +}; + +} + +#endif diff --git a/Source/Modules/LangModelRelated/mgrLangModel.h b/Source/Modules/LangModelRelated/mgrLangModel.h index 0aa14424..e003fd70 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.h +++ b/Source/Modules/LangModelRelated/mgrLangModel.h @@ -36,13 +36,13 @@ NS_ASSUME_NONNULL_BEGIN + (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating; + (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled; + (void)setCNSEnabled:(BOOL)cnsEnabled; ++ (NSString *)specifyBundleDataPath:(NSString *)filename; + (NSString *)userPhrasesDataPath:(InputMode)mode; + (NSString *)userAssociatedPhrasesDataPath:(InputMode)mode; + (NSString *)excludedPhrasesDataPath:(InputMode)mode; + (NSString *)phraseReplacementDataPath:(InputMode)mode; @property (class, readonly, nonatomic) NSString *dataFolderPath; -@property (class, readonly, nonatomic) NSString *cnsDataPath; @end diff --git a/Source/Modules/LangModelRelated/mgrLangModel.mm b/Source/Modules/LangModelRelated/mgrLangModel.mm index c6f830f6..9c696d6c 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.mm +++ b/Source/Modules/LangModelRelated/mgrLangModel.mm @@ -45,19 +45,38 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing lm.loadLanguageModel([dataPath UTF8String]); } ++ (NSString *)specifyBundleDataPath:(NSString *)filenameWithoutExtension; +{ + Class cls = NSClassFromString(@"ctlInputMethod"); + return [[NSBundle bundleForClass:cls] pathForResource:filenameWithoutExtension ofType:@"txt"]; +} + + (void)loadDataModels { if (!gLangModelCHT.isDataModelLoaded()) { LTLoadLanguageModelFile(@"data-cht", gLangModelCHT); } - if (!gLangModelCHT.isCNSDataLoaded()){ - gLangModelCHT.loadCNSData([[self cnsDataPath] UTF8String]); + if (!gLangModelCHT.isMiscDataLoaded()) { + gLangModelCHT.loadMiscData([[self specifyBundleDataPath: @"data-zhuyinwen"] UTF8String]); } + if (!gLangModelCHT.isSymbolDataLoaded()){ + gLangModelCHT.loadSymbolData([[self specifyBundleDataPath: @"data-symbols"] UTF8String]); + } + if (!gLangModelCHT.isCNSDataLoaded()){ + gLangModelCHT.loadCNSData([[self specifyBundleDataPath: @"char-kanji-cns"] UTF8String]); + } + // ----------------- if (!gLangModelCHS.isDataModelLoaded()) { LTLoadLanguageModelFile(@"data-chs", gLangModelCHS); } + if (!gLangModelCHS.isMiscDataLoaded()) { + gLangModelCHS.loadMiscData([[self specifyBundleDataPath: @"data-zhuyinwen"] UTF8String]); + } + if (!gLangModelCHS.isSymbolDataLoaded()){ + gLangModelCHS.loadSymbolData([[self specifyBundleDataPath: @"data-symbols"] UTF8String]); + } if (!gLangModelCHS.isCNSDataLoaded()){ - gLangModelCHS.loadCNSData([[self cnsDataPath] UTF8String]); + gLangModelCHS.loadCNSData([[self specifyBundleDataPath: @"char-kanji-cns"] UTF8String]); } } @@ -67,8 +86,14 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing if (!gLangModelCHT.isDataModelLoaded()) { LTLoadLanguageModelFile(@"data-cht", gLangModelCHT); } + if (!gLangModelCHT.isMiscDataLoaded()) { + gLangModelCHT.loadMiscData([[self specifyBundleDataPath: @"data-zhuyinwen"] UTF8String]); + } + if (!gLangModelCHT.isSymbolDataLoaded()){ + gLangModelCHT.loadSymbolData([[self specifyBundleDataPath: @"data-symbols"] UTF8String]); + } if (!gLangModelCHT.isCNSDataLoaded()){ - gLangModelCHT.loadCNSData([[self cnsDataPath] UTF8String]); + gLangModelCHT.loadCNSData([[self specifyBundleDataPath: @"char-kanji-cns"] UTF8String]); } } @@ -76,8 +101,14 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing if (!gLangModelCHS.isDataModelLoaded()) { LTLoadLanguageModelFile(@"data-chs", gLangModelCHS); } + if (!gLangModelCHS.isMiscDataLoaded()) { + gLangModelCHS.loadMiscData([[self specifyBundleDataPath: @"data-zhuyinwen"] UTF8String]); + } + if (!gLangModelCHS.isSymbolDataLoaded()){ + gLangModelCHS.loadSymbolData([[self specifyBundleDataPath: @"data-symbols"] UTF8String]); + } if (!gLangModelCHS.isCNSDataLoaded()){ - gLangModelCHS.loadCNSData([[self cnsDataPath] UTF8String]); + gLangModelCHS.loadCNSData([[self specifyBundleDataPath: @"char-kanji-cns"] UTF8String]); } } } @@ -308,12 +339,6 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing return [[self dataFolderPath] stringByAppendingPathComponent:fileName]; } -+ (NSString *)cnsDataPath -{ - Class cls = NSClassFromString(@"ctlInputMethod"); - return [[NSBundle bundleForClass:cls] pathForResource:@"char-kanji-cns" ofType:@"txt"]; -} - + (vChewing::LMInstantiator *)lmCHT { return &gLangModelCHT; diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 41a88e28..b28153e9 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; }; 5B2DB16F27AF6891006D874E /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16D27AF6891006D874E /* data-chs.txt */; }; 5B2DB17027AF6891006D874E /* data-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16E27AF6891006D874E /* data-cht.txt */; }; + 5B4D47C127C9304000220DDC /* data-zhuyinwen.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B4D47BD27C9304000220DDC /* data-zhuyinwen.txt */; }; + 5B4D47C227C9304000220DDC /* data-symbols.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B4D47BE27C9304000220DDC /* data-symbols.txt */; }; 5B62A31727AE73A700A19448 /* unzip.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30927AE73A700A19448 /* unzip.m */; }; 5B62A31827AE73A700A19448 /* zip.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30A27AE73A700A19448 /* zip.m */; }; 5B62A31927AE73A700A19448 /* ioapi.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30B27AE73A700A19448 /* ioapi.m */; }; @@ -174,6 +176,8 @@ 5B2DB16E27AF6891006D874E /* data-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "data-cht.txt"; path = "Data/data-cht.txt"; sourceTree = ""; }; 5B2DB17127AF8771006D874E /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = Data/Makefile; sourceTree = ""; }; 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = vChewingKeyLayout.bundle; sourceTree = ""; }; + 5B4D47BD27C9304000220DDC /* data-zhuyinwen.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "data-zhuyinwen.txt"; path = "../../libvchewing-data/components/common/data-zhuyinwen.txt"; sourceTree = ""; }; + 5B4D47BE27C9304000220DDC /* data-symbols.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "data-symbols.txt"; path = "../../libvchewing-data/components/common/data-symbols.txt"; sourceTree = ""; }; 5B62A30927AE73A700A19448 /* unzip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = unzip.m; sourceTree = ""; }; 5B62A30A27AE73A700A19448 /* zip.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = zip.m; sourceTree = ""; }; 5B62A30B27AE73A700A19448 /* ioapi.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ioapi.m; sourceTree = ""; }; @@ -206,6 +210,7 @@ 5B73FB5F27B2BE1300E9BF49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Source/WindowNIBs/Base.lproj/frmPrefWindow.xib; sourceTree = ""; }; 5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Source/WindowNIBs/en.lproj/frmPrefWindow.strings; sourceTree = ""; }; + 5B8F43ED27C9BC220069AC27 /* SymbolLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolLM.h; sourceTree = ""; }; 5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = ""; }; 5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = ""; }; 5BBBB76627AED5DB0023B93A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmNonModalAlertWindow.xib; sourceTree = ""; }; @@ -365,6 +370,7 @@ 5B4D47B627C9186900220DDC /* InstantiatedModels */ = { isa = PBXGroup; children = ( + 5B8F43ED27C9BC220069AC27 /* SymbolLM.h */, 5B62A32B27AE78B000A19448 /* CNSLM.h */, ); path = InstantiatedModels; @@ -596,6 +602,8 @@ 5BD05B8027B22F3C004C4F1D /* char-kanji-cns.txt */, 5B2DB16D27AF6891006D874E /* data-chs.txt */, 5B2DB16E27AF6891006D874E /* data-cht.txt */, + 5B4D47BE27C9304000220DDC /* data-symbols.txt */, + 5B4D47BD27C9304000220DDC /* data-zhuyinwen.txt */, 5B2DB17127AF8771006D874E /* Makefile */, ); name = Data; @@ -962,6 +970,7 @@ D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */, 5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */, 5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */, + 5B4D47C227C9304000220DDC /* data-symbols.txt in Resources */, 6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */, D4E33D8F27A838F0006DB1CF /* InfoPlist.strings in Resources */, 5BBBB76B27AED5DB0023B93A /* frmNonModalAlertWindow.xib in Resources */, @@ -969,6 +978,7 @@ 5BBBB77527AED70B0023B93A /* MenuIcon-SCVIM.png in Resources */, 5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */, 5BD05B8127B22F3C004C4F1D /* char-kanji-cns.txt in Resources */, + 5B4D47C127C9304000220DDC /* data-zhuyinwen.txt in Resources */, 5B2DB17027AF6891006D874E /* data-cht.txt in Resources */, 5BBBB77327AED70B0023B93A /* MenuIcon-TCVIM@2x.png in Resources */, 5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */, From 3e9725cafbcafc67e60c78c607d14c2f65bebf7d Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 26 Feb 2022 13:46:37 +0800 Subject: [PATCH 20/24] Zonble: KeyHandler // Don't let UOM remember symbols. - This feature is okay to be enabled since we have introduced SymbolLM. Co-Authored-By: Weizhong Yang a.k.a zonble --- Source/Modules/ControllerModules/KeyHandler.mm | 12 +++++++++++- .../Modules/LanguageParsers/Gramambular/Node.h | 18 +++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler.mm b/Source/Modules/ControllerModules/KeyHandler.mm index 82770558..78e760e8 100644 --- a/Source/Modules/ControllerModules/KeyHandler.mm +++ b/Source/Modules/ControllerModules/KeyHandler.mm @@ -208,7 +208,17 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot"; // If the length of the readings and the characters do not match, // it often means it is a special symbol and it should not be stored // in the user override model. - if (selectedNode.spanningLength == [value count]) { + BOOL addToOverrideModel = YES; + if (selectedNode.spanningLength != [value count]) { + addToOverrideModel = NO; + } + if (addToOverrideModel) { + double score = selectedNode.node->scoreForCandidate(stringValue); + if (score <= -12) { // 威注音的 SymbolLM 的 Score 是 -12。 + addToOverrideModel = NO; + } + } + if (addToOverrideModel) { _userOverrideModel->observe(_walkedNodes, cursorIndex, stringValue, [[NSDate date] timeIntervalSince1970]); } } diff --git a/Source/Modules/LanguageParsers/Gramambular/Node.h b/Source/Modules/LanguageParsers/Gramambular/Node.h index ff1d3fd2..dfc961c5 100644 --- a/Source/Modules/LanguageParsers/Gramambular/Node.h +++ b/Source/Modules/LanguageParsers/Gramambular/Node.h @@ -184,15 +184,15 @@ inline const std::string& Node::key() const { return m_key; } inline double Node::score() const { return m_score; } -// Prevents the override model to remember symbols with scode -X or lower. -//inline double Node::scoreForCandidate(const std::string& candidate) const { -// for (auto unigram : m_unigrams) { -// if (unigram.keyValue.value == candidate) { -// return unigram.score; -// } -// } -// return 0.0; -//} + +inline double Node::scoreForCandidate(const std::string& candidate) const { + for (auto unigram : m_unigrams) { + if (unigram.keyValue.value == candidate) { + return unigram.score; + } + } + return 0.0; +} inline double Node::highestUnigramScore() const { if (m_unigrams.empty()) { From 88edff7d4b9bc075ec96b60503fee5299b489b66 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 26 Feb 2022 14:18:59 +0800 Subject: [PATCH 21/24] README // State the availability of terminal compilation. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4110afc0..63f7e633 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ 接下来就是直接开 Xcode 专案,Product -> Scheme 选「vChewingInstaller」,编译即可。 -> 之前说「在成功之后执行 `make` 即可组建、再执行 `make install` 可以触发威注音的安装程式」。但最近威注音在换用 ParselessLM 之后、用这种方式建置出来的话,会出现无论如何也敲不了汉字的问题。所以该方法不再是推荐的编译方法。 +> 之前说「在成功之后执行 `make` 即可组建、再执行 `make install` 可以触发威注音的安装程式」,这对新版威注音而言**当且仅当**使用纯 Swift 编译脚本工序时才可以使用。目前的 libvchewing-data 模组已经针对 macOS 版威注音实装了纯 Swift 词库编译脚本。 第一次安装完,日后程式码或词库有任何修改,只要重复上述流程,再次安装威注音即可。 From 6a2bf70ab92d3a457cb380b481663c28f2690941 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 26 Feb 2022 14:36:11 +0800 Subject: [PATCH 22/24] Repo // Updating Credits. --- Installer/Resources/Base.lproj/MainMenu.xib | 6 +++--- Installer/Resources/en.lproj/MainMenu.strings | 4 ++-- Installer/Resources/ja.lproj/MainMenu.strings | 4 ++-- Installer/Resources/zh-Hans.lproj/MainMenu.strings | 4 ++-- Installer/Resources/zh-Hant.lproj/MainMenu.strings | 4 ++-- LICENSE-CHS.txt | 2 +- LICENSE-CHT.txt | 2 +- LICENSE-JPN.txt | 2 +- LICENSE.txt | 2 +- Source/WindowNIBs/Base.lproj/frmAboutWindow.xib | 2 +- Source/WindowNIBs/en.lproj/frmAboutWindow.strings | 4 ++-- Source/WindowNIBs/ja.lproj/frmAboutWindow.strings | 4 ++-- Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings | 4 ++-- Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings | 4 ++-- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Installer/Resources/Base.lproj/MainMenu.xib b/Installer/Resources/Base.lproj/MainMenu.xib index 18ad828f..b0282031 100644 --- a/Installer/Resources/Base.lproj/MainMenu.xib +++ b/Installer/Resources/Base.lproj/MainMenu.xib @@ -67,7 +67,7 @@ - + @@ -154,7 +154,7 @@ McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development Reinforced by Hiraku Wang.
vChewing Phrase Database Maintained by Shiki Suen. +vChewing macOS Development: Shiki Suen, Hiraku Wang, etc.
vChewing Phrase Database Maintained by Shiki Suen. @@ -282,7 +282,7 @@ Gw - + diff --git a/Installer/Resources/en.lproj/MainMenu.strings b/Installer/Resources/en.lproj/MainMenu.strings index 384087ac..c94af990 100644 --- a/Installer/Resources/en.lproj/MainMenu.strings +++ b/Installer/Resources/en.lproj/MainMenu.strings @@ -56,8 +56,8 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "Derived from OpenVanilla McBopopmofo Project."; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ +"VW8-s5-Wpn.title" = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ // "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/Installer/Resources/ja.lproj/MainMenu.strings b/Installer/Resources/ja.lproj/MainMenu.strings index 3c49deb2..8f0c7545 100644 --- a/Installer/Resources/ja.lproj/MainMenu.strings +++ b/Installer/Resources/ja.lproj/MainMenu.strings @@ -56,8 +56,8 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "OpenVanilla 小麦注音プロジェクトから派生。"; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "小麦注音入力エンジン開発:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, など。\nmacOS 版の開発協力:Hiraku Wang。\n威注音語彙データの維持:Shiki Suen。"; +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ +"VW8-s5-Wpn.title" = "小麦注音入力エンジン開発:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, など。\nmacOS 版の開発:Shiki Suen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。"; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/Installer/Resources/zh-Hans.lproj/MainMenu.strings b/Installer/Resources/zh-Hans.lproj/MainMenu.strings index 1f52fb43..bbee8893 100644 --- a/Installer/Resources/zh-Hans.lproj/MainMenu.strings +++ b/Installer/Resources/zh-Hans.lproj/MainMenu.strings @@ -56,9 +56,9 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "该专案由 OpenVanilla 小麦注音专案衍生而来。"; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang. +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "小麦注音引擎研发:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研发协力:Hiraku Wang。\n威注音词库维护:Shiki Suen。"; +"VW8-s5-Wpn.title" = "小麦注音引擎研发:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研发:Shiki Suen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。"; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ // "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/Installer/Resources/zh-Hant.lproj/MainMenu.strings b/Installer/Resources/zh-Hant.lproj/MainMenu.strings index 86d7dcd9..7e11c4a0 100644 --- a/Installer/Resources/zh-Hant.lproj/MainMenu.strings +++ b/Installer/Resources/zh-Hant.lproj/MainMenu.strings @@ -56,9 +56,9 @@ /* Class = "NSTextFieldCell"; title = "Derived from OpenVanilla McBopopmofo Project."; ObjectID = "QYf-Nf-hoi"; */ "QYf-Nf-hoi.title" = "該專案由 OpenVanilla 小麥注音專案衍生而來。"; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang. +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "VW8-s5-Wpn"; */ -"VW8-s5-Wpn.title" = "小麥注音引擎研發:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研發協力:Hiraku Wang。\n威注音詞庫維護:Shiki Suen。"; +"VW8-s5-Wpn.title" = "小麥注音引擎研發:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研發:Shiki Suen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。"; /* Class = "NSTextFieldCell"; title = "Placeholder for showing copyright information."; ObjectID = "eo3-TK-0rB"; */ // "eo3-TK-0rB.title" = "Placeholder for showing copyright information."; diff --git a/LICENSE-CHS.txt b/LICENSE-CHS.txt index 1395021c..2c8380e6 100644 --- a/LICENSE-CHS.txt +++ b/LICENSE-CHS.txt @@ -2,7 +2,7 @@ vChewing macOS: MIT-NTL License 麻理(去商标)授权合约 © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. 小麦注音引擎研发:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。 -威注音 macOS 程式研发协力:Hiraku Wang。 +威注音 macOS 程式研发:Shiki Suen, Hiraku Wang, 等。 威注音词库维护:Shiki Suen。 软件之著作权利人依此麻理授权条款,将其对于软件之著作权利授权释出,只须使用者践履以下二项麻理授权条款叙明之义务性规定,其即享有对此软件程式及其相关说明文档自由不受限制地进行利用之权利,范围包括「使用、重制、修改、合并、出版、散布、再授权、及贩售程式重制作品」等诸多方面之应用,而散布程式之人、更可将上述权利传递予其后收受程式之后手,倘若其后收受程式之人亦服膺以下二项麻理授权条款之义务性规定,则其对程式亦享有与前手运用范围相同之同一权利。 diff --git a/LICENSE-CHT.txt b/LICENSE-CHT.txt index b28a7f56..518d06f8 100644 --- a/LICENSE-CHT.txt +++ b/LICENSE-CHT.txt @@ -2,7 +2,7 @@ vChewing macOS: MIT-NTL License 麻理(去商標)授權合約 © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. 小麥注音引擎研發:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。 -威注音 macOS 程式研發協力:Hiraku Wang。 +威注音 macOS 程式研發:Shiki Suen, Hiraku Wang, 等。 威注音詞庫維護:Shiki Suen。 軟體之著作權利人依此麻理授權條款,將其對於軟體之著作權利授權釋出,只須使用者踐履以下二項麻理授權條款敘明之義務性規定,其即享有對此軟體程式及其相關說明文檔自由不受限制地進行利用之權利,範圍包括「使用、重製、修改、合併、出版、散布、再授權、及販售程式重製作品」等諸多方面之應用,而散布程式之人、更可將上述權利傳遞予其後收受程式之後手,倘若其後收受程式之人亦服膺以下二項麻理授權條款之義務性規定,則其對程式亦享有與前手運用範圍相同之同一權利。 diff --git a/LICENSE-JPN.txt b/LICENSE-JPN.txt index c7b8afff..340b1f37 100644 --- a/LICENSE-JPN.txt +++ b/LICENSE-JPN.txt @@ -2,7 +2,7 @@ vChewing macOS: MIT商標不許可ライセンス (MIT-NTL License) © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. 小麦注音入力エンジン開発:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, など。 -威注音 macOS 版の開発協力:Hiraku Wang。 +威注音 macOS 版の開発:Hiraku Wang, Shiki Suen, など。 威注音語彙データの維持:Shiki Suen。 以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル(以下「ソフトウェア」)の複製を取得するすべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブライセンス、および/または販売する権利、およびソフトウェアを提供する相手に同じことを許可する権利も無制限に含まれます。 diff --git a/LICENSE.txt b/LICENSE.txt index 923830c0..319b514d 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -2,7 +2,7 @@ vChewing macOS: MIT-NTL License © 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project. McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development Reinforced by Hiraku Wang. +vChewing macOS Development: Shiki Suen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib index 2da9449d..1700100f 100644 --- a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib @@ -58,7 +58,7 @@ McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al. -vChewing macOS Development Reinforced by Hiraku Wang. +vChewing macOS Development: Shiki Suen, Hiraku Wang, etc. vChewing Phrase Database Maintained by Shiki Suen. diff --git a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings index 15eabeb1..2794c3c6 100644 --- a/Source/WindowNIBs/en.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ -"lblCredits.title" = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ +"lblCredits.title" = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; diff --git a/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings b/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings index d39e1f93..71ab1f3c 100644 --- a/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ -"lblCredits.title" = "小麦注音入力エンジン開発:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, など。\nmacOS 版の開発協力:Hiraku Wang。\n威注音語彙データの維持:Shiki Suen。"; +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ +"lblCredits.title" = "小麦注音入力エンジン開発:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, など。\nmacOS 版の開発:Shiki Suen, Hiraku Wang, など。\n威注音語彙データの維持:Shiki Suen。"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings index f327b548..3657c6b6 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ -"VW8-s5-Wpn.title" = "小麦注音引擎研发:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研发协力:Hiraku Wang。\n威注音词库维护:Shiki Suen。"; +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ +"VW8-s5-Wpn.title" = "小麦注音引擎研发:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研发:Shiki Suen, Hiraku Wang, 等。\n威注音词库维护:Shiki Suen。"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings index f1463355..fd892d88 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmAboutWindow.strings @@ -23,5 +23,5 @@ /* Class = "NSTextFieldCell"; title = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; ObjectID = "lblCopyright"; */ // "lblCopyright.title" = "© 2011-2022 OpenVanilla Project & © 2021-2022 vChewing Project."; -/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development Reinforced by Hiraku Wang.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ -"VW8-s5-Wpn.title" = "小麥注音引擎研發:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研發協力:Hiraku Wang。\n威注音詞庫維護:Shiki Suen。"; +/* Class = "NSTextFieldCell"; title = "McBopomofo Engine by Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, et al.\nvChewing macOS Development: Shiki Suen, Hiraku Wang, etc.\nvChewing Phrase Database Maintained by Shiki Suen."; ObjectID = "lblCredits"; */ +"VW8-s5-Wpn.title" = "小麥注音引擎研發:Mengjuei Hsieh, Lukhnos Liu, Zonble Yang, 等。\n威注音 macOS 程式研發:Shiki Suen, Hiraku Wang, 等。\n威注音詞庫維護:Shiki Suen。"; From 96b30e9fe92cec18e28c18bda6fdfeef59a10f8e Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 26 Feb 2022 14:48:36 +0800 Subject: [PATCH 23/24] PrefWindow // Adding missed i18n translations. --- .../Source/WindowNIBs/en.lproj/frmPrefWindow.strings | 9 +++++++++ .../Source/WindowNIBs/ja.lproj/frmPrefWindow.strings | 9 +++++++++ .../WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings | 9 +++++++++ .../WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings | 9 +++++++++ 4 files changed, 36 insertions(+) diff --git a/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings index 8e72240f..0f699ea3 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/en.lproj/frmPrefWindow.strings @@ -196,3 +196,12 @@ /* Class = "NSTextFieldCell"; title = "Regarding On-Screen Keyboard Support:"; ObjectID = "wQ9-px-b07"; */ "wQ9-px-b07.title" = "Regarding On-Screen Keyboard Viewer Support:\n\n\tSince v1.3.2, vChewing supports on-screen keyboard by supporting \"Apple Zhuyin Bopomofo\" and \"Apple Zhuyin Eten\" alphanumeric layout. Theoreotically, these two dynamic layouts work with all types of Apple physical keyboards, and you can report failure cases through macOS Feedback Assistant app if macOS built-in Zhuyin / Eten-Zhuyin Input Method fails from working with your non-US keyboard.\n\n\tHOWEVER, choosing such dynamic alphanumeric layouts REQUIRING THAT you have to choose the Bopomofo layout above to Standard (Microsoft / Dachen) since the Bopomofo / Eten layout support in this case is already finished by the macOS system."; + +/* Class = "NSButtonCell"; title = "Cycling Pages"; ObjectID = "s7u-Fm-dVg"; */ +"s7u-Fm-dVg.title" = "Cycling Pages"; + +/* Class = "NSButtonCell"; title = "Cycling Candidates"; ObjectID = "FVC-br-H57"; */ +"FVC-br-H57.title" = "Cycling Candidates"; + +/* Class = "NSTextFieldCell"; title = "Choose the behavior of (Shift+)Tab key in the candidate window."; ObjectID = "ueU-Rz-a1C"; */ +"ueU-Rz-a1C.title" = "Choose the behavior of (Shift+)Tab key in the candidate window."; diff --git a/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings index 859f850c..27296d66 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings @@ -196,3 +196,12 @@ /* Class = "NSTextFieldCell"; title = "Regarding On-Screen Keyboard Support:"; ObjectID = "wQ9-px-b07"; */ "wQ9-px-b07.title" = "macOS 内蔵のキーボードビューアについて:\n\n\t威注音は v1.3.2 版にて macOS 内蔵のキーボードビューアをサポートし始めたが、「Apple Zhuyin Bopomofo」と「Apple Zhuyin Eten」この2つダイナミック英数キーボード配列をサポートしたためである。基本的には、この機能は全ての言語の Apple キーボードと一緒に動けるはず。macOS 内蔵の注音入力と倚天注音入力が支障なく使える限り(支障があったら Feedback Assistant.app で Apple にご報告を)、この2つダイナミック英数キーボード配列も威注音で作動できるだと考えられる。\n\n\tだが、もし、ダイナミック英数キーボード配列を起用すると、今のこの画面の上の「注音キーボード配列」を標準配列にしなければならぬこと。なぜなら、この場合、倚天などの注音配列のサポート役割は macOS である。"; + +/* Class = "NSButtonCell"; title = "Cycling Pages"; ObjectID = "s7u-Fm-dVg"; */ +"s7u-Fm-dVg.title" = "ページ"; + +/* Class = "NSButtonCell"; title = "Cycling Candidates"; ObjectID = "FVC-br-H57"; */ +"FVC-br-H57.title" = "候補文字そのもの"; + +/* Class = "NSTextFieldCell"; title = "Choose the behavior of (Shift+)Tab key in the candidate window."; ObjectID = "ueU-Rz-a1C"; */ +"ueU-Rz-a1C.title" = "入力候補陳列での (Shift+)Tab キーの輪番切替対象をご指定ください。"; diff --git a/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings index c2a38827..600874d5 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings @@ -196,3 +196,12 @@ /* Class = "NSTextFieldCell"; title = "Regarding On-Screen Keyboard Support:"; ObjectID = "wQ9-px-b07"; */ "wQ9-px-b07.title" = "关于 macOS 内建萤幕模拟键盘支援:\n\n\t自 v1.3.2 版开始,威注音支援 macOS 内建的萤幕小键盘。该功能是借由对「Apple 标准注音键盘布局」与「Apple 倚天注音键盘布局」这两个动态英数键盘布局来完成的。理论上来讲,这两个动态英数键盘布局应该可以与所有语种的 Apple 物理键盘相容。如果有不相容的情况的话,macOS 内建的注音与倚天注音输入法一定也会有相同的故障(可以借由 Feedback Assistant.app 向 Apple 反馈这种键盘布局问题)。\n\n\t然而,如果您启用了这种动态英数键盘布局的话,请将当前画面顶端的注音键盘布局设为「微软/大千……」,因为对诸如倚天等异种键盘的支援已经交给 macOS 系统来事先完成了。"; + +/* Class = "NSButtonCell"; title = "Cycling Pages"; ObjectID = "s7u-Fm-dVg"; */ +"s7u-Fm-dVg.title" = "轮替页面"; + +/* Class = "NSButtonCell"; title = "Cycling Candidates"; ObjectID = "FVC-br-H57"; */ +"FVC-br-H57.title" = "轮替候选字"; + +/* Class = "NSTextFieldCell"; title = "Choose the behavior of (Shift+)Tab key in the candidate window."; ObjectID = "ueU-Rz-a1C"; */ +"ueU-Rz-a1C.title" = "指定 (Shift+)Tab 热键在选字窗内的轮替操作对象。"; diff --git a/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings b/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings index 7032b8c9..0fff1e88 100644 --- a/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings @@ -196,3 +196,12 @@ /* Class = "NSTextFieldCell"; title = "Regarding On-Screen Keyboard Support:"; ObjectID = "wQ9-px-b07"; */ "wQ9-px-b07.title" = "關於 macOS 內建螢幕模擬鍵盤支援:\n\n\t自 v1.3.2 版開始,威注音支援 macOS 內建的螢幕小鍵盤。該功能是藉由對「Apple 標準注音鍵盤佈局」與「Apple 倚天注音鍵盤佈局」這兩個動態英數鍵盤佈局來完成的。理論上來講,這兩個動態英數鍵盤佈局應該可以與所有語種的 Apple 物理鍵盤相容。如果有不相容的情況的話,macOS 內建的注音與倚天注音輸入法一定也會有相同的故障(可以藉由 Feedback Assistant.app 向 Apple 反饋這種鍵盤佈局問題)。\n\n\t然而,如果您啟用了這種動態英數鍵盤佈局的話,請將當前畫面頂端的注音鍵盤佈局設為「微軟/大千……」,因為對諸如倚天等異種鍵盤的支援已經交給 macOS 系統來事先完成了。"; + +/* Class = "NSButtonCell"; title = "Cycling Pages"; ObjectID = "s7u-Fm-dVg"; */ +"s7u-Fm-dVg.title" = "輪替頁面"; + +/* Class = "NSButtonCell"; title = "Cycling Candidates"; ObjectID = "FVC-br-H57"; */ +"FVC-br-H57.title" = "輪替候選字"; + +/* Class = "NSTextFieldCell"; title = "Choose the behavior of (Shift+)Tab key in the candidate window."; ObjectID = "ueU-Rz-a1C"; */ +"ueU-Rz-a1C.title" = "指定 (Shift+)Tab 熱鍵在選字窗內的輪替操作對象。"; From f33b26e8565e0f82b21e112452ca84a516755957 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 24 Feb 2022 22:33:28 +0800 Subject: [PATCH 24/24] Bump version to 1.3.6 Build 1925. --- Update-Info.plist | 4 ++-- vChewing.xcodeproj/project.pbxproj | 32 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Update-Info.plist b/Update-Info.plist index e189ccff..40e16d4a 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -7,8 +7,8 @@ UpdateInfoSite https://gitee.com/vChewing/vChewing-macOS/releases CFBundleVersion - 1923 + 1925 CFBundleShortVersionString - 1.3.4 + 1.3.6 diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index b28153e9..2d4d7e84 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -1293,7 +1293,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; @@ -1312,7 +1312,7 @@ INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1345,7 +1345,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1359,7 +1359,7 @@ INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1389,7 +1389,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_ASSET_PATHS = KeyboardExtension/vChewingKeyLayout.bundle; DEVELOPMENT_TEAM = ""; @@ -1408,7 +1408,7 @@ INFOPLIST_KEY_NSHumanReadableCopyright = ""; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 12.1; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing.KeyboardExtension; @@ -1440,7 +1440,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = KeyboardExtension/vChewingKeyLayout.bundle; DEVELOPMENT_TEAM = ""; @@ -1454,7 +1454,7 @@ INFOPLIST_KEY_NSHumanReadableCopyright = ""; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 12.1; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing.KeyboardExtension; @@ -1570,7 +1570,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1602,7 +1602,7 @@ INFOPLIST_FILE = "Source/Resources/IME-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1635,7 +1635,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1661,7 +1661,7 @@ INFOPLIST_FILE = "Source/Resources/IME-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1744,7 +1744,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -1766,7 +1766,7 @@ INFOPLIST_FILE = "Installer/Installer-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1794,7 +1794,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1924; + CURRENT_PROJECT_VERSION = 1925; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1810,7 +1810,7 @@ INFOPLIST_FILE = "Installer/Installer-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.3.5; + MARKETING_VERSION = 1.3.6; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";