From d5914e5f7851cd45712ed57e538f013578899d79 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 15 May 2022 09:18:23 +0800 Subject: [PATCH 01/24] Update AUTHORS --- AUTHORS | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index e9eaf28d..cb04c967 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,14 +1,30 @@ $ Main contributors and volunteers of this repository (vChewing for macOS): -- Shiki Suen // Main developer of vChewing for macOS. +- Shiki Suen // Main developer of vChewing for macOS, Megrez language engine, and Tekkon syllable composer engine. - Hiraku Wang // Technical reinforcement in Cocoa during the Object-Cpp dev period of this project. - Isaac Xen // Technical reinforcement in Swift: SFX Module and StringView Ranges Extension. $ Contributors and volunteeres of the upstream repo, having no responsibility in discussing anything in the current repo: -- Mengjuei Hsieh // McBopomofo for macOS 1.x main developer and architect. -- Zonble Yang // McBopomofo for macOS 2.x architect, especially state-based IME behavior management. -- Lukhnos D Liu // Developer of the Mandarin syllable input processor. +- Zonble Yang: + - McBopomofo for macOS 2.x architect, especially state-based IME behavior management. + - Voltaire candidate window MK2 (massively modified in vChewing by Shiki Suen). + - InputHandler. + - Notifier window and Tooltip UI. + - NSStringUtils and FSEventStreamHelper. + - App-style installer (only preserved for developer purposes). +- Mengjuei Hsieh + - McBopomofo for macOS 1.x main developer and architect. + - User Override Module (not enabled at this moment). + - Shiki Suen is trying to rewrite this module in Swift but it is not working yet. + +Although there is no Lukhnos's codes left in the current repository, we still credit him for his previous work: + +- Lukhnos Liu: + - Developer of Gramambular language engine (removed since vChewing 1.5.4). + - Shiki Suen's Megrez engine is basically a Swift-rewritten version of Gramambular. + - Developer of Mandarin syllable composer (removed since vChewing 1.5.7). + - Shiki Suen's Tekkon engine is made from scratch and has no relationship to Mandarin syllable composer. $ Special thanks to: From 6d6e50ab8fc572cddd38afecebd97daa1ba99ba7 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 15 May 2022 13:42:21 +0800 Subject: [PATCH 02/24] Tekkon // DachenCP26 arrange and Pinyin input support. --- .../ControllerModules/SyllableComposer.swift | 949 ++++++++++++++---- 1 file changed, 747 insertions(+), 202 deletions(-) diff --git a/Source/Modules/ControllerModules/SyllableComposer.swift b/Source/Modules/ControllerModules/SyllableComposer.swift index f0305763..e391977d 100644 --- a/Source/Modules/ControllerModules/SyllableComposer.swift +++ b/Source/Modules/ControllerModules/SyllableComposer.swift @@ -40,19 +40,26 @@ public struct Tekkon { /// 定義注音排列的類型 public enum MandarinParser: Int { case ofDachen = 0 - case ofEten = 1 - case ofHsu = 2 + case ofDachen26 = 1 + case ofEten = 2 case ofEten26 = 3 - case ofIBM = 4 - case ofMiTAC = 5 - case ofFakeSeigyou = 6 + case ofHsu = 4 + case ofIBM = 5 + case ofMiTAC = 6 case ofSeigyou = 7 - case ofHanyuPinyin = 10 // 目前暫時沒有漢語拼音支援 + case ofFakeSeigyou = 8 + case ofHanyuPinyin = 100 + case ofSecondaryPinyin = 101 + case ofYalePinyin = 102 + case ofHualuoPinyin = 103 + case ofUniversalPinyin = 104 var name: String { switch self { case .ofDachen: return "Dachen" + case .ofDachen26: + return "Dachen26" case .ofEten: return "ETen" case .ofHsu: @@ -69,6 +76,14 @@ public struct Tekkon { return "Seigyou" case .ofHanyuPinyin: return "HanyuPinyin" + case .ofSecondaryPinyin: + return "SecondaryPinyin" + case .ofYalePinyin: + return "YalePinyin" + case .ofHualuoPinyin: + return "HualuoPinyin" + case .ofUniversalPinyin: + return "UniversalPinyin" } } } @@ -138,6 +153,14 @@ public struct Tekkon { valueStorage = "" } + /// 自我變換資料值。 + /// - Parameters: + /// - strOf: 要取代的內容。 + /// - strWith: 要取代成的內容。 + mutating func selfReplace(_ strOf: String, _ strWith: String = "") { + valueStorage = valueStorage.replacingOccurrences(of: strOf, with: strWith) + } + // MARK: - Misc Definitions /// 這些內容用來滿足 "Equatable, Hashable, ExpressibleByStringLiteral" 需求。 @@ -185,33 +208,34 @@ public struct Tekkon { /// 聲調。 public var intonation: Phonabet = "" + /// 為拉丁字母專用的組音區 + public var romajiBuffer: String = "" + /// 注音排列種類。預設情況下是大千排列(Windows / macOS 預設注音排列)。 public var parser: MandarinParser = .ofDachen /// 內容值,會直接按照正確的順序拼裝自己的聲介韻調內容、再回傳。 /// 注意:直接取這個參數的內容的話,陰平聲調會成為一個空格。 - /// 如果是要取不帶空格的注音的話,請使用「.realComposition」而非「.value」。 + /// 如果是要取不帶空格的注音的話,請使用「.getComposition()」而非「.value」。 public var value: String { consonant.value + semivowel.value + vowel.value + intonation.value } - /// 這是專門用來「生成用以進行詞庫檢索的 Key」的函數。 - public var realComposition: String { - value.replacingOccurrences(of: " ", with: "") - } - - /// 與 value 類似。這個函數就是用來決定輸入法組字區內顯示的注音/拼音內容。 + /// 與 value 類似,這個函數就是用來決定輸入法組字區內顯示的注音/拼音內容, /// 但可以指定是否輸出教科書格式(拼音的調號在字母上方、注音的輕聲寫在左側)。 + /// - Parameters: + /// - isHanyuPinyin: 是否將輸出結果轉成漢語拼音。 + /// - isTextBookStyle: 是否將輸出的注音/拼音結果轉成教科書排版格式。 public func getComposition(isHanyuPinyin: Bool = false, isTextBookStyle: Bool = false) -> String { switch isHanyuPinyin { - case false: + case false: // 注音輸出的場合 var valReturnZhuyin = value.replacingOccurrences(of: " ", with: "") if isTextBookStyle, valReturnZhuyin.contains("˙") { valReturnZhuyin = String(valReturnZhuyin.dropLast()) valReturnZhuyin.insert("˙", at: valReturnZhuyin.startIndex) } return valReturnZhuyin - case true: + case true: // 拼音輸出的場合 var valReturnPinyin = Tekkon.cnvPhonaToHanyuPinyin(target: value) if isTextBookStyle { valReturnPinyin = Tekkon.cnvHanyuPinyinToTextbookStyle(target: valReturnPinyin) @@ -220,15 +244,47 @@ public struct Tekkon { } } + // 該函數僅用來獲取給 macOS InputMethod Kit 的內文組字區使用的顯示字串。 + /// - Parameters: + /// - isHanyuPinyin: 是否將輸出結果轉成漢語拼音。 + public func getInlineCompositionForIMK(isHanyuPinyin: Bool = false) -> String { + switch parser { + case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin: + var toneReturned = "" + switch intonation.value { + case " ": toneReturned = "1" + case "ˊ": toneReturned = "2" + case "ˇ": toneReturned = "3" + case "ˋ": toneReturned = "4" + case "˙": toneReturned = "5" + default: break + } + return romajiBuffer + toneReturned + default: return getComposition(isHanyuPinyin: isHanyuPinyin) + } + } + /// 注拼槽內容是否為空。 public var isEmpty: Bool { - intonation.isEmpty && vowel.isEmpty && semivowel.isEmpty && consonant.isEmpty + switch parser { + case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin: + return intonation.isEmpty && romajiBuffer.isEmpty + default: return intonation.isEmpty && vowel.isEmpty && semivowel.isEmpty && consonant.isEmpty + } + } + + /// 注拼槽內容是否為空。 + public var isPronouncable: Bool { + !vowel.isEmpty || !semivowel.isEmpty || !consonant.isEmpty } // MARK: 注拼槽對外處理函數 /// 初期化一個新的注拼槽。可以藉由 @input 參數指定初期已經傳入的按鍵訊號。 /// 還可以在初期化時藉由 @arrange 參數來指定注音排列(預設為「.ofDachen」大千佈局)。 + /// - Parameters: + /// - input: 傳入的 String 內容,用以處理單個字符。 + /// - arrange: 要使用的注音排列。 public init(_ input: String = "", arrange parser: MandarinParser = .ofDachen) { ensureParser(arrange: parser) receiveKey(fromString: input) @@ -241,6 +297,7 @@ public struct Tekkon { semivowel.clear() vowel.clear() intonation.clear() + romajiBuffer = "" } // MARK: - Public Functions @@ -256,6 +313,8 @@ public struct Tekkon { switch parser { case .ofDachen: return Tekkon.mapQwertyDachen[input] != nil + case .ofDachen26: + return Tekkon.mapDachenCP26StaticKeys[input] != nil case .ofEten: return Tekkon.mapQwertyEtenTraditional[input] != nil case .ofHsu: @@ -270,7 +329,7 @@ public struct Tekkon { return Tekkon.mapSeigyou[input] != nil case .ofFakeSeigyou: return Tekkon.mapFakeSeigyou[input] != nil - case .ofHanyuPinyin: + case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin: return Tekkon.mapArayuruPinyin.contains(input) } } @@ -284,14 +343,22 @@ public struct Tekkon { /// - Parameters: /// - fromString: 傳入的 String 內容。 public mutating func receiveKey(fromString input: String = "") { - let translatedInput = translate(key: String(input)) - let thePhone: Phonabet = .init(translatedInput) - switch thePhone.type { - case .consonant: consonant = thePhone - case .semivowel: semivowel = thePhone - case .vowel: vowel = thePhone - case .intonation: intonation = thePhone - default: break + switch parser { + case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin: + if mapArayuruPinyinIntonation.keys.contains(input) { + if let theTone = mapArayuruPinyinIntonation[input] { + intonation = Phonabet(theTone) + } + } else { + // 為了防止 romajiBuffer 越敲越長帶來算力負擔,這裡讓它在要溢出時自動丟掉先取音頭。 + if romajiBuffer.count > 5 { + romajiBuffer = String(romajiBuffer.dropFirst()) + } + let romajiBufferBackup = romajiBuffer + input + receiveSequence(romajiBufferBackup, isRomaji: true) + romajiBuffer = romajiBufferBackup + } + default: receiveKey(fromPhonabet: translate(key: String(input))) } } @@ -307,12 +374,90 @@ public struct Tekkon { } } + /// 接受傳入的按鍵訊號時的處理,處理對象為單個注音符號。 + /// 主要就是將注音符號拆分辨識且分配到正確的貯存位置而已。 + /// - Parameters: + /// - fromPhonabet: 傳入的單個注音符號字串。 + public mutating func receiveKey(fromPhonabet phonabet: String = "") { + let thePhone: Phonabet = .init(phonabet) + switch thePhone.type { + case .consonant: consonant = thePhone + case .semivowel: semivowel = thePhone + case .vowel: vowel = thePhone + case .intonation: intonation = thePhone + default: break + } + } + + /// 處理一連串的按鍵輸入。 + /// - Parameters: + /// - givenSequence: 傳入的 String 內容,用以處理一整串擊鍵輸入。 + /// - isRomaji: 如果輸入的字串是諸如漢語拼音這樣的西文字母拼音的話,請啟用此選項。 + public mutating func receiveSequence(_ givenSequence: String = "", isRomaji: Bool = false) { + clear() + if isRomaji { + switch parser { + case .ofHanyuPinyin: + if let dictResult = mapHanyuPinyin[givenSequence] { + for phonabet in dictResult { + receiveKey(fromPhonabet: String(phonabet)) + } + } + case .ofSecondaryPinyin: + if let dictResult = mapSecondaryPinyin[givenSequence] { + for phonabet in dictResult { + receiveKey(fromPhonabet: String(phonabet)) + } + } + case .ofYalePinyin: + if let dictResult = mapYalePinyin[givenSequence] { + for phonabet in dictResult { + receiveKey(fromPhonabet: String(phonabet)) + } + } + case .ofHualuoPinyin: + if let dictResult = mapHualuoPinyin[givenSequence] { + for phonabet in dictResult { + receiveKey(fromPhonabet: String(phonabet)) + } + } + case .ofUniversalPinyin: + if let dictResult = mapUniversalPinyin[givenSequence] { + for phonabet in dictResult { + receiveKey(fromPhonabet: String(phonabet)) + } + } + default: break + } + } else { + for key in givenSequence { + receiveKey(fromString: String(key)) + } + } + } + + /// 處理一連串的按鍵輸入、且返回被處理之後的注音(陰平為空格)。 + /// - Parameters: + /// - givenSequence: 傳入的 String 內容,用以處理一整串擊鍵輸入。 + public mutating func convertSequenceToRawComposition(_ givenSequence: String = "") -> String { + receiveSequence(givenSequence) + return value + } + /// 專門用來響應使用者摁下 BackSpace 按鍵時的行為。 /// 刪除順序:調、韻、介、聲。 /// @--DISCUSSION--@ /// 基本上就是按順序從游標前方開始往後刪。 public mutating func doBackSpace() { - if !intonation.isEmpty { + if [.ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin].contains(parser), + !romajiBuffer.isEmpty + { + if !intonation.isEmpty { + intonation.clear() + } else { + romajiBuffer = String(romajiBuffer.dropLast()) + } + } else if !intonation.isEmpty { intonation.clear() } else if !vowel.isEmpty { vowel.clear() @@ -353,6 +498,8 @@ public struct Tekkon { switch parser { case .ofDachen: return Tekkon.mapQwertyDachen[key] ?? "" + case .ofDachen26: + return handleDachen26(key: key) case .ofEten: return Tekkon.mapQwertyEtenTraditional[key] ?? "" case .ofHsu: @@ -367,7 +514,8 @@ public struct Tekkon { return Tekkon.mapSeigyou[key] ?? "" case .ofFakeSeigyou: return Tekkon.mapFakeSeigyou[key] ?? "" - case .ofHanyuPinyin: break // TODO: 待辦 + case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin: + break // 漢語拼音單獨用另外的函數處理 } return "" } @@ -383,18 +531,27 @@ public struct Tekkon { let incomingPhonabet = Phonabet(strReturn) switch key { - case "d": if consonant.isEmpty { consonant = "ㄉ" } else { intonation = "˙" } - case "f": if consonant.isEmpty { consonant = "ㄈ" } else { intonation = "ˊ" } - case "h": if consonant.isEmpty { consonant = "ㄏ" } else { vowel = "ㄦ" } - case "j": if consonant.isEmpty { consonant = "ㄖ" } else { intonation = "ˇ" } - case "k": if consonant.isEmpty { consonant = "ㄎ" } else { intonation = "ˋ" } - case "l": if consonant.isEmpty { consonant = "ㄌ" } else { vowel = "ㄥ" } - case "m": if consonant.isEmpty { consonant = "ㄇ" } else { vowel = "ㄢ" } - case "n": if consonant.isEmpty { consonant = "ㄋ" } else { vowel = "ㄣ" } - case "p": if consonant.isEmpty { consonant = "ㄆ" } else { vowel = "ㄡ" } - case "q": if consonant.isEmpty { consonant = "ㄗ" } else { vowel = "ㄟ" } - case "t": if consonant.isEmpty { consonant = "ㄊ" } else { vowel = "ㄤ" } - case "w": if consonant.isEmpty { consonant = "ㄘ" } else { vowel = "ㄝ" } + case "d": if !isPronouncable { consonant = "ㄉ" } else { intonation = "˙" } + case "f": if !isPronouncable { consonant = "ㄈ" } else { intonation = "ˊ" } + case "j": if !isPronouncable { consonant = "ㄖ" } else { intonation = "ˇ" } + case "k": if !isPronouncable { consonant = "ㄎ" } else { intonation = "ˋ" } + case "h": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄏ" } else { vowel = "ㄦ" } + case "l": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄌ" } else { vowel = "ㄥ" } + case "m": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄇ" } else { vowel = "ㄢ" } + case "n": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄋ" } else { vowel = "ㄣ" } + case "q": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄗ" } else { vowel = "ㄟ" } + case "t": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄊ" } else { vowel = "ㄤ" } + case "w": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄘ" } else { vowel = "ㄝ" } + case "p": + if consonant.isEmpty, semivowel.isEmpty { + consonant = "ㄆ" + } else if consonant.isEmpty, semivowel == "ㄧ" { + vowel = "ㄡ" + } else if consonant.isEmpty { + vowel = "ㄆ" + } else { + vowel = "ㄡ" + } default: break } @@ -426,6 +583,20 @@ public struct Tekkon { } } + if "dfjk ".contains(key), + !consonant.isEmpty, semivowel.isEmpty, vowel.isEmpty + { + consonant.selfReplace("ㄆ", "ㄡ") + consonant.selfReplace("ㄇ", "ㄢ") + consonant.selfReplace("ㄊ", "ㄤ") + consonant.selfReplace("ㄋ", "ㄣ") + consonant.selfReplace("ㄌ", "ㄥ") + consonant.selfReplace("ㄏ", "ㄦ") + } + + // 後置修正 + if value == "ㄍ˙" { consonant = "ㄑ" } + // 這些按鍵在上文處理過了,就不要再回傳了。 if "dfhjklmnpqtw".contains(key) { strReturn = "" } @@ -443,63 +614,171 @@ public struct Tekkon { strReturn = Tekkon.mapHsuStaticKeys[key] ?? "" let incomingPhonabet = Phonabet(strReturn) + if key == " ", value == "ㄋ" { + consonant = "" + vowel = "ㄣ" + } + switch key { - case "a": if consonant.isEmpty { consonant = "ㄘ" } else { vowel = "ㄟ" } - case "d": if consonant.isEmpty { consonant = "ㄉ" } else { intonation = "ˊ" } + case "d": if isPronouncable { intonation = "ˊ" } else { consonant = "ㄉ" } + case "f": if isPronouncable { intonation = "ˇ" } else { consonant = "ㄈ" } + case "s": if isPronouncable { intonation = "˙" } else { consonant = "ㄙ" } + case "j": if isPronouncable { intonation = "ˋ" } else { consonant = "ㄓ" } + case "a": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄘ" } else { vowel = "ㄟ" } + case "v": if semivowel.isEmpty { consonant = "ㄔ" } else { consonant = "ㄑ" } + case "c": if semivowel.isEmpty { consonant = "ㄕ" } else { consonant = "ㄒ" } case "e": if semivowel.isEmpty { semivowel = "ㄧ" } else { vowel = "ㄝ" } - case "f": if consonant.isEmpty { consonant = "ㄈ" } else { intonation = "ˇ" } - case "g": if consonant.isEmpty { consonant = "ㄍ" } else { vowel = "ㄜ" } - case "h": if consonant.isEmpty { consonant = "ㄏ" } else { vowel = "ㄛ" } - case "k": if consonant.isEmpty { consonant = "ㄎ" } else { vowel = "ㄤ" } + case "g": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄍ" } else { vowel = "ㄜ" } + case "h": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄏ" } else { vowel = "ㄛ" } + case "k": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄎ" } else { vowel = "ㄤ" } + case "m": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄇ" } else { vowel = "ㄢ" } + case "n": if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄋ" } else { vowel = "ㄣ" } case "l": if value.isEmpty, !consonant.isEmpty, !semivowel.isEmpty { vowel = "ㄦ" - } else if consonant.isEmpty { + } else if consonant.isEmpty, semivowel.isEmpty { consonant = "ㄌ" } else { vowel = "ㄥ" } - case "m": if consonant.isEmpty { consonant = "ㄇ" } else { vowel = "ㄢ" } - case "n": if consonant.isEmpty { consonant = "ㄋ" } else { vowel = "ㄣ" } - case "s": if consonant.isEmpty { consonant = "ㄙ" } else { intonation = "˙" } default: break } - // 處理「一個按鍵對應兩個聲母」的情形。 - if !consonant.isEmpty, incomingPhonabet.type == .semivowel { - switch consonant { - case "ㄍ": // 許氏鍵盤應該也需要這個自動糾正 - switch incomingPhonabet { - case "ㄧ": consonant = "ㄑ" // ㄑㄧ - case "ㄨ": consonant = "ㄍ" // ㄍㄨ - case "ㄩ": consonant = "ㄑ" // ㄑㄩ - default: break - } - case "ㄓ": - if intonation.isEmpty { + + // 處理特殊情形。 + switch incomingPhonabet.type { + case .semivowel: + switch consonant { + case "ㄍ": // 許氏鍵盤應該也需要這個自動糾正 switch incomingPhonabet { - case "ㄧ": consonant = "ㄐ" // ㄐㄧ - case "ㄨ": consonant = "ㄓ" // ㄓㄨ - case "ㄩ": consonant = "ㄐ" // ㄐㄩ + case "ㄧ": consonant = "ㄑ" // ㄑㄧ + case "ㄨ": consonant = "ㄍ" // ㄍㄨ + case "ㄩ": consonant = "ㄑ" // ㄑㄩ default: break } - } - case "ㄕ": - switch incomingPhonabet { - case "ㄧ": consonant = "ㄒ" // ㄒㄧ - case "ㄨ": consonant = "ㄕ" // ㄕㄨ - case "ㄩ": consonant = "ㄒ" // ㄒㄩ - default: break - } - default: break - } + case "ㄓ": + if intonation.isEmpty { + switch incomingPhonabet { + case "ㄧ": consonant = "ㄐ" // ㄐㄧ + case "ㄨ": consonant = "ㄓ" // ㄓㄨ + case "ㄩ": consonant = "ㄐ" // ㄐㄩ + default: break + } + } + case "ㄑ": + if intonation.isEmpty { + switch incomingPhonabet { + case "ㄧ": consonant = "ㄑ" // ㄐㄧ + case "ㄨ": consonant = "ㄔ" // ㄓㄨ + case "ㄩ": consonant = "ㄑ" // ㄐㄩ + default: break + } + } + case "ㄕ": + switch incomingPhonabet { + case "ㄧ": consonant = "ㄒ" // ㄒㄧ + case "ㄨ": consonant = "ㄕ" // ㄕㄨ + case "ㄩ": consonant = "ㄒ" // ㄒㄩ + default: break + } + default: break + } + case .vowel: + if semivowel.isEmpty { + consonant.selfReplace("ㄐ", "ㄓ") + consonant.selfReplace("ㄑ", "ㄔ") + consonant.selfReplace("ㄒ", "ㄕ") + } + default: break } - if key == "j" { // 對該按鍵作為調號的處理得放在最後 - if !consonant.isEmpty { intonation = "ˋ" } + if "dfjs ".contains(key) { + if !consonant.isEmpty, semivowel.isEmpty, vowel.isEmpty { + consonant.selfReplace("ㄍ", "ㄜ") + consonant.selfReplace("ㄋ", "ㄣ") + consonant.selfReplace("ㄌ", "ㄦ") + consonant.selfReplace("ㄎ", "ㄤ") + consonant.selfReplace("ㄇ", "ㄢ") + } + if !consonant.isEmpty, vowel.isEmpty { + consonant.selfReplace("ㄧ", "ㄝ") + } + if "ㄢㄣㄤㄥ".contains(vowel.value), semivowel.isEmpty { + consonant.selfReplace("ㄐ", "ㄓ") + consonant.selfReplace("ㄑ", "ㄔ") + consonant.selfReplace("ㄒ", "ㄕ") + } + if "ㄐㄑㄒ".contains(consonant.value), semivowel.isEmpty { + consonant.selfReplace("ㄐ", "ㄓ") + consonant.selfReplace("ㄑ", "ㄔ") + consonant.selfReplace("ㄒ", "ㄕ") + } + if vowel == "ㄜ", semivowel.isEmpty { consonant.selfReplace("ㄑ", "ㄔ") } + } + + // 後置修正 + if value == "ㄔ˙" { consonant = "ㄑ" } + + // 這些按鍵在上文處理過了,就不要再回傳了。 + if "acdefghjklmns".contains(key) { strReturn = "" } + + // 回傳結果是空的話,不要緊,因為上文已經代處理過分配過程了。 + return strReturn + } + + /// 大千忘形一樣同樣也比較麻煩,需要單獨處理。 + /// @--DISCUSSION--@ + /// 回傳結果是空的話,不要緊,因為該函數內部已經處理過分配過程了。 + /// - Parameters: + /// - key: 傳入的 String 訊號。 + mutating func handleDachen26(key: String = "") -> String { + var strReturn = "" + strReturn = Tekkon.mapDachenCP26StaticKeys[key] ?? "" + + switch key { + case "e": if isPronouncable { intonation = "ˊ" } else { consonant = "ㄍ" } + case "r": if isPronouncable { intonation = "ˇ" } else { consonant = "ㄐ" } + case "d": if isPronouncable { intonation = "ˋ" } else { consonant = "ㄎ" } + case "y": if isPronouncable { intonation = "˙" } else { consonant = "ㄗ" } + case "b": if !consonant.isEmpty || !semivowel.isEmpty { vowel = "ㄝ" } else { consonant = "ㄖ" } + case "i": if vowel.isEmpty || vowel == "ㄞ" { vowel = "ㄛ" } else { vowel = "ㄞ" } + case "l": if vowel.isEmpty || vowel == "ㄤ" { vowel = "ㄠ" } else { vowel = "ㄤ" } + case "n": if !consonant.isEmpty || !semivowel.isEmpty { vowel = "ㄥ" } else { consonant = "ㄙ" } + case "o": if vowel.isEmpty || vowel == "ㄢ" { vowel = "ㄟ" } else { vowel = "ㄢ" } + case "p": if vowel.isEmpty || vowel == "ㄦ" { vowel = "ㄣ" } else { vowel = "ㄦ" } + case "q": if consonant.isEmpty || consonant == "ㄅ" { consonant = "ㄆ" } else { consonant = "ㄅ" } + case "t": if consonant.isEmpty || consonant == "ㄓ" { consonant = "ㄔ" } else { consonant = "ㄓ" } + case "w": if consonant.isEmpty || consonant == "ㄉ" { consonant = "ㄊ" } else { consonant = "ㄉ" } + case "m": + if semivowel == "ㄩ", vowel != "ㄡ" { + semivowel = "" + vowel = "ㄡ" + } else if semivowel != "ㄩ", vowel == "ㄡ" { + semivowel = "ㄩ" + vowel = "" + } else if !semivowel.isEmpty { + vowel = "ㄡ" + } else { + semivowel = "ㄩ" + } + case "u": + if semivowel == "ㄧ", vowel != "ㄚ" { + semivowel = "" + vowel = "ㄚ" + } else if semivowel != "ㄧ", vowel == "ㄚ" { + semivowel = "ㄧ" + } else if semivowel == "ㄧ", vowel == "ㄚ" { + semivowel = "" + vowel = "" + } else if !semivowel.isEmpty { + vowel = "ㄚ" + } else { + semivowel = "ㄧ" + } + default: break } // 這些按鍵在上文處理過了,就不要再回傳了。 - if "adefghklmns".contains(key) { strReturn = "" } + if "qwtilopnbmuerdy".contains(key) { strReturn = "" } // 回傳結果是空的話,不要緊,因為上文已經代處理過分配過程了。 return strReturn @@ -533,53 +812,6 @@ public struct Tekkon { } } - // MARK: - Phonabets (Enum) - - /// 該 Enum 羅列了所有合理的注音符號,將來做漢語拼音功能支援時可能會用到。 - enum Phonabets: Phonabet { - case ofBO = "ㄅ" - case ofPO = "ㄆ" - case ofMO = "ㄇ" - case ofFO = "ㄈ" - case ofDE = "ㄉ" - case ofTE = "ㄊ" - case ofNE = "ㄋ" - case ofLE = "ㄌ" - case ofGE = "ㄍ" - case ofKE = "ㄎ" - case ofHE = "ㄏ" - case ofJI = "ㄐ" - case ofQI = "ㄑ" - case ofXI = "ㄒ" - case ofZH = "ㄓ" - case ofCH = "ㄔ" - case ofSH = "ㄕ" - case ofRI = "ㄖ" - case ofZI = "ㄗ" - case ofCI = "ㄘ" - case ofSI = "ㄙ" - case ofYI = "ㄧ" - case ofWU = "ㄨ" - case ofYU = "ㄩ" - case ofAA = "ㄚ" - case ofOO = "ㄛ" - case ofEE = "ㄜ" - case ofEA = "ㄝ" - case ofAI = "ㄞ" - case ofEI = "ㄟ" - case ofAO = "ㄠ" - case ofOU = "ㄡ" - case ofAN = "ㄢ" - case ofEN = "ㄣ" - case ofAG = "ㄤ" - case ofOG = "ㄥ" - case ofT1 = " " - case ofT2 = "ˊ" - case ofT3 = "ˇ" - case ofT4 = "ˋ" - case ofT5 = "˙" - } - // MARK: - Phonabet to Hanyu-Pinyin Conversion Processing /// 注音轉拼音,要求陰平必須是空格。 @@ -603,82 +835,90 @@ public struct Tekkon { /// 原始轉換對照表資料貯存專用佇列(數字標調格式) static let arrPhonaToHanyuPinyin = [ // 排序很重要。先處理最長的,再處理短的。不然會出亂子。 - [" ", "1"], ["ˊ", "2"], ["ˇ", "3"], ["ˋ", "4"], ["˙", "5"], ["ㄔㄨㄤ", "chuang"], ["ㄕㄨㄤ", "shuang"], - ["ㄓㄨㄤ", "zhuang"], ["ㄔㄨㄥ", "chong"], ["ㄔㄨㄞ", "chuai"], ["ㄔㄨㄢ", "chuan"], ["ㄍㄨㄤ", "guang"], ["ㄏㄨㄤ", "huang"], - ["ㄐㄧㄤ", "jiang"], ["ㄐㄩㄥ", "jiong"], ["ㄎㄨㄤ", "kuang"], ["ㄌㄧㄤ", "liang"], ["ㄋㄧㄤ", "niang"], ["ㄑㄧㄤ", "qiang"], - ["ㄑㄩㄥ", "qiong"], ["ㄕㄨㄞ", "shuai"], ["ㄕㄨㄢ", "shuan"], ["ㄒㄧㄤ", "xiang"], ["ㄒㄩㄥ", "xiong"], ["ㄓㄨㄥ", "zhong"], - ["ㄓㄨㄞ", "zhuai"], ["ㄓㄨㄢ", "zhuan"], ["ㄅㄧㄢ", "bian"], ["ㄅㄧㄠ", "biao"], ["ㄅㄧㄥ", "bing"], ["ㄔㄨㄚ", "chua"], - ["ㄔㄨㄟ", "chui"], ["ㄔㄨㄣ", "chun"], ["ㄔㄨㄛ", "chuo"], ["ㄘㄨㄥ", "cong"], ["ㄘㄨㄢ", "cuan"], ["ㄉㄧㄢ", "dian"], - ["ㄉㄧㄠ", "diao"], ["ㄉㄧㄥ", "ding"], ["ㄉㄨㄥ", "dong"], ["ㄉㄨㄢ", "duan"], ["ㄈㄧㄠ", "fiao"], ["ㄍㄧㄠ", "giao"], - ["ㄍㄧㄣ", "gin"], ["ㄍㄨㄥ", "gong"], ["ㄍㄨㄞ", "guai"], ["ㄍㄨㄢ", "guan"], ["ㄏㄨㄥ", "hong"], ["ㄏㄨㄞ", "huai"], - ["ㄏㄨㄢ", "huan"], ["ㄐㄧㄢ", "jian"], ["ㄐㄧㄠ", "jiao"], ["ㄐㄧㄥ", "jing"], ["ㄐㄩㄢ", "juan"], ["ㄎㄧㄡ", "kiu"], - ["ㄎㄨㄥ", "kong"], ["ㄎㄨㄞ", "kuai"], ["ㄎㄨㄢ", "kuan"], ["ㄌㄧㄢ", "lian"], ["ㄌㄧㄠ", "liao"], ["ㄌㄧㄥ", "ling"], - ["ㄌㄨㄥ", "long"], ["ㄌㄨㄢ", "luan"], ["ㄌㄩㄢ", "lvan"], ["ㄇㄧㄢ", "mian"], ["ㄇㄧㄠ", "miao"], ["ㄇㄧㄥ", "ming"], - ["ㄋㄧㄢ", "nian"], ["ㄋㄧㄠ", "niao"], ["ㄋㄧㄥ", "ning"], ["ㄋㄨㄥ", "nong"], ["ㄋㄨㄢ", "nuan"], ["ㄆㄧㄢ", "pian"], - ["ㄆㄧㄠ", "piao"], ["ㄆㄧㄥ", "ping"], ["ㄑㄧㄢ", "qian"], ["ㄑㄧㄠ", "qiao"], ["ㄑㄧㄥ", "qing"], ["ㄑㄩㄢ", "quan"], - ["ㄖㄨㄥ", "rong"], ["ㄖㄨㄢ", "ruan"], ["ㄕㄨㄚ", "shua"], ["ㄕㄨㄟ", "shui"], ["ㄕㄨㄣ", "shun"], ["ㄕㄨㄛ", "shuo"], - ["ㄙㄨㄥ", "song"], ["ㄙㄨㄢ", "suan"], ["ㄊㄧㄢ", "tian"], ["ㄊㄧㄠ", "tiao"], ["ㄊㄧㄥ", "ting"], ["ㄊㄨㄥ", "tong"], - ["ㄊㄨㄢ", "tuan"], ["ㄒㄧㄢ", "xian"], ["ㄒㄧㄠ", "xiao"], ["ㄒㄧㄥ", "xing"], ["ㄒㄩㄢ", "xuan"], ["ㄓㄨㄚ", "zhua"], - ["ㄓㄨㄟ", "zhui"], ["ㄓㄨㄣ", "zhun"], ["ㄓㄨㄛ", "zhuo"], ["ㄗㄨㄥ", "zong"], ["ㄗㄨㄢ", "zuan"], ["ㄈㄨㄥ", "fong"], - ["ㄐㄩㄣ", "jun"], ["ㄅㄧㄝ", "bie"], ["ㄅㄧㄣ", "bin"], ["ㄘㄨㄟ", "cui"], ["ㄘㄨㄣ", "cun"], ["ㄘㄨㄛ", "cuo"], ["ㄉㄧㄚ", "dia"], - ["ㄉㄧㄝ", "die"], ["ㄉㄧㄡ", "diu"], ["ㄉㄨㄟ", "dui"], ["ㄉㄨㄣ", "dun"], ["ㄉㄨㄛ", "duo"], ["ㄍㄨㄚ", "gua"], ["ㄍㄨㄜ", "gue"], - ["ㄍㄨㄟ", "gui"], ["ㄍㄨㄣ", "gun"], ["ㄍㄨㄛ", "guo"], ["ㄏㄨㄚ", "hua"], ["ㄏㄨㄟ", "hui"], ["ㄏㄨㄣ", "hun"], ["ㄏㄨㄛ", "huo"], - ["ㄐㄧㄚ", "jia"], ["ㄐㄧㄝ", "jie"], ["ㄐㄧㄣ", "jin"], ["ㄐㄧㄡ", "jiu"], ["ㄐㄩㄝ", "jue"], ["ㄎㄨㄚ", "kua"], ["ㄎㄨㄟ", "kui"], - ["ㄎㄨㄣ", "kun"], ["ㄎㄨㄛ", "kuo"], ["ㄌㄧㄚ", "lia"], ["ㄌㄧㄝ", "lie"], ["ㄌㄧㄣ", "lin"], ["ㄌㄧㄡ", "liu"], ["ㄌㄨㄣ", "lun"], - ["ㄌㄨㄛ", "luo"], ["ㄌㄩㄝ", "lve"], ["ㄇㄧㄝ", "mie"], ["ㄇㄧㄣ", "min"], ["ㄇㄧㄡ", "miu"], ["ㄋㄧㄝ", "nie"], ["ㄋㄧㄣ", "nin"], - ["ㄋㄧㄡ", "niu"], ["ㄋㄨㄟ", "nui"], ["ㄋㄨㄣ", "nun"], ["ㄋㄨㄛ", "nuo"], ["ㄋㄩㄝ", "nve"], ["ㄆㄧㄚ", "pia"], ["ㄆㄧㄝ", "pie"], - ["ㄆㄧㄣ", "pin"], ["ㄑㄧㄚ", "qia"], ["ㄑㄧㄝ", "qie"], ["ㄑㄧㄣ", "qin"], ["ㄑㄧㄡ", "qiu"], ["ㄑㄩㄝ", "que"], ["ㄑㄩㄣ", "qun"], - ["ㄖㄨㄟ", "rui"], ["ㄖㄨㄣ", "run"], ["ㄖㄨㄛ", "ruo"], ["ㄙㄨㄟ", "sui"], ["ㄙㄨㄣ", "sun"], ["ㄙㄨㄛ", "suo"], ["ㄊㄧㄝ", "tie"], - ["ㄊㄨㄟ", "tui"], ["ㄊㄨㄣ", "tun"], ["ㄊㄨㄛ", "tuo"], ["ㄒㄧㄚ", "xia"], ["ㄒㄧㄝ", "xie"], ["ㄒㄧㄣ", "xin"], ["ㄒㄧㄡ", "xiu"], - ["ㄒㄩㄝ", "xue"], ["ㄒㄩㄣ", "xun"], ["ㄗㄨㄟ", "zui"], ["ㄗㄨㄣ", "zun"], ["ㄗㄨㄛ", "zuo"], ["ㄘㄟ", "cei"], ["ㄔㄤ", "chang"], - ["ㄔㄥ", "cheng"], ["ㄕㄤ", "shang"], ["ㄕㄥ", "sheng"], ["ㄓㄤ", "zhang"], ["ㄓㄥ", "zheng"], ["ㄅㄤ", "bang"], - ["ㄅㄥ", "beng"], ["ㄘㄤ", "cang"], ["ㄘㄥ", "ceng"], ["ㄔㄞ", "chai"], ["ㄔㄢ", "chan"], ["ㄔㄠ", "chao"], ["ㄔㄣ", "chen"], - ["ㄔㄡ", "chou"], ["ㄉㄤ", "dang"], ["ㄉㄥ", "deng"], ["ㄈㄤ", "fang"], ["ㄈㄥ", "feng"], ["ㄍㄤ", "gang"], ["ㄍㄥ", "geng"], - ["ㄏㄤ", "hang"], ["ㄏㄥ", "heng"], ["ㄎㄤ", "kang"], ["ㄎㄥ", "keng"], ["ㄌㄤ", "lang"], ["ㄌㄥ", "leng"], ["ㄇㄤ", "mang"], - ["ㄇㄥ", "meng"], ["ㄋㄤ", "nang"], ["ㄋㄥ", "neng"], ["ㄆㄤ", "pang"], ["ㄆㄥ", "peng"], ["ㄖㄤ", "rang"], ["ㄖㄥ", "reng"], - ["ㄙㄤ", "sang"], ["ㄙㄥ", "seng"], ["ㄕㄞ", "shai"], ["ㄕㄢ", "shan"], ["ㄕㄠ", "shao"], ["ㄕㄟ", "shei"], ["ㄕㄣ", "shen"], - ["ㄕㄡ", "shou"], ["ㄊㄤ", "tang"], ["ㄊㄥ", "teng"], ["ㄨㄤ", "wang"], ["ㄨㄥ", "weng"], ["ㄧㄤ", "yang"], ["ㄧㄥ", "ying"], - ["ㄩㄥ", "yong"], ["ㄩㄢ", "yuan"], ["ㄗㄤ", "zang"], ["ㄗㄥ", "zeng"], ["ㄓㄞ", "zhai"], ["ㄓㄢ", "zhan"], ["ㄓㄠ", "zhao"], - ["ㄓㄟ", "zhei"], ["ㄓㄣ", "zhen"], ["ㄓㄡ", "zhou"], ["ㄅㄞ", "bai"], ["ㄅㄢ", "ban"], ["ㄅㄠ", "bao"], ["ㄅㄟ", "bei"], - ["ㄅㄣ", "ben"], ["ㄘㄞ", "cai"], ["ㄘㄢ", "can"], ["ㄘㄠ", "cao"], ["ㄘㄣ", "cen"], ["ㄔㄚ", "cha"], ["ㄔㄜ", "che"], - ["ㄔㄨ", "chu"], ["ㄘㄡ", "cou"], ["ㄉㄞ", "dai"], ["ㄉㄢ", "dan"], ["ㄉㄠ", "dao"], ["ㄉㄟ", "dei"], ["ㄉㄣ", "den"], - ["ㄉㄡ", "dou"], ["ㄈㄢ", "fan"], ["ㄈㄟ", "fei"], ["ㄈㄣ", "fen"], ["ㄈㄡ", "fou"], ["ㄍㄞ", "gai"], ["ㄍㄢ", "gan"], - ["ㄍㄠ", "gao"], ["ㄍㄟ", "gei"], ["ㄍㄣ", "gen"], ["ㄍㄡ", "gou"], ["ㄏㄞ", "hai"], ["ㄏㄢ", "han"], ["ㄏㄠ", "hao"], - ["ㄏㄟ", "hei"], ["ㄏㄣ", "hen"], ["ㄏㄡ", "hou"], ["ㄎㄞ", "kai"], ["ㄎㄢ", "kan"], ["ㄎㄠ", "kao"], ["ㄎㄣ", "ken"], - ["ㄎㄡ", "kou"], ["ㄌㄞ", "lai"], ["ㄌㄢ", "lan"], ["ㄌㄠ", "lao"], ["ㄌㄟ", "lei"], ["ㄌㄡ", "lou"], ["ㄇㄞ", "mai"], - ["ㄇㄢ", "man"], ["ㄇㄠ", "mao"], ["ㄇㄟ", "mei"], ["ㄇㄣ", "men"], ["ㄇㄡ", "mou"], ["ㄋㄞ", "nai"], ["ㄋㄢ", "nan"], - ["ㄋㄠ", "nao"], ["ㄋㄟ", "nei"], ["ㄋㄣ", "nen"], ["ㄋㄡ", "nou"], ["ㄆㄞ", "pai"], ["ㄆㄢ", "pan"], ["ㄆㄠ", "pao"], - ["ㄆㄟ", "pei"], ["ㄆㄣ", "pen"], ["ㄆㄡ", "pou"], ["ㄖㄢ", "ran"], ["ㄖㄠ", "rao"], ["ㄖㄣ", "ren"], ["ㄖㄡ", "rou"], - ["ㄙㄞ", "sai"], ["ㄙㄢ", "san"], ["ㄙㄠ", "sao"], ["ㄙㄟ", "sei"], ["ㄙㄣ", "sen"], ["ㄕㄚ", "sha"], ["ㄕㄜ", "she"], - ["ㄕㄨ", "shu"], ["ㄙㄡ", "sou"], ["ㄊㄞ", "tai"], ["ㄊㄢ", "tan"], ["ㄊㄠ", "tao"], ["ㄊㄡ", "tou"], ["ㄨㄞ", "wai"], - ["ㄨㄢ", "wan"], ["ㄨㄟ", "wei"], ["ㄨㄣ", "wen"], ["ㄧㄞ", "yai"], ["ㄧㄢ", "yan"], ["ㄧㄠ", "yao"], ["ㄧㄣ", "yin"], - ["ㄧㄡ", "you"], ["ㄩㄝ", "yue"], ["ㄩㄣ", "yun"], ["ㄗㄞ", "zai"], ["ㄗㄢ", "zan"], ["ㄗㄠ", "zao"], ["ㄗㄟ", "zei"], - ["ㄗㄣ", "zen"], ["ㄓㄚ", "zha"], ["ㄓㄜ", "zhe"], ["ㄓㄨ", "zhu"], ["ㄗㄡ", "zou"], ["ㄅㄚ", "ba"], ["ㄅㄧ", "bi"], - ["ㄅㄛ", "bo"], ["ㄅㄨ", "bu"], ["ㄘㄚ", "ca"], ["ㄘㄜ", "ce"], ["ㄘㄨ", "cu"], ["ㄉㄚ", "da"], ["ㄉㄜ", "de"], ["ㄉㄧ", "di"], - ["ㄉㄨ", "du"], ["ㄈㄚ", "fa"], ["ㄈㄛ", "fo"], ["ㄈㄨ", "fu"], ["ㄍㄚ", "ga"], ["ㄍㄜ", "ge"], ["ㄍㄧ", "gi"], ["ㄍㄨ", "gu"], - ["ㄏㄚ", "ha"], ["ㄏㄜ", "he"], ["ㄏㄨ", "hu"], ["ㄐㄧ", "ji"], ["ㄐㄩ", "ju"], ["ㄎㄚ", "ka"], ["ㄎㄜ", "ke"], ["ㄎㄨ", "ku"], - ["ㄌㄚ", "la"], ["ㄌㄜ", "le"], ["ㄌㄧ", "li"], ["ㄌㄛ", "lo"], ["ㄌㄨ", "lu"], ["ㄌㄩ", "lv"], ["ㄇㄚ", "ma"], ["ㄇㄜ", "me"], - ["ㄇㄧ", "mi"], ["ㄇㄛ", "mo"], ["ㄇㄨ", "mu"], ["ㄋㄚ", "na"], ["ㄋㄜ", "ne"], ["ㄋㄧ", "ni"], ["ㄋㄨ", "nu"], ["ㄋㄩ", "nv"], - ["ㄆㄚ", "pa"], ["ㄆㄧ", "pi"], ["ㄆㄛ", "po"], ["ㄆㄨ", "pu"], ["ㄑㄧ", "qi"], ["ㄑㄩ", "qu"], ["ㄖㄜ", "re"], ["ㄖㄨ", "ru"], - ["ㄙㄚ", "sa"], ["ㄙㄜ", "se"], ["ㄙㄨ", "su"], ["ㄊㄚ", "ta"], ["ㄊㄜ", "te"], ["ㄊㄧ", "ti"], ["ㄊㄨ", "tu"], ["ㄨㄚ", "wa"], - ["ㄨㄛ", "wo"], ["ㄒㄧ", "xi"], ["ㄒㄩ", "xu"], ["ㄧㄚ", "ya"], ["ㄧㄝ", "ye"], ["ㄧㄛ", "yo"], ["ㄗㄚ", "za"], ["ㄗㄜ", "ze"], - ["ㄗㄨ", "zu"], ["ㄅ", "b"], ["ㄆ", "p"], ["ㄇ", "m"], ["ㄈ", "f"], ["ㄉ", "d"], ["ㄊ", "t"], ["ㄋ", "n"], - ["ㄌ", "l"], ["ㄍ", "g"], ["ㄎ", "k"], ["ㄏ", "h"], ["ㄐ", "j"], ["ㄑ", "q"], ["ㄒ", "x"], ["ㄓ", "zhi"], - ["ㄔ", "chi"], ["ㄕ", "shi"], ["ㄖ", "ri"], ["ㄗ", "zi"], ["ㄘ", "ci"], ["ㄙ", "si"], ["ㄚ", "a"], ["ㄛ", "o"], ["ㄜ", "e"], - ["ㄝ", "eh"], ["ㄞ", "ai"], ["ㄟ", "ei"], ["ㄠ", "ao"], ["ㄡ", "ou"], ["ㄢ", "an"], ["ㄣ", "en"], ["ㄤ", "ang"], - ["ㄥ", "eng"], ["ㄦ", "er"], ["ㄧ", "yi"], ["ㄨ", "wu"], ["ㄩ", "yu"], + [" ", "1"], ["ˊ", "2"], ["ˇ", "3"], ["ˋ", "4"], ["˙", "5"], + + ["ㄅㄧㄝ", "bie"], ["ㄅㄧㄠ", "biao"], ["ㄅㄧㄢ", "bian"], ["ㄅㄧㄣ", "bin"], ["ㄅㄧㄥ", "bing"], ["ㄆㄧㄚ", "pia"], ["ㄆㄧㄝ", "pie"], + ["ㄆㄧㄠ", "piao"], ["ㄆㄧㄢ", "pian"], ["ㄆㄧㄣ", "pin"], ["ㄆㄧㄥ", "ping"], ["ㄇㄧㄝ", "mie"], ["ㄇㄧㄠ", "miao"], ["ㄇㄧㄡ", "miu"], + ["ㄇㄧㄢ", "mian"], ["ㄇㄧㄣ", "min"], ["ㄇㄧㄥ", "ming"], ["ㄈㄧㄠ", "fiao"], ["ㄈㄨㄥ", "fong"], ["ㄉㄧㄚ", "dia"], ["ㄉㄧㄝ", "die"], + ["ㄉㄧㄠ", "diao"], ["ㄉㄧㄡ", "diu"], ["ㄉㄧㄢ", "dian"], ["ㄉㄧㄥ", "ding"], ["ㄉㄨㄛ", "duo"], ["ㄉㄨㄟ", "dui"], ["ㄉㄨㄢ", "duan"], + ["ㄉㄨㄣ", "dun"], ["ㄉㄨㄥ", "dong"], ["ㄊㄧㄝ", "tie"], ["ㄊㄧㄠ", "tiao"], ["ㄊㄧㄢ", "tian"], ["ㄊㄧㄥ", "ting"], ["ㄊㄨㄛ", "tuo"], + ["ㄊㄨㄟ", "tui"], ["ㄊㄨㄢ", "tuan"], ["ㄊㄨㄣ", "tun"], ["ㄊㄨㄥ", "tong"], ["ㄋㄧㄝ", "nie"], ["ㄋㄧㄠ", "niao"], ["ㄋㄧㄡ", "niu"], + ["ㄋㄧㄢ", "nian"], ["ㄋㄧㄣ", "nin"], ["ㄋㄧㄤ", "niang"], ["ㄋㄧㄥ", "ning"], ["ㄋㄨㄛ", "nuo"], ["ㄋㄨㄟ", "nui"], + ["ㄋㄨㄢ", "nuan"], ["ㄋㄨㄣ", "nun"], ["ㄋㄨㄥ", "nong"], ["ㄋㄩㄝ", "nve"], ["ㄌㄧㄚ", "lia"], ["ㄌㄧㄝ", "lie"], ["ㄌㄧㄠ", "liao"], + ["ㄌㄧㄡ", "liu"], ["ㄌㄧㄢ", "lian"], ["ㄌㄧㄣ", "lin"], ["ㄌㄧㄤ", "liang"], ["ㄌㄧㄥ", "ling"], ["ㄌㄨㄛ", "luo"], + ["ㄌㄨㄢ", "luan"], ["ㄌㄨㄣ", "lun"], ["ㄌㄨㄥ", "long"], ["ㄌㄩㄝ", "lve"], ["ㄌㄩㄢ", "lvan"], ["ㄍㄧㄠ", "giao"], ["ㄍㄧㄣ", "gin"], + ["ㄍㄨㄚ", "gua"], ["ㄍㄨㄛ", "guo"], ["ㄍㄨㄜ", "gue"], ["ㄍㄨㄞ", "guai"], ["ㄍㄨㄟ", "gui"], ["ㄍㄨㄢ", "guan"], ["ㄍㄨㄣ", "gun"], + ["ㄍㄨㄤ", "guang"], ["ㄍㄨㄥ", "gong"], ["ㄎㄧㄡ", "kiu"], ["ㄎㄧㄤ", "kiang"], ["ㄎㄨㄚ", "kua"], ["ㄎㄨㄛ", "kuo"], + ["ㄎㄨㄞ", "kuai"], ["ㄎㄨㄟ", "kui"], ["ㄎㄨㄢ", "kuan"], ["ㄎㄨㄣ", "kun"], ["ㄎㄨㄤ", "kuang"], ["ㄎㄨㄥ", "kong"], + ["ㄏㄨㄚ", "hua"], ["ㄏㄨㄛ", "huo"], ["ㄏㄨㄞ", "huai"], ["ㄏㄨㄟ", "hui"], ["ㄏㄨㄢ", "huan"], ["ㄏㄨㄣ", "hun"], ["ㄏㄨㄤ", "huang"], + ["ㄏㄨㄥ", "hong"], ["ㄐㄧㄚ", "jia"], ["ㄐㄧㄝ", "jie"], ["ㄐㄧㄠ", "jiao"], ["ㄐㄧㄡ", "jiu"], ["ㄐㄧㄢ", "jian"], ["ㄐㄧㄣ", "jin"], + ["ㄐㄧㄤ", "jiang"], ["ㄐㄧㄥ", "jing"], ["ㄐㄩㄝ", "jue"], ["ㄐㄩㄢ", "juan"], ["ㄐㄩㄣ", "jun"], ["ㄐㄩㄥ", "jiong"], + ["ㄑㄧㄚ", "qia"], ["ㄑㄧㄝ", "qie"], ["ㄑㄧㄠ", "qiao"], ["ㄑㄧㄡ", "qiu"], ["ㄑㄧㄢ", "qian"], ["ㄑㄧㄣ", "qin"], ["ㄑㄧㄤ", "qiang"], + ["ㄑㄧㄥ", "qing"], ["ㄑㄩㄝ", "que"], ["ㄑㄩㄢ", "quan"], ["ㄑㄩㄣ", "qun"], ["ㄑㄩㄥ", "qiong"], ["ㄒㄧㄚ", "xia"], ["ㄒㄧㄝ", "xie"], + ["ㄒㄧㄠ", "xiao"], ["ㄒㄧㄡ", "xiu"], ["ㄒㄧㄢ", "xian"], ["ㄒㄧㄣ", "xin"], ["ㄒㄧㄤ", "xiang"], ["ㄒㄧㄥ", "xing"], + ["ㄒㄩㄝ", "xue"], ["ㄒㄩㄢ", "xuan"], ["ㄒㄩㄣ", "xun"], ["ㄒㄩㄥ", "xiong"], ["ㄓㄨㄚ", "zhua"], ["ㄓㄨㄛ", "zhuo"], + ["ㄓㄨㄞ", "zhuai"], ["ㄓㄨㄟ", "zhui"], ["ㄓㄨㄢ", "zhuan"], ["ㄓㄨㄣ", "zhun"], ["ㄓㄨㄤ", "zhuang"], ["ㄓㄨㄥ", "zhong"], + ["ㄔㄨㄚ", "chua"], ["ㄔㄨㄛ", "chuo"], ["ㄔㄨㄞ", "chuai"], ["ㄔㄨㄟ", "chui"], ["ㄔㄨㄢ", "chuan"], ["ㄔㄨㄣ", "chun"], + ["ㄔㄨㄤ", "chuang"], ["ㄔㄨㄥ", "chong"], ["ㄕㄨㄚ", "shua"], ["ㄕㄨㄛ", "shuo"], ["ㄕㄨㄞ", "shuai"], ["ㄕㄨㄟ", "shui"], + ["ㄕㄨㄢ", "shuan"], ["ㄕㄨㄣ", "shun"], ["ㄕㄨㄤ", "shuang"], ["ㄖㄨㄛ", "ruo"], ["ㄖㄨㄟ", "rui"], ["ㄖㄨㄢ", "ruan"], + ["ㄖㄨㄣ", "run"], ["ㄖㄨㄥ", "rong"], ["ㄗㄨㄛ", "zuo"], ["ㄗㄨㄟ", "zui"], ["ㄗㄨㄢ", "zuan"], ["ㄗㄨㄣ", "zun"], ["ㄗㄨㄥ", "zong"], + ["ㄘㄨㄛ", "cuo"], ["ㄘㄨㄟ", "cui"], ["ㄘㄨㄢ", "cuan"], ["ㄘㄨㄣ", "cun"], ["ㄘㄨㄥ", "cong"], ["ㄙㄨㄛ", "suo"], ["ㄙㄨㄟ", "sui"], + ["ㄙㄨㄢ", "suan"], ["ㄙㄨㄣ", "sun"], ["ㄙㄨㄥ", "song"], + + ["ㄅㄚ", "ba"], ["ㄅㄛ", "bo"], ["ㄅㄞ", "bai"], ["ㄅㄟ", "bei"], ["ㄅㄠ", "bao"], ["ㄅㄢ", "ban"], ["ㄅㄣ", "ben"], + ["ㄅㄤ", "bang"], ["ㄅㄥ", "beng"], ["ㄅㄧ", "bi"], ["ㄅㄨ", "bu"], ["ㄆㄚ", "pa"], ["ㄆㄛ", "po"], ["ㄆㄞ", "pai"], + ["ㄆㄟ", "pei"], ["ㄆㄠ", "pao"], ["ㄆㄡ", "pou"], ["ㄆㄢ", "pan"], ["ㄆㄣ", "pen"], ["ㄆㄤ", "pang"], ["ㄆㄥ", "peng"], + ["ㄆㄧ", "pi"], ["ㄆㄨ", "pu"], ["ㄇㄚ", "ma"], ["ㄇㄛ", "mo"], ["ㄇㄜ", "me"], ["ㄇㄞ", "mai"], ["ㄇㄟ", "mei"], ["ㄇㄠ", "mao"], + ["ㄇㄡ", "mou"], ["ㄇㄢ", "man"], ["ㄇㄣ", "men"], ["ㄇㄤ", "mang"], ["ㄇㄥ", "meng"], ["ㄇㄧ", "mi"], ["ㄇㄨ", "mu"], + ["ㄈㄚ", "fa"], ["ㄈㄛ", "fo"], ["ㄈㄟ", "fei"], ["ㄈㄡ", "fou"], ["ㄈㄢ", "fan"], ["ㄈㄣ", "fen"], ["ㄈㄤ", "fang"], + ["ㄈㄥ", "feng"], ["ㄈㄨ", "fu"], ["ㄉㄚ", "da"], ["ㄉㄜ", "de"], ["ㄉㄞ", "dai"], ["ㄉㄟ", "dei"], ["ㄉㄠ", "dao"], + ["ㄉㄡ", "dou"], ["ㄉㄢ", "dan"], ["ㄉㄣ", "den"], ["ㄉㄤ", "dang"], ["ㄉㄥ", "deng"], ["ㄉㄧ", "di"], ["ㄉㄨ", "du"], + ["ㄊㄚ", "ta"], ["ㄊㄜ", "te"], ["ㄊㄞ", "tai"], ["ㄊㄠ", "tao"], ["ㄊㄡ", "tou"], ["ㄊㄢ", "tan"], ["ㄊㄤ", "tang"], + ["ㄊㄥ", "teng"], ["ㄊㄧ", "ti"], ["ㄊㄨ", "tu"], ["ㄋㄚ", "na"], ["ㄋㄜ", "ne"], ["ㄋㄞ", "nai"], ["ㄋㄟ", "nei"], + ["ㄋㄠ", "nao"], ["ㄋㄡ", "nou"], ["ㄋㄢ", "nan"], ["ㄋㄣ", "nen"], ["ㄋㄤ", "nang"], ["ㄋㄥ", "neng"], ["ㄋㄧ", "ni"], + ["ㄋㄨ", "nu"], ["ㄋㄩ", "nv"], ["ㄌㄚ", "la"], ["ㄌㄛ", "lo"], ["ㄌㄜ", "le"], ["ㄌㄞ", "lai"], ["ㄌㄟ", "lei"], ["ㄌㄠ", "lao"], + ["ㄌㄡ", "lou"], ["ㄌㄢ", "lan"], ["ㄌㄤ", "lang"], ["ㄌㄥ", "leng"], ["ㄌㄧ", "li"], ["ㄌㄨ", "lu"], ["ㄌㄩ", "lv"], + ["ㄍㄚ", "ga"], ["ㄍㄜ", "ge"], ["ㄍㄞ", "gai"], ["ㄍㄟ", "gei"], ["ㄍㄠ", "gao"], ["ㄍㄡ", "gou"], ["ㄍㄢ", "gan"], + ["ㄍㄣ", "gen"], ["ㄍㄤ", "gang"], ["ㄍㄥ", "geng"], ["ㄍㄧ", "gi"], ["ㄍㄨ", "gu"], ["ㄎㄚ", "ka"], ["ㄎㄜ", "ke"], + ["ㄎㄞ", "kai"], ["ㄎㄠ", "kao"], ["ㄎㄡ", "kou"], ["ㄎㄢ", "kan"], ["ㄎㄣ", "ken"], ["ㄎㄤ", "kang"], ["ㄎㄥ", "keng"], + ["ㄎㄨ", "ku"], ["ㄏㄚ", "ha"], ["ㄏㄜ", "he"], ["ㄏㄞ", "hai"], ["ㄏㄟ", "hei"], ["ㄏㄠ", "hao"], ["ㄏㄡ", "hou"], + ["ㄏㄢ", "han"], ["ㄏㄣ", "hen"], ["ㄏㄤ", "hang"], ["ㄏㄥ", "heng"], ["ㄏㄨ", "hu"], ["ㄐㄧ", "ji"], ["ㄐㄩ", "ju"], + ["ㄑㄧ", "qi"], ["ㄑㄩ", "qu"], ["ㄒㄧ", "xi"], ["ㄒㄩ", "xu"], ["ㄓㄚ", "zha"], ["ㄓㄜ", "zhe"], ["ㄓㄞ", "zhai"], + ["ㄓㄟ", "zhei"], ["ㄓㄠ", "zhao"], ["ㄓㄡ", "zhou"], ["ㄓㄢ", "zhan"], ["ㄓㄣ", "zhen"], ["ㄓㄤ", "zhang"], ["ㄓㄥ", "zheng"], + ["ㄓㄨ", "zhu"], ["ㄔㄚ", "cha"], ["ㄔㄜ", "che"], ["ㄔㄞ", "chai"], ["ㄔㄠ", "chao"], ["ㄔㄡ", "chou"], ["ㄔㄢ", "chan"], + ["ㄔㄣ", "chen"], ["ㄔㄤ", "chang"], ["ㄔㄥ", "cheng"], ["ㄔㄨ", "chu"], ["ㄕㄚ", "sha"], ["ㄕㄜ", "she"], ["ㄕㄞ", "shai"], + ["ㄕㄟ", "shei"], ["ㄕㄠ", "shao"], ["ㄕㄡ", "shou"], ["ㄕㄢ", "shan"], ["ㄕㄣ", "shen"], ["ㄕㄤ", "shang"], ["ㄕㄥ", "sheng"], + ["ㄕㄨ", "shu"], ["ㄖㄜ", "re"], ["ㄖㄠ", "rao"], ["ㄖㄡ", "rou"], ["ㄖㄢ", "ran"], ["ㄖㄣ", "ren"], ["ㄖㄤ", "rang"], + ["ㄖㄥ", "reng"], ["ㄖㄨ", "ru"], ["ㄗㄚ", "za"], ["ㄗㄜ", "ze"], ["ㄗㄞ", "zai"], ["ㄗㄟ", "zei"], ["ㄗㄠ", "zao"], + ["ㄗㄡ", "zou"], ["ㄗㄢ", "zan"], ["ㄗㄣ", "zen"], ["ㄗㄤ", "zang"], ["ㄗㄥ", "zeng"], ["ㄗㄨ", "zu"], ["ㄘㄚ", "ca"], + ["ㄘㄜ", "ce"], ["ㄘㄞ", "cai"], ["ㄘㄟ", "cei"], ["ㄘㄠ", "cao"], ["ㄘㄡ", "cou"], ["ㄘㄢ", "can"], ["ㄘㄣ", "cen"], + ["ㄘㄤ", "cang"], ["ㄘㄥ", "ceng"], ["ㄘㄨ", "cu"], ["ㄙㄚ", "sa"], ["ㄙㄜ", "se"], ["ㄙㄞ", "sai"], ["ㄙㄟ", "sei"], + ["ㄙㄠ", "sao"], ["ㄙㄡ", "sou"], ["ㄙㄢ", "san"], ["ㄙㄣ", "sen"], ["ㄙㄤ", "sang"], ["ㄙㄥ", "seng"], ["ㄙㄨ", "su"], + ["ㄧㄚ", "ya"], ["ㄧㄛ", "yo"], ["ㄧㄝ", "ye"], ["ㄧㄞ", "yai"], ["ㄧㄠ", "yao"], ["ㄧㄡ", "you"], ["ㄧㄢ", "yan"], + ["ㄧㄣ", "yin"], ["ㄧㄤ", "yang"], ["ㄧㄥ", "ying"], ["ㄨㄚ", "wa"], ["ㄨㄛ", "wo"], ["ㄨㄞ", "wai"], ["ㄨㄟ", "wei"], + ["ㄨㄢ", "wan"], ["ㄨㄣ", "wen"], ["ㄨㄤ", "wang"], ["ㄨㄥ", "weng"], ["ㄩㄝ", "yue"], ["ㄩㄢ", "yuan"], ["ㄩㄣ", "yun"], + ["ㄩㄥ", "yong"], + + ["ㄅ", "b"], ["ㄆ", "p"], ["ㄇ", "m"], ["ㄈ", "f"], ["ㄉ", "d"], ["ㄊ", "t"], ["ㄋ", "n"], + ["ㄌ", "l"], ["ㄍ", "g"], ["ㄎ", "k"], ["ㄏ", "h"], ["ㄐ", "j"], ["ㄑ", "q"], ["ㄒ", "x"], ["ㄓ", "zhi"], ["ㄔ", "chi"], + ["ㄕ", "shi"], ["ㄖ", "ri"], ["ㄗ", "zi"], ["ㄘ", "ci"], ["ㄙ", "si"], ["ㄚ", "a"], ["ㄛ", "o"], ["ㄜ", "e"], ["ㄝ", "eh"], + ["ㄞ", "ai"], ["ㄟ", "ei"], ["ㄠ", "ao"], ["ㄡ", "ou"], ["ㄢ", "an"], ["ㄣ", "en"], ["ㄤ", "ang"], ["ㄥ", "eng"], + ["ㄦ", "er"], ["ㄧ", "yi"], ["ㄨ", "wu"], ["ㄩ", "yu"], ] /// 漢語拼音韻母轉換對照表資料貯存專用佇列 static let arrHanyuPinyinTextbookStyleConversionTable = [ // 排序很重要。先處理最長的,再處理短的。不然會出亂子。 ["iang1", "iāng"], ["iang2", "iáng"], ["iang3", "iǎng"], ["iang4", "iàng"], ["iong1", "iōng"], ["iong2", "ióng"], ["iong3", "iǒng"], ["iong4", "iòng"], ["uang1", "uāng"], ["uang2", "uáng"], ["uang3", "uǎng"], ["uang4", "uàng"], - ["uang5", "uang"], ["ang1", "āng"], ["ang2", "áng"], ["ang3", "ǎng"], ["ang4", "àng"], ["ang5", "ang"], - ["eng1", "ēng"], ["eng2", "éng"], ["eng3", "ěng"], ["eng4", "èng"], ["ian1", "iān"], ["ian2", "ián"], - ["ian3", "iǎn"], ["ian4", "iàn"], ["iao1", "iāo"], ["iao2", "iáo"], ["iao3", "iǎo"], ["iao4", "iào"], - ["ing1", "īng"], ["ing2", "íng"], ["ing3", "ǐng"], ["ing4", "ìng"], ["ong1", "ōng"], ["ong2", "óng"], - ["ong3", "ǒng"], ["ong4", "òng"], ["uai1", "uāi"], ["uai2", "uái"], ["uai3", "uǎi"], ["uai4", "uài"], - ["uan1", "uān"], ["uan2", "uán"], ["uan3", "uǎn"], ["uan4", "uàn"], ["van2", "üán"], ["van3", "üǎn"], + ["uang5", "uang"], + + ["ang1", "āng"], ["ang2", "áng"], ["ang3", "ǎng"], ["ang4", "àng"], ["ang5", "ang"], ["eng1", "ēng"], + ["eng2", "éng"], ["eng3", "ěng"], ["eng4", "èng"], ["ian1", "iān"], ["ian2", "ián"], ["ian3", "iǎn"], + ["ian4", "iàn"], ["iao1", "iāo"], ["iao2", "iáo"], ["iao3", "iǎo"], ["iao4", "iào"], ["ing1", "īng"], + ["ing2", "íng"], ["ing3", "ǐng"], ["ing4", "ìng"], ["ong1", "ōng"], ["ong2", "óng"], ["ong3", "ǒng"], + ["ong4", "òng"], ["uai1", "uāi"], ["uai2", "uái"], ["uai3", "uǎi"], ["uai4", "uài"], ["uan1", "uān"], + ["uan2", "uán"], ["uan3", "uǎn"], ["uan4", "uàn"], ["van2", "üán"], ["van3", "üǎn"], + ["ai1", "āi"], ["ai2", "ái"], ["ai3", "ǎi"], ["ai4", "ài"], ["ai5", "ai"], ["an1", "ān"], ["an2", "án"], ["an3", "ǎn"], ["an4", "àn"], ["ao1", "āo"], ["ao2", "áo"], ["ao3", "ǎo"], ["ao4", "ào"], ["ao5", "ao"], ["eh2", "ế"], ["eh3", "êˇ"], ["eh4", "ề"], ["eh5", "ê"], ["ei1", "ēi"], ["ei2", "éi"], ["ei3", "ěi"], @@ -690,17 +930,312 @@ public struct Tekkon { ["ua2", "uá"], ["ua3", "uǎ"], ["ua4", "uà"], ["ue1", "uē"], ["ue2", "ué"], ["ue3", "uě"], ["ue4", "uè"], ["ui1", "uī"], ["ui2", "uí"], ["ui3", "uǐ"], ["ui4", "uì"], ["un1", "ūn"], ["un2", "ún"], ["un3", "ǔn"], ["un4", "ùn"], ["uo1", "uō"], ["uo2", "uó"], ["uo3", "uǒ"], ["uo4", "uò"], ["uo5", "uo"], ["ve1", "üē"], - ["ve3", "üě"], ["ve4", "üè"], ["a1", "ā"], ["a2", "á"], ["a3", "ǎ"], ["a4", "à"], ["a5", "a"], ["e1", "ē"], - ["e2", "é"], ["e3", "ě"], ["e4", "è"], ["e5", "e"], ["i1", "ī"], ["i2", "í"], ["i3", "ǐ"], ["i4", "ì"], - ["i5", "i"], ["o1", "ō"], ["o2", "ó"], ["o3", "ǒ"], ["o4", "ò"], ["o5", "o"], ["u1", "ū"], ["u2", "ú"], - ["u3", "ǔ"], ["u4", "ù"], ["v1", "ǖ"], ["v2", "ǘ"], ["v3", "ǚ"], ["v4", "ǜ"], + ["ve3", "üě"], ["ve4", "üè"], + + ["a1", "ā"], ["a2", "á"], ["a3", "ǎ"], ["a4", "à"], ["a5", "a"], ["e1", "ē"], ["e2", "é"], ["e3", "ě"], + ["e4", "è"], ["e5", "e"], ["i1", "ī"], ["i2", "í"], ["i3", "ǐ"], ["i4", "ì"], ["i5", "i"], ["o1", "ō"], + ["o2", "ó"], ["o3", "ǒ"], ["o4", "ò"], ["o5", "o"], ["u1", "ū"], ["u2", "ú"], ["u3", "ǔ"], ["u4", "ù"], + ["v1", "ǖ"], ["v2", "ǘ"], ["v3", "ǚ"], ["v4", "ǜ"], + ] + + // MARK: - Maps for Keyboard-to-Pinyin parsers + + /// 任何形式的拼音排列都會用到的陣列,用 Strings 反而省事一些。 + /// 這裡同時兼容大千注音的調號數字,所以也將 6、7 號數字鍵放在允許範圍內。 + static let mapArayuruPinyin: String = "abcdefghijklmnopqrstuvwxyz1234567 " + + /// 任何拼音都會用到的聲調鍵陣列 + static let mapArayuruPinyinIntonation: [String: String] = [ + "1": " ", "2": "ˊ", "3": "ˇ", "4": "ˋ", "5": "˙", "6": "ˊ", "7": "˙", " ": " ", + ] + /// 漢語拼音排列專用處理陣列 + static let mapHanyuPinyin: [String: String] = [ + "chuang": "ㄔㄨㄤ", "shuang": "ㄕㄨㄤ", "zhuang": "ㄓㄨㄤ", "chang": "ㄔㄤ", "cheng": "ㄔㄥ", "chong": "ㄔㄨㄥ", "chuai": "ㄔㄨㄞ", + "chuan": "ㄔㄨㄢ", "guang": "ㄍㄨㄤ", "huang": "ㄏㄨㄤ", "jiang": "ㄐㄧㄤ", "jiong": "ㄐㄩㄥ", "kiang": "ㄎㄧㄤ", "kuang": "ㄎㄨㄤ", + "liang": "ㄌㄧㄤ", "niang": "ㄋㄧㄤ", "qiang": "ㄑㄧㄤ", "qiong": "ㄑㄩㄥ", "shang": "ㄕㄤ", "sheng": "ㄕㄥ", "shuai": "ㄕㄨㄞ", + "shuan": "ㄕㄨㄢ", "xiang": "ㄒㄧㄤ", "xiong": "ㄒㄩㄥ", "zhang": "ㄓㄤ", "zheng": "ㄓㄥ", "zhong": "ㄓㄨㄥ", "zhuai": "ㄓㄨㄞ", + "zhuan": "ㄓㄨㄢ", "bang": "ㄅㄤ", "beng": "ㄅㄥ", "bian": "ㄅㄧㄢ", "biao": "ㄅㄧㄠ", "bing": "ㄅㄧㄥ", "cang": "ㄘㄤ", "ceng": "ㄘㄥ", + "chai": "ㄔㄞ", "chan": "ㄔㄢ", "chao": "ㄔㄠ", "chen": "ㄔㄣ", "chou": "ㄔㄡ", "chua": "ㄔㄨㄚ", "chui": "ㄔㄨㄟ", "chun": "ㄔㄨㄣ", + "chuo": "ㄔㄨㄛ", "cong": "ㄘㄨㄥ", "cuan": "ㄘㄨㄢ", "dang": "ㄉㄤ", "deng": "ㄉㄥ", "dian": "ㄉㄧㄢ", "diao": "ㄉㄧㄠ", + "ding": "ㄉㄧㄥ", "dong": "ㄉㄨㄥ", "duan": "ㄉㄨㄢ", "fang": "ㄈㄤ", "feng": "ㄈㄥ", "fiao": "ㄈㄧㄠ", "fong": "ㄈㄨㄥ", "gang": "ㄍㄤ", + "geng": "ㄍㄥ", "giao": "ㄍㄧㄠ", "gong": "ㄍㄨㄥ", "guai": "ㄍㄨㄞ", "guan": "ㄍㄨㄢ", "hang": "ㄏㄤ", "heng": "ㄏㄥ", "hong": "ㄏㄨㄥ", + "huai": "ㄏㄨㄞ", "huan": "ㄏㄨㄢ", "jian": "ㄐㄧㄢ", "jiao": "ㄐㄧㄠ", "jing": "ㄐㄧㄥ", "juan": "ㄐㄩㄢ", "kang": "ㄎㄤ", + "keng": "ㄎㄥ", "kong": "ㄎㄨㄥ", "kuai": "ㄎㄨㄞ", "kuan": "ㄎㄨㄢ", "lang": "ㄌㄤ", "leng": "ㄌㄥ", "lian": "ㄌㄧㄢ", "liao": "ㄌㄧㄠ", + "ling": "ㄌㄧㄥ", "long": "ㄌㄨㄥ", "luan": "ㄌㄨㄢ", "lvan": "ㄌㄩㄢ", "mang": "ㄇㄤ", "meng": "ㄇㄥ", "mian": "ㄇㄧㄢ", + "miao": "ㄇㄧㄠ", "ming": "ㄇㄧㄥ", "nang": "ㄋㄤ", "neng": "ㄋㄥ", "nian": "ㄋㄧㄢ", "niao": "ㄋㄧㄠ", "ning": "ㄋㄧㄥ", + "nong": "ㄋㄨㄥ", "nuan": "ㄋㄨㄢ", "pang": "ㄆㄤ", "peng": "ㄆㄥ", "pian": "ㄆㄧㄢ", "piao": "ㄆㄧㄠ", "ping": "ㄆㄧㄥ", + "qian": "ㄑㄧㄢ", "qiao": "ㄑㄧㄠ", "qing": "ㄑㄧㄥ", "quan": "ㄑㄩㄢ", "rang": "ㄖㄤ", "reng": "ㄖㄥ", "rong": "ㄖㄨㄥ", + "ruan": "ㄖㄨㄢ", "sang": "ㄙㄤ", "seng": "ㄙㄥ", "shai": "ㄕㄞ", "shan": "ㄕㄢ", "shao": "ㄕㄠ", "shei": "ㄕㄟ", "shen": "ㄕㄣ", + "shou": "ㄕㄡ", "shua": "ㄕㄨㄚ", "shui": "ㄕㄨㄟ", "shun": "ㄕㄨㄣ", "shuo": "ㄕㄨㄛ", "song": "ㄙㄨㄥ", "suan": "ㄙㄨㄢ", + "tang": "ㄊㄤ", "teng": "ㄊㄥ", "tian": "ㄊㄧㄢ", "tiao": "ㄊㄧㄠ", "ting": "ㄊㄧㄥ", "tong": "ㄊㄨㄥ", "tuan": "ㄊㄨㄢ", "wang": "ㄨㄤ", + "weng": "ㄨㄥ", "xian": "ㄒㄧㄢ", "xiao": "ㄒㄧㄠ", "xing": "ㄒㄧㄥ", "xuan": "ㄒㄩㄢ", "yang": "ㄧㄤ", "ying": "ㄧㄥ", "yong": "ㄩㄥ", + "yuan": "ㄩㄢ", "zang": "ㄗㄤ", "zeng": "ㄗㄥ", "zhai": "ㄓㄞ", "zhan": "ㄓㄢ", "zhao": "ㄓㄠ", "zhei": "ㄓㄟ", "zhen": "ㄓㄣ", + "zhou": "ㄓㄡ", "zhua": "ㄓㄨㄚ", "zhui": "ㄓㄨㄟ", "zhun": "ㄓㄨㄣ", "zhuo": "ㄓㄨㄛ", "zong": "ㄗㄨㄥ", "zuan": "ㄗㄨㄢ", + "jun": "ㄐㄩㄣ", "ang": "ㄤ", "bai": "ㄅㄞ", "ban": "ㄅㄢ", "bao": "ㄅㄠ", "bei": "ㄅㄟ", "ben": "ㄅㄣ", "bie": "ㄅㄧㄝ", + "bin": "ㄅㄧㄣ", "cai": "ㄘㄞ", "can": "ㄘㄢ", "cao": "ㄘㄠ", "cei": "ㄘㄟ", "cen": "ㄘㄣ", "cha": "ㄔㄚ", "che": "ㄔㄜ", "chi": "ㄔ", + "chu": "ㄔㄨ", "cou": "ㄘㄡ", "cui": "ㄘㄨㄟ", "cun": "ㄘㄨㄣ", "cuo": "ㄘㄨㄛ", "dai": "ㄉㄞ", "dan": "ㄉㄢ", "dao": "ㄉㄠ", + "dei": "ㄉㄟ", "den": "ㄉㄣ", "dia": "ㄉㄧㄚ", "die": "ㄉㄧㄝ", "diu": "ㄉㄧㄡ", "dou": "ㄉㄡ", "dui": "ㄉㄨㄟ", "dun": "ㄉㄨㄣ", + "duo": "ㄉㄨㄛ", "eng": "ㄥ", "fan": "ㄈㄢ", "fei": "ㄈㄟ", "fen": "ㄈㄣ", "fou": "ㄈㄡ", "gai": "ㄍㄞ", "gan": "ㄍㄢ", "gao": "ㄍㄠ", + "gei": "ㄍㄟ", "gin": "ㄍㄧㄣ", "gen": "ㄍㄣ", "gou": "ㄍㄡ", "gua": "ㄍㄨㄚ", "gue": "ㄍㄨㄜ", "gui": "ㄍㄨㄟ", "gun": "ㄍㄨㄣ", + "guo": "ㄍㄨㄛ", "hai": "ㄏㄞ", "han": "ㄏㄢ", "hao": "ㄏㄠ", "hei": "ㄏㄟ", "hen": "ㄏㄣ", "hou": "ㄏㄡ", "hua": "ㄏㄨㄚ", + "hui": "ㄏㄨㄟ", "hun": "ㄏㄨㄣ", "huo": "ㄏㄨㄛ", "jia": "ㄐㄧㄚ", "jie": "ㄐㄧㄝ", "jin": "ㄐㄧㄣ", "jiu": "ㄐㄧㄡ", "jue": "ㄐㄩㄝ", + "kai": "ㄎㄞ", "kan": "ㄎㄢ", "kao": "ㄎㄠ", "ken": "ㄎㄣ", "kiu": "ㄎㄧㄡ", "kou": "ㄎㄡ", "kua": "ㄎㄨㄚ", "kui": "ㄎㄨㄟ", + "kun": "ㄎㄨㄣ", "kuo": "ㄎㄨㄛ", "lai": "ㄌㄞ", "lan": "ㄌㄢ", "lao": "ㄌㄠ", "lei": "ㄌㄟ", "lia": "ㄌㄧㄚ", "lie": "ㄌㄧㄝ", + "lin": "ㄌㄧㄣ", "liu": "ㄌㄧㄡ", "lou": "ㄌㄡ", "lun": "ㄌㄨㄣ", "luo": "ㄌㄨㄛ", "lve": "ㄌㄩㄝ", "mai": "ㄇㄞ", "man": "ㄇㄢ", + "mao": "ㄇㄠ", "mei": "ㄇㄟ", "men": "ㄇㄣ", "mie": "ㄇㄧㄝ", "min": "ㄇㄧㄣ", "miu": "ㄇㄧㄡ", "mou": "ㄇㄡ", "nai": "ㄋㄞ", + "nan": "ㄋㄢ", "nao": "ㄋㄠ", "nei": "ㄋㄟ", "nen": "ㄋㄣ", "nie": "ㄋㄧㄝ", "nin": "ㄋㄧㄣ", "niu": "ㄋㄧㄡ", "nou": "ㄋㄡ", + "nui": "ㄋㄨㄟ", "nun": "ㄋㄨㄣ", "nuo": "ㄋㄨㄛ", "nve": "ㄋㄩㄝ", "pai": "ㄆㄞ", "pan": "ㄆㄢ", "pao": "ㄆㄠ", "pei": "ㄆㄟ", + "pen": "ㄆㄣ", "pia": "ㄆㄧㄚ", "pie": "ㄆㄧㄝ", "pin": "ㄆㄧㄣ", "pou": "ㄆㄡ", "qia": "ㄑㄧㄚ", "qie": "ㄑㄧㄝ", "qin": "ㄑㄧㄣ", + "qiu": "ㄑㄧㄡ", "que": "ㄑㄩㄝ", "qun": "ㄑㄩㄣ", "ran": "ㄖㄢ", "rao": "ㄖㄠ", "ren": "ㄖㄣ", "rou": "ㄖㄡ", "rui": "ㄖㄨㄟ", + "run": "ㄖㄨㄣ", "ruo": "ㄖㄨㄛ", "sai": "ㄙㄞ", "san": "ㄙㄢ", "sao": "ㄙㄠ", "sei": "ㄙㄟ", "sen": "ㄙㄣ", "sha": "ㄕㄚ", + "she": "ㄕㄜ", "shi": "ㄕ", "shu": "ㄕㄨ", "sou": "ㄙㄡ", "sui": "ㄙㄨㄟ", "sun": "ㄙㄨㄣ", "suo": "ㄙㄨㄛ", "tai": "ㄊㄞ", + "tan": "ㄊㄢ", "tao": "ㄊㄠ", "tie": "ㄊㄧㄝ", "tou": "ㄊㄡ", "tui": "ㄊㄨㄟ", "tun": "ㄊㄨㄣ", "tuo": "ㄊㄨㄛ", "wai": "ㄨㄞ", + "wan": "ㄨㄢ", "wei": "ㄨㄟ", "wen": "ㄨㄣ", "xia": "ㄒㄧㄚ", "xie": "ㄒㄧㄝ", "xin": "ㄒㄧㄣ", "xiu": "ㄒㄧㄡ", "xue": "ㄒㄩㄝ", + "xun": "ㄒㄩㄣ", "yai": "ㄧㄞ", "yan": "ㄧㄢ", "yao": "ㄧㄠ", "yin": "ㄧㄣ", "you": "ㄧㄡ", "yue": "ㄩㄝ", "yun": "ㄩㄣ", + "zai": "ㄗㄞ", "zan": "ㄗㄢ", "zao": "ㄗㄠ", "zei": "ㄗㄟ", "zen": "ㄗㄣ", "zha": "ㄓㄚ", "zhe": "ㄓㄜ", "zhi": "ㄓ", "zhu": "ㄓㄨ", + "zou": "ㄗㄡ", "zui": "ㄗㄨㄟ", "zun": "ㄗㄨㄣ", "zuo": "ㄗㄨㄛ", "ai": "ㄞ", "an": "ㄢ", "ao": "ㄠ", "ba": "ㄅㄚ", "bi": "ㄅㄧ", + "bo": "ㄅㄛ", "bu": "ㄅㄨ", "ca": "ㄘㄚ", "ce": "ㄘㄜ", "ci": "ㄘ", "cu": "ㄘㄨ", "da": "ㄉㄚ", "de": "ㄉㄜ", "di": "ㄉㄧ", + "du": "ㄉㄨ", "eh": "ㄝ", "ei": "ㄟ", "en": "ㄣ", "er": "ㄦ", "fa": "ㄈㄚ", "fo": "ㄈㄛ", "fu": "ㄈㄨ", "ga": "ㄍㄚ", "ge": "ㄍㄜ", + "gi": "ㄍㄧ", "gu": "ㄍㄨ", "ha": "ㄏㄚ", "he": "ㄏㄜ", "hu": "ㄏㄨ", "ji": "ㄐㄧ", "ju": "ㄐㄩ", "ka": "ㄎㄚ", "ke": "ㄎㄜ", + "ku": "ㄎㄨ", "la": "ㄌㄚ", "le": "ㄌㄜ", "li": "ㄌㄧ", "lo": "ㄌㄛ", "lu": "ㄌㄨ", "lv": "ㄌㄩ", "ma": "ㄇㄚ", "me": "ㄇㄜ", + "mi": "ㄇㄧ", "mo": "ㄇㄛ", "mu": "ㄇㄨ", "na": "ㄋㄚ", "ne": "ㄋㄜ", "ni": "ㄋㄧ", "nu": "ㄋㄨ", "nv": "ㄋㄩ", "ou": "ㄡ", + "pa": "ㄆㄚ", "pi": "ㄆㄧ", "po": "ㄆㄛ", "pu": "ㄆㄨ", "qi": "ㄑㄧ", "qu": "ㄑㄩ", "re": "ㄖㄜ", "ri": "ㄖ", "ru": "ㄖㄨ", + "sa": "ㄙㄚ", "se": "ㄙㄜ", "si": "ㄙ", "su": "ㄙㄨ", "ta": "ㄊㄚ", "te": "ㄊㄜ", "ti": "ㄊㄧ", "tu": "ㄊㄨ", "wa": "ㄨㄚ", + "wo": "ㄨㄛ", "wu": "ㄨ", "xi": "ㄒㄧ", "xu": "ㄒㄩ", "ya": "ㄧㄚ", "ye": "ㄧㄝ", "yi": "ㄧ", "yo": "ㄧㄛ", "yu": "ㄩ", "za": "ㄗㄚ", + "ze": "ㄗㄜ", "zi": "ㄗ", "zu": "ㄗㄨ", "a": "ㄚ", "e": "ㄜ", "o": "ㄛ", "q": "ㄑ", + ] + + /// 國音二式排列專用處理陣列 + static let mapSecondaryPinyin: [String: String] = [ + "chuang": "ㄔㄨㄤ", "shuang": "ㄕㄨㄤ", "chiang": "ㄑㄧㄤ", "chiung": "ㄑㄩㄥ", "chiuan": "ㄑㄩㄢ", "shiang": "ㄒㄧㄤ", + "shiung": "ㄒㄩㄥ", "shiuan": "ㄒㄩㄢ", "juang": "ㄓㄨㄤ", "jiang": "ㄐㄧㄤ", "jiung": "ㄐㄩㄥ", "niang": "ㄋㄧㄤ", "liang": "ㄌㄧㄤ", + "guang": "ㄍㄨㄤ", "kuang": "ㄎㄨㄤ", "huang": "ㄏㄨㄤ", "chang": "ㄔㄤ", "cheng": "ㄔㄥ", "chuai": "ㄔㄨㄞ", "chuan": "ㄔㄨㄢ", + "chung": "ㄔㄨㄥ", "shang": "ㄕㄤ", "sheng": "ㄕㄥ", "shuai": "ㄕㄨㄞ", "shuan": "ㄕㄨㄢ", "jiuan": "ㄐㄩㄢ", "chiau": "ㄑㄧㄠ", + "chian": "ㄑㄧㄢ", "ching": "ㄑㄧㄥ", "shing": "ㄒㄧㄥ", "tzang": "ㄗㄤ", "tzeng": "ㄗㄥ", "tzuan": "ㄗㄨㄢ", "tzung": "ㄗㄨㄥ", + "tsang": "ㄘㄤ", "tseng": "ㄘㄥ", "tsuan": "ㄘㄨㄢ", "tsung": "ㄘㄨㄥ", "chiue": "ㄑㄩㄝ", "liuan": "ㄌㄩㄢ", "chuei": "ㄔㄨㄟ", + "chuen": "ㄔㄨㄣ", "shuei": "ㄕㄨㄟ", "shuen": "ㄕㄨㄣ", "chiou": "ㄑㄧㄡ", "chiun": "ㄑㄩㄣ", "tzuei": "ㄗㄨㄟ", "tzuen": "ㄗㄨㄣ", + "tsuei": "ㄘㄨㄟ", "tsuen": "ㄘㄨㄣ", "kiang": "ㄎㄧㄤ", "shiau": "ㄒㄧㄠ", "shian": "ㄒㄧㄢ", "shiue": "ㄒㄩㄝ", "shiou": "ㄒㄧㄡ", + "shiun": "ㄒㄩㄣ", "jang": "ㄓㄤ", "jeng": "ㄓㄥ", "juai": "ㄓㄨㄞ", "juan": "ㄓㄨㄢ", "jung": "ㄓㄨㄥ", "jiau": "ㄐㄧㄠ", + "jian": "ㄐㄧㄢ", "jing": "ㄐㄧㄥ", "jiue": "ㄐㄩㄝ", "chie": "ㄑㄧㄝ", "bang": "ㄅㄤ", "beng": "ㄅㄥ", "biau": "ㄅㄧㄠ", + "bian": "ㄅㄧㄢ", "bing": "ㄅㄧㄥ", "pang": "ㄆㄤ", "peng": "ㄆㄥ", "piau": "ㄆㄧㄠ", "pian": "ㄆㄧㄢ", "ping": "ㄆㄧㄥ", "mang": "ㄇㄤ", + "meng": "ㄇㄥ", "miau": "ㄇㄧㄠ", "mian": "ㄇㄧㄢ", "ming": "ㄇㄧㄥ", "fang": "ㄈㄤ", "feng": "ㄈㄥ", "fiau": "ㄈㄧㄠ", "dang": "ㄉㄤ", + "deng": "ㄉㄥ", "diau": "ㄉㄧㄠ", "dian": "ㄉㄧㄢ", "ding": "ㄉㄧㄥ", "duan": "ㄉㄨㄢ", "dung": "ㄉㄨㄥ", "tang": "ㄊㄤ", "teng": "ㄊㄥ", + "tiau": "ㄊㄧㄠ", "tian": "ㄊㄧㄢ", "ting": "ㄊㄧㄥ", "tuan": "ㄊㄨㄢ", "tung": "ㄊㄨㄥ", "nang": "ㄋㄤ", "neng": "ㄋㄥ", + "niau": "ㄋㄧㄠ", "nian": "ㄋㄧㄢ", "ning": "ㄋㄧㄥ", "nuan": "ㄋㄨㄢ", "nung": "ㄋㄨㄥ", "lang": "ㄌㄤ", "leng": "ㄌㄥ", + "liau": "ㄌㄧㄠ", "lian": "ㄌㄧㄢ", "ling": "ㄌㄧㄥ", "luan": "ㄌㄨㄢ", "lung": "ㄌㄨㄥ", "gang": "ㄍㄤ", "geng": "ㄍㄥ", + "guai": "ㄍㄨㄞ", "guan": "ㄍㄨㄢ", "gung": "ㄍㄨㄥ", "kang": "ㄎㄤ", "keng": "ㄎㄥ", "kuai": "ㄎㄨㄞ", "kuan": "ㄎㄨㄢ", + "kung": "ㄎㄨㄥ", "hang": "ㄏㄤ", "heng": "ㄏㄥ", "huai": "ㄏㄨㄞ", "huan": "ㄏㄨㄢ", "hung": "ㄏㄨㄥ", "juei": "ㄓㄨㄟ", + "juen": "ㄓㄨㄣ", "chai": "ㄔㄞ", "chau": "ㄔㄠ", "chou": "ㄔㄡ", "chan": "ㄔㄢ", "chen": "ㄔㄣ", "chua": "ㄔㄨㄚ", "shai": "ㄕㄞ", + "shei": "ㄕㄟ", "shau": "ㄕㄠ", "shou": "ㄕㄡ", "shan": "ㄕㄢ", "shen": "ㄕㄣ", "shua": "ㄕㄨㄚ", "shuo": "ㄕㄨㄛ", "rang": "ㄖㄤ", + "reng": "ㄖㄥ", "ruan": "ㄖㄨㄢ", "rung": "ㄖㄨㄥ", "sang": "ㄙㄤ", "seng": "ㄙㄥ", "suan": "ㄙㄨㄢ", "sung": "ㄙㄨㄥ", "yang": "ㄧㄤ", + "ying": "ㄧㄥ", "wang": "ㄨㄤ", "weng": "ㄨㄥ", "yuan": "ㄩㄢ", "yung": "ㄩㄥ", "niue": "ㄋㄩㄝ", "liue": "ㄌㄩㄝ", "guei": "ㄍㄨㄟ", + "kuei": "ㄎㄨㄟ", "jiou": "ㄐㄧㄡ", "jiun": "ㄐㄩㄣ", "chia": "ㄑㄧㄚ", "chin": "ㄑㄧㄣ", "shin": "ㄒㄧㄣ", "tzai": "ㄗㄞ", + "tzei": "ㄗㄟ", "tzau": "ㄗㄠ", "tzou": "ㄗㄡ", "tzan": "ㄗㄢ", "tzen": "ㄗㄣ", "tsai": "ㄘㄞ", "tsau": "ㄘㄠ", "tsou": "ㄘㄡ", + "tsan": "ㄘㄢ", "tsen": "ㄘㄣ", "chuo": "ㄔㄨㄛ", "miou": "ㄇㄧㄡ", "diou": "ㄉㄧㄡ", "duei": "ㄉㄨㄟ", "duen": "ㄉㄨㄣ", + "tuei": "ㄊㄨㄟ", "tuen": "ㄊㄨㄣ", "niou": "ㄋㄧㄡ", "nuei": "ㄋㄨㄟ", "nuen": "ㄋㄨㄣ", "liou": "ㄌㄧㄡ", "luen": "ㄌㄨㄣ", + "guen": "ㄍㄨㄣ", "kuen": "ㄎㄨㄣ", "huei": "ㄏㄨㄟ", "huen": "ㄏㄨㄣ", "ruei": "ㄖㄨㄟ", "ruen": "ㄖㄨㄣ", "tzuo": "ㄗㄨㄛ", + "tsuo": "ㄘㄨㄛ", "suei": "ㄙㄨㄟ", "suen": "ㄙㄨㄣ", "chiu": "ㄑㄩ", "giau": "ㄍㄧㄠ", "shie": "ㄒㄧㄝ", "shia": "ㄒㄧㄚ", + "shiu": "ㄒㄩ", "jie": "ㄐㄧㄝ", "jai": "ㄓㄞ", "jei": "ㄓㄟ", "jau": "ㄓㄠ", "jou": "ㄓㄡ", "jan": "ㄓㄢ", "jen": "ㄓㄣ", + "jua": "ㄓㄨㄚ", "bie": "ㄅㄧㄝ", "pie": "ㄆㄧㄝ", "mie": "ㄇㄧㄝ", "die": "ㄉㄧㄝ", "tie": "ㄊㄧㄝ", "nie": "ㄋㄧㄝ", "lie": "ㄌㄧㄝ", + "jia": "ㄐㄧㄚ", "jin": "ㄐㄧㄣ", "chr": "ㄔ", "shr": "ㄕ", "yue": "ㄩㄝ", "juo": "ㄓㄨㄛ", "bai": "ㄅㄞ", "bei": "ㄅㄟ", + "bau": "ㄅㄠ", "ban": "ㄅㄢ", "ben": "ㄅㄣ", "bin": "ㄅㄧㄣ", "pai": "ㄆㄞ", "pei": "ㄆㄟ", "pau": "ㄆㄠ", "pou": "ㄆㄡ", + "pan": "ㄆㄢ", "pen": "ㄆㄣ", "pia": "ㄆㄧㄚ", "pin": "ㄆㄧㄣ", "mai": "ㄇㄞ", "mei": "ㄇㄟ", "mau": "ㄇㄠ", "mou": "ㄇㄡ", + "man": "ㄇㄢ", "men": "ㄇㄣ", "min": "ㄇㄧㄣ", "fei": "ㄈㄟ", "fou": "ㄈㄡ", "fan": "ㄈㄢ", "fen": "ㄈㄣ", "dai": "ㄉㄞ", + "dei": "ㄉㄟ", "dau": "ㄉㄠ", "dou": "ㄉㄡ", "dan": "ㄉㄢ", "den": "ㄉㄣ", "dia": "ㄉㄧㄚ", "tai": "ㄊㄞ", "tau": "ㄊㄠ", + "tou": "ㄊㄡ", "tan": "ㄊㄢ", "nai": "ㄋㄞ", "nei": "ㄋㄟ", "nau": "ㄋㄠ", "nou": "ㄋㄡ", "nan": "ㄋㄢ", "nen": "ㄋㄣ", + "nin": "ㄋㄧㄣ", "lai": "ㄌㄞ", "lei": "ㄌㄟ", "lau": "ㄌㄠ", "lou": "ㄌㄡ", "lan": "ㄌㄢ", "lia": "ㄌㄧㄚ", "lin": "ㄌㄧㄣ", + "gai": "ㄍㄞ", "gei": "ㄍㄟ", "gau": "ㄍㄠ", "gou": "ㄍㄡ", "gan": "ㄍㄢ", "gen": "ㄍㄣ", "gua": "ㄍㄨㄚ", "guo": "ㄍㄨㄛ", + "gue": "ㄍㄨㄜ", "kai": "ㄎㄞ", "kau": "ㄎㄠ", "kou": "ㄎㄡ", "kan": "ㄎㄢ", "ken": "ㄎㄣ", "kua": "ㄎㄨㄚ", "kuo": "ㄎㄨㄛ", + "hai": "ㄏㄞ", "hei": "ㄏㄟ", "hau": "ㄏㄠ", "hou": "ㄏㄡ", "han": "ㄏㄢ", "hen": "ㄏㄣ", "hua": "ㄏㄨㄚ", "huo": "ㄏㄨㄛ", + "cha": "ㄔㄚ", "che": "ㄔㄜ", "chu": "ㄔㄨ", "sha": "ㄕㄚ", "she": "ㄕㄜ", "shu": "ㄕㄨ", "rau": "ㄖㄠ", "rou": "ㄖㄡ", "ran": "ㄖㄢ", + "ren": "ㄖㄣ", "sai": "ㄙㄞ", "sei": "ㄙㄟ", "sau": "ㄙㄠ", "sou": "ㄙㄡ", "san": "ㄙㄢ", "sen": "ㄙㄣ", "ang": "ㄤ", "eng": "ㄥ", + "yai": "ㄧㄞ", "yau": "ㄧㄠ", "yan": "ㄧㄢ", "yin": "ㄧㄣ", "wai": "ㄨㄞ", "wei": "ㄨㄟ", "wan": "ㄨㄢ", "wen": "ㄨㄣ", "yun": "ㄩㄣ", + "jiu": "ㄐㄩ", "chi": "ㄑㄧ", "shi": "ㄒㄧ", "tza": "ㄗㄚ", "tze": "ㄗㄜ", "tzu": "ㄗㄨ", "tsz": "ㄘ", "tsa": "ㄘㄚ", "tse": "ㄘㄜ", + "tsu": "ㄘㄨ", "duo": "ㄉㄨㄛ", "tuo": "ㄊㄨㄛ", "nuo": "ㄋㄨㄛ", "luo": "ㄌㄨㄛ", "ruo": "ㄖㄨㄛ", "suo": "ㄙㄨㄛ", "you": "ㄧㄡ", + "niu": "ㄋㄩ", "liu": "ㄌㄩ", "gin": "ㄍㄧㄣ", "bo": "ㄅㄛ", "po": "ㄆㄛ", "mo": "ㄇㄛ", "fo": "ㄈㄛ", "jr": "ㄓ", "ja": "ㄓㄚ", + "je": "ㄓㄜ", "ju": "ㄓㄨ", "ji": "ㄐㄧ", "tz": "ㄗ", "sz": "ㄙ", "er": "ㄦ", "ye": "ㄧㄝ", "ba": "ㄅㄚ", "bi": "ㄅㄧ", "bu": "ㄅㄨ", + "pa": "ㄆㄚ", "pi": "ㄆㄧ", "pu": "ㄆㄨ", "ma": "ㄇㄚ", "me": "ㄇㄜ", "mi": "ㄇㄧ", "mu": "ㄇㄨ", "fa": "ㄈㄚ", "fu": "ㄈㄨ", + "da": "ㄉㄚ", "de": "ㄉㄜ", "di": "ㄉㄧ", "du": "ㄉㄨ", "ta": "ㄊㄚ", "te": "ㄊㄜ", "ti": "ㄊㄧ", "tu": "ㄊㄨ", "na": "ㄋㄚ", + "ne": "ㄋㄜ", "ni": "ㄋㄧ", "nu": "ㄋㄨ", "la": "ㄌㄚ", "lo": "ㄌㄛ", "le": "ㄌㄜ", "li": "ㄌㄧ", "lu": "ㄌㄨ", "ga": "ㄍㄚ", + "ge": "ㄍㄜ", "gu": "ㄍㄨ", "ka": "ㄎㄚ", "ke": "ㄎㄜ", "ku": "ㄎㄨ", "ha": "ㄏㄚ", "he": "ㄏㄜ", "hu": "ㄏㄨ", "re": "ㄖㄜ", + "ru": "ㄖㄨ", "sa": "ㄙㄚ", "se": "ㄙㄜ", "su": "ㄙㄨ", "eh": "ㄝ", "ai": "ㄞ", "ei": "ㄟ", "au": "ㄠ", "ou": "ㄡ", "an": "ㄢ", + "en": "ㄣ", "ya": "ㄧㄚ", "yo": "ㄧㄛ", "wu": "ㄨ", "wa": "ㄨㄚ", "wo": "ㄨㄛ", "yu": "ㄩ", "ch": "ㄑ", "yi": "ㄧ", "r": "ㄖ", + "a": "ㄚ", "o": "ㄛ", "e": "ㄜ", + ] + + /// 耶魯拼音排列專用處理陣列 + static let mapYalePinyin: [String: String] = [ + "chwang": "ㄔㄨㄤ", "shwang": "ㄕㄨㄤ", "chyang": "ㄑㄧㄤ", "chyung": "ㄑㄩㄥ", "chywan": "ㄑㄩㄢ", "jwang": "ㄓㄨㄤ", "syang": "ㄒㄧㄤ", + "syung": "ㄒㄩㄥ", "jyang": "ㄐㄧㄤ", "jyung": "ㄐㄩㄥ", "nyang": "ㄋㄧㄤ", "lyang": "ㄌㄧㄤ", "gwang": "ㄍㄨㄤ", "kwang": "ㄎㄨㄤ", + "hwang": "ㄏㄨㄤ", "chang": "ㄔㄤ", "cheng": "ㄔㄥ", "chwai": "ㄔㄨㄞ", "chwan": "ㄔㄨㄢ", "chung": "ㄔㄨㄥ", "shang": "ㄕㄤ", + "sheng": "ㄕㄥ", "shwai": "ㄕㄨㄞ", "shwan": "ㄕㄨㄢ", "sywan": "ㄒㄩㄢ", "jywan": "ㄐㄩㄢ", "chyau": "ㄑㄧㄠ", "chyan": "ㄑㄧㄢ", + "ching": "ㄑㄧㄥ", "sying": "ㄒㄧㄥ", "dzang": "ㄗㄤ", "dzeng": "ㄗㄥ", "dzwan": "ㄗㄨㄢ", "dzung": "ㄗㄨㄥ", "tsang": "ㄘㄤ", + "tseng": "ㄘㄥ", "tswan": "ㄘㄨㄢ", "tsung": "ㄘㄨㄥ", "chywe": "ㄑㄩㄝ", "lywan": "ㄌㄩㄢ", "chwei": "ㄔㄨㄟ", "chwun": "ㄔㄨㄣ", + "shwei": "ㄕㄨㄟ", "shwun": "ㄕㄨㄣ", "chyou": "ㄑㄧㄡ", "chyun": "ㄑㄩㄣ", "dzwei": "ㄗㄨㄟ", "dzwun": "ㄗㄨㄣ", "tswei": "ㄘㄨㄟ", + "tswun": "ㄘㄨㄣ", "kyang": "ㄎㄧㄤ", "jang": "ㄓㄤ", "jeng": "ㄓㄥ", "jwai": "ㄓㄨㄞ", "jwan": "ㄓㄨㄢ", "jung": "ㄓㄨㄥ", + "syau": "ㄒㄧㄠ", "syan": "ㄒㄧㄢ", "jyau": "ㄐㄧㄠ", "jyan": "ㄐㄧㄢ", "jing": "ㄐㄧㄥ", "sywe": "ㄒㄩㄝ", "jywe": "ㄐㄩㄝ", + "chye": "ㄑㄧㄝ", "bang": "ㄅㄤ", "beng": "ㄅㄥ", "byau": "ㄅㄧㄠ", "byan": "ㄅㄧㄢ", "bing": "ㄅㄧㄥ", "pang": "ㄆㄤ", "peng": "ㄆㄥ", + "pyau": "ㄆㄧㄠ", "pyan": "ㄆㄧㄢ", "ping": "ㄆㄧㄥ", "mang": "ㄇㄤ", "meng": "ㄇㄥ", "myau": "ㄇㄧㄠ", "myan": "ㄇㄧㄢ", + "ming": "ㄇㄧㄥ", "fang": "ㄈㄤ", "feng": "ㄈㄥ", "fyau": "ㄈㄧㄠ", "dang": "ㄉㄤ", "deng": "ㄉㄥ", "dyau": "ㄉㄧㄠ", "dyan": "ㄉㄧㄢ", + "ding": "ㄉㄧㄥ", "dwan": "ㄉㄨㄢ", "dung": "ㄉㄨㄥ", "tang": "ㄊㄤ", "teng": "ㄊㄥ", "tyau": "ㄊㄧㄠ", "tyan": "ㄊㄧㄢ", + "ting": "ㄊㄧㄥ", "twan": "ㄊㄨㄢ", "tung": "ㄊㄨㄥ", "nang": "ㄋㄤ", "neng": "ㄋㄥ", "nyau": "ㄋㄧㄠ", "nyan": "ㄋㄧㄢ", + "ning": "ㄋㄧㄥ", "nwan": "ㄋㄨㄢ", "nung": "ㄋㄨㄥ", "lang": "ㄌㄤ", "leng": "ㄌㄥ", "lyau": "ㄌㄧㄠ", "lyan": "ㄌㄧㄢ", + "ling": "ㄌㄧㄥ", "lwan": "ㄌㄨㄢ", "lung": "ㄌㄨㄥ", "gang": "ㄍㄤ", "geng": "ㄍㄥ", "gwai": "ㄍㄨㄞ", "gwan": "ㄍㄨㄢ", + "gung": "ㄍㄨㄥ", "kang": "ㄎㄤ", "keng": "ㄎㄥ", "kwai": "ㄎㄨㄞ", "kwan": "ㄎㄨㄢ", "kung": "ㄎㄨㄥ", "hang": "ㄏㄤ", "heng": "ㄏㄥ", + "hwai": "ㄏㄨㄞ", "hwan": "ㄏㄨㄢ", "hung": "ㄏㄨㄥ", "jwei": "ㄓㄨㄟ", "jwun": "ㄓㄨㄣ", "chai": "ㄔㄞ", "chau": "ㄔㄠ", "chou": "ㄔㄡ", + "chan": "ㄔㄢ", "chen": "ㄔㄣ", "chwa": "ㄔㄨㄚ", "shai": "ㄕㄞ", "shei": "ㄕㄟ", "shau": "ㄕㄠ", "shou": "ㄕㄡ", "shan": "ㄕㄢ", + "shen": "ㄕㄣ", "shwa": "ㄕㄨㄚ", "shwo": "ㄕㄨㄛ", "rang": "ㄖㄤ", "reng": "ㄖㄥ", "rwan": "ㄖㄨㄢ", "rung": "ㄖㄨㄥ", "sang": "ㄙㄤ", + "seng": "ㄙㄥ", "swan": "ㄙㄨㄢ", "sung": "ㄙㄨㄥ", "yang": "ㄧㄤ", "ying": "ㄧㄥ", "wang": "ㄨㄤ", "weng": "ㄨㄥ", "ywan": "ㄩㄢ", + "yung": "ㄩㄥ", "syou": "ㄒㄧㄡ", "syun": "ㄒㄩㄣ", "nywe": "ㄋㄩㄝ", "lywe": "ㄌㄩㄝ", "gwei": "ㄍㄨㄟ", "kwei": "ㄎㄨㄟ", + "jyou": "ㄐㄧㄡ", "jyun": "ㄐㄩㄣ", "chya": "ㄑㄧㄚ", "chin": "ㄑㄧㄣ", "syin": "ㄒㄧㄣ", "dzai": "ㄗㄞ", "dzei": "ㄗㄟ", "dzau": "ㄗㄠ", + "dzou": "ㄗㄡ", "dzan": "ㄗㄢ", "dzen": "ㄗㄣ", "tsai": "ㄘㄞ", "tsau": "ㄘㄠ", "tsou": "ㄘㄡ", "tsan": "ㄘㄢ", "tsen": "ㄘㄣ", + "chwo": "ㄔㄨㄛ", "myou": "ㄇㄧㄡ", "dyou": "ㄉㄧㄡ", "dwei": "ㄉㄨㄟ", "dwun": "ㄉㄨㄣ", "twei": "ㄊㄨㄟ", "twun": "ㄊㄨㄣ", + "nyou": "ㄋㄧㄡ", "nwei": "ㄋㄨㄟ", "nwun": "ㄋㄨㄣ", "lyou": "ㄌㄧㄡ", "lwun": "ㄌㄨㄣ", "gwun": "ㄍㄨㄣ", "kwun": "ㄎㄨㄣ", + "hwei": "ㄏㄨㄟ", "hwun": "ㄏㄨㄣ", "rwei": "ㄖㄨㄟ", "rwun": "ㄖㄨㄣ", "dzwo": "ㄗㄨㄛ", "tswo": "ㄘㄨㄛ", "swei": "ㄙㄨㄟ", + "swun": "ㄙㄨㄣ", "chyu": "ㄑㄩ", "giau": "ㄍㄧㄠ", "sye": "ㄒㄧㄝ", "jye": "ㄐㄧㄝ", "jai": "ㄓㄞ", "jei": "ㄓㄟ", "jau": "ㄓㄠ", + "jou": "ㄓㄡ", "jan": "ㄓㄢ", "jen": "ㄓㄣ", "jwa": "ㄓㄨㄚ", "sya": "ㄒㄧㄚ", "bye": "ㄅㄧㄝ", "pye": "ㄆㄧㄝ", "mye": "ㄇㄧㄝ", + "dye": "ㄉㄧㄝ", "tye": "ㄊㄧㄝ", "nye": "ㄋㄧㄝ", "lye": "ㄌㄧㄝ", "jya": "ㄐㄧㄚ", "jin": "ㄐㄧㄣ", "chr": "ㄔ", "shr": "ㄕ", + "ywe": "ㄩㄝ", "jwo": "ㄓㄨㄛ", "bai": "ㄅㄞ", "bei": "ㄅㄟ", "bau": "ㄅㄠ", "ban": "ㄅㄢ", "ben": "ㄅㄣ", "bin": "ㄅㄧㄣ", + "pai": "ㄆㄞ", "pei": "ㄆㄟ", "pau": "ㄆㄠ", "pou": "ㄆㄡ", "pan": "ㄆㄢ", "pen": "ㄆㄣ", "pya": "ㄆㄧㄚ", "pin": "ㄆㄧㄣ", + "mai": "ㄇㄞ", "mei": "ㄇㄟ", "mau": "ㄇㄠ", "mou": "ㄇㄡ", "man": "ㄇㄢ", "men": "ㄇㄣ", "min": "ㄇㄧㄣ", "fei": "ㄈㄟ", + "fou": "ㄈㄡ", "fan": "ㄈㄢ", "fen": "ㄈㄣ", "dai": "ㄉㄞ", "dei": "ㄉㄟ", "dau": "ㄉㄠ", "dou": "ㄉㄡ", "dan": "ㄉㄢ", "den": "ㄉㄣ", + "dya": "ㄉㄧㄚ", "tai": "ㄊㄞ", "tau": "ㄊㄠ", "tou": "ㄊㄡ", "tan": "ㄊㄢ", "nai": "ㄋㄞ", "nei": "ㄋㄟ", "nau": "ㄋㄠ", + "nou": "ㄋㄡ", "nan": "ㄋㄢ", "nen": "ㄋㄣ", "nin": "ㄋㄧㄣ", "lai": "ㄌㄞ", "lei": "ㄌㄟ", "lau": "ㄌㄠ", "lou": "ㄌㄡ", + "lan": "ㄌㄢ", "lya": "ㄌㄧㄚ", "lin": "ㄌㄧㄣ", "gai": "ㄍㄞ", "gei": "ㄍㄟ", "gau": "ㄍㄠ", "gou": "ㄍㄡ", "gan": "ㄍㄢ", + "gen": "ㄍㄣ", "gwa": "ㄍㄨㄚ", "gwo": "ㄍㄨㄛ", "gue": "ㄍㄨㄜ", "kai": "ㄎㄞ", "kau": "ㄎㄠ", "kou": "ㄎㄡ", "kan": "ㄎㄢ", + "ken": "ㄎㄣ", "kwa": "ㄎㄨㄚ", "kwo": "ㄎㄨㄛ", "hai": "ㄏㄞ", "hei": "ㄏㄟ", "hau": "ㄏㄠ", "hou": "ㄏㄡ", "han": "ㄏㄢ", + "hen": "ㄏㄣ", "hwa": "ㄏㄨㄚ", "hwo": "ㄏㄨㄛ", "cha": "ㄔㄚ", "che": "ㄔㄜ", "chu": "ㄔㄨ", "sha": "ㄕㄚ", "she": "ㄕㄜ", + "shu": "ㄕㄨ", "rau": "ㄖㄠ", "rou": "ㄖㄡ", "ran": "ㄖㄢ", "ren": "ㄖㄣ", "sai": "ㄙㄞ", "sei": "ㄙㄟ", "sau": "ㄙㄠ", "sou": "ㄙㄡ", + "san": "ㄙㄢ", "sen": "ㄙㄣ", "ang": "ㄤ", "eng": "ㄥ", "yai": "ㄧㄞ", "yau": "ㄧㄠ", "yan": "ㄧㄢ", "yin": "ㄧㄣ", "wai": "ㄨㄞ", + "wei": "ㄨㄟ", "wan": "ㄨㄢ", "wen": "ㄨㄣ", "yun": "ㄩㄣ", "syu": "ㄒㄩ", "jyu": "ㄐㄩ", "chi": "ㄑㄧ", "syi": "ㄒㄧ", "dza": "ㄗㄚ", + "dze": "ㄗㄜ", "dzu": "ㄗㄨ", "tsz": "ㄘ", "tsa": "ㄘㄚ", "tse": "ㄘㄜ", "tsu": "ㄘㄨ", "dwo": "ㄉㄨㄛ", "two": "ㄊㄨㄛ", + "nwo": "ㄋㄨㄛ", "lwo": "ㄌㄨㄛ", "rwo": "ㄖㄨㄛ", "swo": "ㄙㄨㄛ", "you": "ㄧㄡ", "nyu": "ㄋㄩ", "lyu": "ㄌㄩ", "bwo": "ㄅㄛ", + "pwo": "ㄆㄛ", "mwo": "ㄇㄛ", "fwo": "ㄈㄛ", "gin": "ㄍㄧㄣ", "jr": "ㄓ", "ja": "ㄓㄚ", "je": "ㄓㄜ", "ju": "ㄓㄨ", "ji": "ㄐㄧ", + "dz": "ㄗ", "sz": "ㄙ", "er": "ㄦ", "ye": "ㄧㄝ", "ba": "ㄅㄚ", "bi": "ㄅㄧ", "bu": "ㄅㄨ", "pa": "ㄆㄚ", "pi": "ㄆㄧ", "pu": "ㄆㄨ", + "ma": "ㄇㄚ", "me": "ㄇㄜ", "mi": "ㄇㄧ", "mu": "ㄇㄨ", "fa": "ㄈㄚ", "fu": "ㄈㄨ", "da": "ㄉㄚ", "de": "ㄉㄜ", "di": "ㄉㄧ", + "du": "ㄉㄨ", "ta": "ㄊㄚ", "te": "ㄊㄜ", "ti": "ㄊㄧ", "tu": "ㄊㄨ", "na": "ㄋㄚ", "ne": "ㄋㄜ", "ni": "ㄋㄧ", "nu": "ㄋㄨ", + "la": "ㄌㄚ", "lo": "ㄌㄛ", "le": "ㄌㄜ", "li": "ㄌㄧ", "lu": "ㄌㄨ", "ga": "ㄍㄚ", "ge": "ㄍㄜ", "gu": "ㄍㄨ", "ka": "ㄎㄚ", + "ke": "ㄎㄜ", "ku": "ㄎㄨ", "ha": "ㄏㄚ", "he": "ㄏㄜ", "hu": "ㄏㄨ", "re": "ㄖㄜ", "ru": "ㄖㄨ", "sa": "ㄙㄚ", "se": "ㄙㄜ", + "su": "ㄙㄨ", "eh": "ㄝ", "ai": "ㄞ", "ei": "ㄟ", "au": "ㄠ", "ou": "ㄡ", "an": "ㄢ", "en": "ㄣ", "ya": "ㄧㄚ", "yo": "ㄧㄛ", + "wu": "ㄨ", "wa": "ㄨㄚ", "wo": "ㄨㄛ", "yu": "ㄩ", "ch": "ㄑ", "yi": "ㄧ", "r": "ㄖ", "a": "ㄚ", "o": "ㄛ", "e": "ㄜ", + ] + + /// 華羅拼音排列專用處理陣列 + static let mapHualuoPinyin: [String: String] = [ + "shuang": "ㄕㄨㄤ", "jhuang": "ㄓㄨㄤ", "chyueh": "ㄑㄩㄝ", "chyuan": "ㄑㄩㄢ", "chyong": "ㄑㄩㄥ", "chiang": "ㄑㄧㄤ", + "chuang": "ㄔㄨㄤ", "kyang": "ㄎㄧㄤ", "syueh": "ㄒㄩㄝ", "syuan": "ㄒㄩㄢ", "syong": "ㄒㄩㄥ", "sihei": "ㄙㄟ", "siang": "ㄒㄧㄤ", + "shuei": "ㄕㄨㄟ", "shuan": "ㄕㄨㄢ", "shuai": "ㄕㄨㄞ", "sheng": "ㄕㄥ", "shang": "ㄕㄤ", "nyueh": "ㄋㄩㄝ", "niang": "ㄋㄧㄤ", + "lyueh": "ㄌㄩㄝ", "lyuan": "ㄌㄩㄢ", "liang": "ㄌㄧㄤ", "kuang": "ㄎㄨㄤ", "jyueh": "ㄐㄩㄝ", "jyuan": "ㄐㄩㄢ", "jyong": "ㄐㄩㄥ", + "jiang": "ㄐㄧㄤ", "jhuei": "ㄓㄨㄟ", "jhuan": "ㄓㄨㄢ", "jhuai": "ㄓㄨㄞ", "jhong": "ㄓㄨㄥ", "jheng": "ㄓㄥ", "jhang": "ㄓㄤ", + "huang": "ㄏㄨㄤ", "guang": "ㄍㄨㄤ", "chyun": "ㄑㄩㄣ", "tsuei": "ㄘㄨㄟ", "tsuan": "ㄘㄨㄢ", "tsong": "ㄘㄨㄥ", "chiou": "ㄑㄧㄡ", + "ching": "ㄑㄧㄥ", "chieh": "ㄑㄧㄝ", "chiao": "ㄑㄧㄠ", "chian": "ㄑㄧㄢ", "chuei": "ㄔㄨㄟ", "chuan": "ㄔㄨㄢ", "chuai": "ㄔㄨㄞ", + "chong": "ㄔㄨㄥ", "cheng": "ㄔㄥ", "chang": "ㄔㄤ", "tseng": "ㄘㄥ", "tsang": "ㄘㄤ", "gyao": "ㄍㄧㄠ", "fiao": "ㄈㄧㄠ", + "zuei": "ㄗㄨㄟ", "zuan": "ㄗㄨㄢ", "zong": "ㄗㄨㄥ", "zeng": "ㄗㄥ", "zang": "ㄗㄤ", "yueh": "ㄩㄝ", "yuan": "ㄩㄢ", "yong": "ㄩㄥ", + "ying": "ㄧㄥ", "yang": "ㄧㄤ", "wong": "ㄨㄥ", "wang": "ㄨㄤ", "tuei": "ㄊㄨㄟ", "tuan": "ㄊㄨㄢ", "tong": "ㄊㄨㄥ", "ting": "ㄊㄧㄥ", + "tieh": "ㄊㄧㄝ", "tiao": "ㄊㄧㄠ", "tian": "ㄊㄧㄢ", "teng": "ㄊㄥ", "tang": "ㄊㄤ", "syun": "ㄒㄩㄣ", "suei": "ㄙㄨㄟ", + "suan": "ㄙㄨㄢ", "song": "ㄙㄨㄥ", "siou": "ㄒㄧㄡ", "sing": "ㄒㄧㄥ", "sieh": "ㄒㄧㄝ", "siao": "ㄒㄧㄠ", "sian": "ㄒㄧㄢ", + "shuo": "ㄕㄨㄛ", "shun": "ㄕㄨㄣ", "shua": "ㄕㄨㄚ", "shou": "ㄕㄡ", "shih": "ㄕ", "shen": "ㄕㄣ", "shei": "ㄕㄟ", "shao": "ㄕㄠ", + "shan": "ㄕㄢ", "shai": "ㄕㄞ", "seng": "ㄙㄥ", "sang": "ㄙㄤ", "ruei": "ㄖㄨㄟ", "ruan": "ㄖㄨㄢ", "rong": "ㄖㄨㄥ", "reng": "ㄖㄥ", + "rang": "ㄖㄤ", "ping": "ㄆㄧㄥ", "pieh": "ㄆㄧㄝ", "piao": "ㄆㄧㄠ", "pian": "ㄆㄧㄢ", "peng": "ㄆㄥ", "pang": "ㄆㄤ", "nuei": "ㄋㄨㄟ", + "nuan": "ㄋㄨㄢ", "nong": "ㄋㄨㄥ", "niou": "ㄋㄧㄡ", "ning": "ㄋㄧㄥ", "nieh": "ㄋㄧㄝ", "niao": "ㄋㄧㄠ", "nian": "ㄋㄧㄢ", + "neng": "ㄋㄥ", "nang": "ㄋㄤ", "miou": "ㄇㄧㄡ", "ming": "ㄇㄧㄥ", "mieh": "ㄇㄧㄝ", "miao": "ㄇㄧㄠ", "mian": "ㄇㄧㄢ", "meng": "ㄇㄥ", + "mang": "ㄇㄤ", "luan": "ㄌㄨㄢ", "long": "ㄌㄨㄥ", "liou": "ㄌㄧㄡ", "ling": "ㄌㄧㄥ", "lieh": "ㄌㄧㄝ", "liao": "ㄌㄧㄠ", + "lian": "ㄌㄧㄢ", "leng": "ㄌㄥ", "lang": "ㄌㄤ", "kuei": "ㄎㄨㄟ", "kuan": "ㄎㄨㄢ", "kuai": "ㄎㄨㄞ", "kong": "ㄎㄨㄥ", "keng": "ㄎㄥ", + "kang": "ㄎㄤ", "jyun": "ㄐㄩㄣ", "jiou": "ㄐㄧㄡ", "jing": "ㄐㄧㄥ", "jieh": "ㄐㄧㄝ", "jiao": "ㄐㄧㄠ", "jian": "ㄐㄧㄢ", + "jhuo": "ㄓㄨㄛ", "jhun": "ㄓㄨㄣ", "jhua": "ㄓㄨㄚ", "jhou": "ㄓㄡ", "jhih": "ㄓ", "jhen": "ㄓㄣ", "jhei": "ㄓㄟ", "jhao": "ㄓㄠ", + "jhan": "ㄓㄢ", "jhai": "ㄓㄞ", "huei": "ㄏㄨㄟ", "huan": "ㄏㄨㄢ", "huai": "ㄏㄨㄞ", "hong": "ㄏㄨㄥ", "heng": "ㄏㄥ", "hang": "ㄏㄤ", + "guei": "ㄍㄨㄟ", "guan": "ㄍㄨㄢ", "guai": "ㄍㄨㄞ", "gong": "ㄍㄨㄥ", "geng": "ㄍㄥ", "gang": "ㄍㄤ", "feng": "ㄈㄥ", "fang": "ㄈㄤ", + "duei": "ㄉㄨㄟ", "duan": "ㄉㄨㄢ", "dong": "ㄉㄨㄥ", "diou": "ㄉㄧㄡ", "ding": "ㄉㄧㄥ", "dieh": "ㄉㄧㄝ", "diao": "ㄉㄧㄠ", + "dian": "ㄉㄧㄢ", "deng": "ㄉㄥ", "dang": "ㄉㄤ", "chyu": "ㄑㄩ", "tsuo": "ㄘㄨㄛ", "tsun": "ㄘㄨㄣ", "tsou": "ㄘㄡ", "chin": "ㄑㄧㄣ", + "tsih": "ㄘ", "chia": "ㄑㄧㄚ", "chuo": "ㄔㄨㄛ", "chun": "ㄔㄨㄣ", "chua": "ㄔㄨㄚ", "chou": "ㄔㄡ", "chih": "ㄔ", "chen": "ㄔㄣ", + "chao": "ㄔㄠ", "chan": "ㄔㄢ", "chai": "ㄔㄞ", "tsen": "ㄘㄣ", "tsao": "ㄘㄠ", "tsan": "ㄘㄢ", "tsai": "ㄘㄞ", "bing": "ㄅㄧㄥ", + "bieh": "ㄅㄧㄝ", "biao": "ㄅㄧㄠ", "bian": "ㄅㄧㄢ", "beng": "ㄅㄥ", "bang": "ㄅㄤ", "gin": "ㄍㄧㄣ", "den": "ㄉㄣ", "zuo": "ㄗㄨㄛ", + "zun": "ㄗㄨㄣ", "zou": "ㄗㄡ", "zih": "ㄗ", "zen": "ㄗㄣ", "zei": "ㄗㄟ", "zao": "ㄗㄠ", "zan": "ㄗㄢ", "zai": "ㄗㄞ", "yun": "ㄩㄣ", + "you": "ㄧㄡ", "yin": "ㄧㄣ", "yeh": "ㄧㄝ", "yao": "ㄧㄠ", "yan": "ㄧㄢ", "yai": "ㄧㄞ", "wun": "ㄨㄣ", "wei": "ㄨㄟ", "wan": "ㄨㄢ", + "wai": "ㄨㄞ", "tuo": "ㄊㄨㄛ", "tun": "ㄊㄨㄣ", "tou": "ㄊㄡ", "tao": "ㄊㄠ", "tan": "ㄊㄢ", "tai": "ㄊㄞ", "syu": "ㄒㄩ", + "suo": "ㄙㄨㄛ", "sun": "ㄙㄨㄣ", "sou": "ㄙㄡ", "sin": "ㄒㄧㄣ", "sih": "ㄙ", "sia": "ㄒㄧㄚ", "shu": "ㄕㄨ", "she": "ㄕㄜ", + "sha": "ㄕㄚ", "sen": "ㄙㄣ", "sao": "ㄙㄠ", "san": "ㄙㄢ", "sai": "ㄙㄞ", "ruo": "ㄖㄨㄛ", "run": "ㄖㄨㄣ", "rou": "ㄖㄡ", + "rih": "ㄖ", "ren": "ㄖㄣ", "rao": "ㄖㄠ", "ran": "ㄖㄢ", "pou": "ㄆㄡ", "pin": "ㄆㄧㄣ", "pia": "ㄆㄧㄚ", "pen": "ㄆㄣ", + "pei": "ㄆㄟ", "pao": "ㄆㄠ", "pan": "ㄆㄢ", "pai": "ㄆㄞ", "nyu": "ㄋㄩ", "nuo": "ㄋㄨㄛ", "nun": "ㄋㄨㄣ", "nou": "ㄋㄡ", + "nin": "ㄋㄧㄣ", "nen": "ㄋㄣ", "nei": "ㄋㄟ", "nao": "ㄋㄠ", "nan": "ㄋㄢ", "nai": "ㄋㄞ", "mou": "ㄇㄡ", "min": "ㄇㄧㄣ", + "men": "ㄇㄣ", "mei": "ㄇㄟ", "mao": "ㄇㄠ", "man": "ㄇㄢ", "mai": "ㄇㄞ", "lyu": "ㄌㄩ", "luo": "ㄌㄨㄛ", "lun": "ㄌㄨㄣ", + "lou": "ㄌㄡ", "lin": "ㄌㄧㄣ", "lia": "ㄌㄧㄚ", "lei": "ㄌㄟ", "lao": "ㄌㄠ", "lan": "ㄌㄢ", "lai": "ㄌㄞ", "kuo": "ㄎㄨㄛ", + "kun": "ㄎㄨㄣ", "kua": "ㄎㄨㄚ", "kou": "ㄎㄡ", "ken": "ㄎㄣ", "kao": "ㄎㄠ", "kan": "ㄎㄢ", "kai": "ㄎㄞ", "jyu": "ㄐㄩ", + "jin": "ㄐㄧㄣ", "jia": "ㄐㄧㄚ", "jhu": "ㄓㄨ", "jhe": "ㄓㄜ", "jha": "ㄓㄚ", "huo": "ㄏㄨㄛ", "hun": "ㄏㄨㄣ", "hua": "ㄏㄨㄚ", + "hou": "ㄏㄡ", "hen": "ㄏㄣ", "hei": "ㄏㄟ", "hao": "ㄏㄠ", "han": "ㄏㄢ", "hai": "ㄏㄞ", "guo": "ㄍㄨㄛ", "gun": "ㄍㄨㄣ", + "gue": "ㄍㄨㄜ", "gua": "ㄍㄨㄚ", "gou": "ㄍㄡ", "gen": "ㄍㄣ", "gei": "ㄍㄟ", "gao": "ㄍㄠ", "gan": "ㄍㄢ", "gai": "ㄍㄞ", + "fou": "ㄈㄡ", "fen": "ㄈㄣ", "fei": "ㄈㄟ", "fan": "ㄈㄢ", "eng": "ㄥ", "duo": "ㄉㄨㄛ", "dun": "ㄉㄨㄣ", "dou": "ㄉㄡ", + "dia": "ㄉㄧㄚ", "dei": "ㄉㄟ", "dao": "ㄉㄠ", "dan": "ㄉㄢ", "dai": "ㄉㄞ", "tsu": "ㄘㄨ", "chi": "ㄑㄧ", "chu": "ㄔㄨ", + "che": "ㄔㄜ", "cha": "ㄔㄚ", "tse": "ㄘㄜ", "tsa": "ㄘㄚ", "bin": "ㄅㄧㄣ", "ben": "ㄅㄣ", "bei": "ㄅㄟ", "bao": "ㄅㄠ", + "ban": "ㄅㄢ", "bai": "ㄅㄞ", "ang": "ㄤ", "ch": "ㄑ", "zu": "ㄗㄨ", "ze": "ㄗㄜ", "za": "ㄗㄚ", "yu": "ㄩ", "yo": "ㄧㄛ", + "ya": "ㄧㄚ", "yi": "ㄧ", "wu": "ㄨ", "wo": "ㄨㄛ", "wa": "ㄨㄚ", "tu": "ㄊㄨ", "ti": "ㄊㄧ", "te": "ㄊㄜ", "ta": "ㄊㄚ", + "su": "ㄙㄨ", "si": "ㄒㄧ", "se": "ㄙㄜ", "sa": "ㄙㄚ", "ru": "ㄖㄨ", "re": "ㄖㄜ", "pu": "ㄆㄨ", "po": "ㄆㄛ", "pi": "ㄆㄧ", + "pa": "ㄆㄚ", "ou": "ㄡ", "nu": "ㄋㄨ", "ni": "ㄋㄧ", "ne": "ㄋㄜ", "na": "ㄋㄚ", "mu": "ㄇㄨ", "mo": "ㄇㄛ", "mi": "ㄇㄧ", + "me": "ㄇㄜ", "ma": "ㄇㄚ", "lu": "ㄌㄨ", "lo": "ㄌㄛ", "li": "ㄌㄧ", "le": "ㄌㄜ", "la": "ㄌㄚ", "ku": "ㄎㄨ", "ke": "ㄎㄜ", + "ka": "ㄎㄚ", "ji": "ㄐㄧ", "hu": "ㄏㄨ", "he": "ㄏㄜ", "ha": "ㄏㄚ", "gu": "ㄍㄨ", "ge": "ㄍㄜ", "ga": "ㄍㄚ", "fu": "ㄈㄨ", + "fo": "ㄈㄛ", "fa": "ㄈㄚ", "er": "ㄦ", "en": "ㄣ", "ei": "ㄟ", "eh": "ㄝ", "du": "ㄉㄨ", "di": "ㄉㄧ", "de": "ㄉㄜ", "da": "ㄉㄚ", + "bu": "ㄅㄨ", "bo": "ㄅㄛ", "bi": "ㄅㄧ", "ba": "ㄅㄚ", "ao": "ㄠ", "an": "ㄢ", "ai": "ㄞ", "o": "ㄛ", "e": "ㄜ", "a": "ㄚ", + ] + + /// 通用拼音排列專用處理陣列 + static let mapUniversalPinyin: [String: String] = [ + "shuang": "ㄕㄨㄤ", "jhuang": "ㄓㄨㄤ", "chuang": "ㄔㄨㄤ", "cyuan": "ㄑㄩㄢ", "cyong": "ㄑㄩㄥ", "ciang": "ㄑㄧㄤ", "kyang": "ㄎㄧㄤ", + "syuan": "ㄒㄩㄢ", "syong": "ㄒㄩㄥ", "sihei": "ㄙㄟ", "siang": "ㄒㄧㄤ", "shuei": "ㄕㄨㄟ", "shuan": "ㄕㄨㄢ", "shuai": "ㄕㄨㄞ", + "sheng": "ㄕㄥ", "shang": "ㄕㄤ", "niang": "ㄋㄧㄤ", "lyuan": "ㄌㄩㄢ", "liang": "ㄌㄧㄤ", "kuang": "ㄎㄨㄤ", "jyuan": "ㄐㄩㄢ", + "jyong": "ㄐㄩㄥ", "jiang": "ㄐㄧㄤ", "jhuei": "ㄓㄨㄟ", "jhuan": "ㄓㄨㄢ", "jhuai": "ㄓㄨㄞ", "jhong": "ㄓㄨㄥ", "jheng": "ㄓㄥ", + "jhang": "ㄓㄤ", "huang": "ㄏㄨㄤ", "guang": "ㄍㄨㄤ", "chuei": "ㄔㄨㄟ", "chuan": "ㄔㄨㄢ", "chuai": "ㄔㄨㄞ", "chong": "ㄔㄨㄥ", + "cheng": "ㄔㄥ", "chang": "ㄔㄤ", "cyue": "ㄑㄩㄝ", "syue": "ㄒㄩㄝ", "nyue": "ㄋㄩㄝ", "lyue": "ㄌㄩㄝ", "jyue": "ㄐㄩㄝ", + "cyun": "ㄑㄩㄣ", "cuei": "ㄘㄨㄟ", "cuan": "ㄘㄨㄢ", "cong": "ㄘㄨㄥ", "ciou": "ㄑㄧㄡ", "cing": "ㄑㄧㄥ", "ciao": "ㄑㄧㄠ", + "cian": "ㄑㄧㄢ", "ceng": "ㄘㄥ", "cang": "ㄘㄤ", "gyao": "ㄍㄧㄠ", "fiao": "ㄈㄧㄠ", "zuei": "ㄗㄨㄟ", "zuan": "ㄗㄨㄢ", + "zong": "ㄗㄨㄥ", "zeng": "ㄗㄥ", "zang": "ㄗㄤ", "yuan": "ㄩㄢ", "yong": "ㄩㄥ", "ying": "ㄧㄥ", "yang": "ㄧㄤ", "wong": "ㄨㄥ", + "wang": "ㄨㄤ", "tuei": "ㄊㄨㄟ", "tuan": "ㄊㄨㄢ", "tong": "ㄊㄨㄥ", "ting": "ㄊㄧㄥ", "tiao": "ㄊㄧㄠ", "tian": "ㄊㄧㄢ", + "teng": "ㄊㄥ", "tang": "ㄊㄤ", "syun": "ㄒㄩㄣ", "suei": "ㄙㄨㄟ", "suan": "ㄙㄨㄢ", "song": "ㄙㄨㄥ", "siou": "ㄒㄧㄡ", + "sing": "ㄒㄧㄥ", "siao": "ㄒㄧㄠ", "sian": "ㄒㄧㄢ", "shuo": "ㄕㄨㄛ", "shun": "ㄕㄨㄣ", "shua": "ㄕㄨㄚ", "shou": "ㄕㄡ", "shih": "ㄕ", + "shen": "ㄕㄣ", "shei": "ㄕㄟ", "shao": "ㄕㄠ", "shan": "ㄕㄢ", "shai": "ㄕㄞ", "seng": "ㄙㄥ", "sang": "ㄙㄤ", "ruei": "ㄖㄨㄟ", + "ruan": "ㄖㄨㄢ", "rong": "ㄖㄨㄥ", "reng": "ㄖㄥ", "rang": "ㄖㄤ", "ping": "ㄆㄧㄥ", "piao": "ㄆㄧㄠ", "pian": "ㄆㄧㄢ", "peng": "ㄆㄥ", + "pang": "ㄆㄤ", "nuei": "ㄋㄨㄟ", "nuan": "ㄋㄨㄢ", "nong": "ㄋㄨㄥ", "niou": "ㄋㄧㄡ", "ning": "ㄋㄧㄥ", "niao": "ㄋㄧㄠ", + "nian": "ㄋㄧㄢ", "neng": "ㄋㄥ", "nang": "ㄋㄤ", "miou": "ㄇㄧㄡ", "ming": "ㄇㄧㄥ", "miao": "ㄇㄧㄠ", "mian": "ㄇㄧㄢ", "meng": "ㄇㄥ", + "mang": "ㄇㄤ", "luan": "ㄌㄨㄢ", "long": "ㄌㄨㄥ", "liou": "ㄌㄧㄡ", "ling": "ㄌㄧㄥ", "liao": "ㄌㄧㄠ", "lian": "ㄌㄧㄢ", + "leng": "ㄌㄥ", "lang": "ㄌㄤ", "kuei": "ㄎㄨㄟ", "kuan": "ㄎㄨㄢ", "kuai": "ㄎㄨㄞ", "kong": "ㄎㄨㄥ", "keng": "ㄎㄥ", "kang": "ㄎㄤ", + "jyun": "ㄐㄩㄣ", "jiou": "ㄐㄧㄡ", "jing": "ㄐㄧㄥ", "jiao": "ㄐㄧㄠ", "jian": "ㄐㄧㄢ", "jhuo": "ㄓㄨㄛ", "jhun": "ㄓㄨㄣ", + "jhua": "ㄓㄨㄚ", "jhou": "ㄓㄡ", "jhih": "ㄓ", "jhen": "ㄓㄣ", "jhei": "ㄓㄟ", "jhao": "ㄓㄠ", "jhan": "ㄓㄢ", "jhai": "ㄓㄞ", + "huei": "ㄏㄨㄟ", "huan": "ㄏㄨㄢ", "huai": "ㄏㄨㄞ", "hong": "ㄏㄨㄥ", "heng": "ㄏㄥ", "hang": "ㄏㄤ", "guei": "ㄍㄨㄟ", + "guan": "ㄍㄨㄢ", "guai": "ㄍㄨㄞ", "gong": "ㄍㄨㄥ", "geng": "ㄍㄥ", "gang": "ㄍㄤ", "fong": "ㄈㄥ", "fang": "ㄈㄤ", "duei": "ㄉㄨㄟ", + "duan": "ㄉㄨㄢ", "dong": "ㄉㄨㄥ", "diou": "ㄉㄧㄡ", "ding": "ㄉㄧㄥ", "diao": "ㄉㄧㄠ", "dian": "ㄉㄧㄢ", "deng": "ㄉㄥ", + "dang": "ㄉㄤ", "chuo": "ㄔㄨㄛ", "chun": "ㄔㄨㄣ", "chua": "ㄔㄨㄚ", "chou": "ㄔㄡ", "chih": "ㄔ", "chen": "ㄔㄣ", "chao": "ㄔㄠ", + "chan": "ㄔㄢ", "chai": "ㄔㄞ", "bing": "ㄅㄧㄥ", "biao": "ㄅㄧㄠ", "bian": "ㄅㄧㄢ", "beng": "ㄅㄥ", "bang": "ㄅㄤ", "cie": "ㄑㄧㄝ", + "yue": "ㄩㄝ", "tie": "ㄊㄧㄝ", "sie": "ㄒㄧㄝ", "pie": "ㄆㄧㄝ", "nie": "ㄋㄧㄝ", "mie": "ㄇㄧㄝ", "lie": "ㄌㄧㄝ", "jie": "ㄐㄧㄝ", + "die": "ㄉㄧㄝ", "cyu": "ㄑㄩ", "cuo": "ㄘㄨㄛ", "cun": "ㄘㄨㄣ", "cou": "ㄘㄡ", "cin": "ㄑㄧㄣ", "cih": "ㄘ", "cia": "ㄑㄧㄚ", + "cen": "ㄘㄣ", "cao": "ㄘㄠ", "can": "ㄘㄢ", "cai": "ㄘㄞ", "bie": "ㄅㄧㄝ", "gin": "ㄍㄧㄣ", "den": "ㄉㄣ", "zuo": "ㄗㄨㄛ", + "zun": "ㄗㄨㄣ", "zou": "ㄗㄡ", "zih": "ㄗ", "zen": "ㄗㄣ", "zei": "ㄗㄟ", "zao": "ㄗㄠ", "zan": "ㄗㄢ", "zai": "ㄗㄞ", "yun": "ㄩㄣ", + "you": "ㄧㄡ", "yin": "ㄧㄣ", "yao": "ㄧㄠ", "yan": "ㄧㄢ", "yai": "ㄧㄞ", "wun": "ㄨㄣ", "wei": "ㄨㄟ", "wan": "ㄨㄢ", "wai": "ㄨㄞ", + "tuo": "ㄊㄨㄛ", "tun": "ㄊㄨㄣ", "tou": "ㄊㄡ", "tao": "ㄊㄠ", "tan": "ㄊㄢ", "tai": "ㄊㄞ", "syu": "ㄒㄩ", "suo": "ㄙㄨㄛ", + "sun": "ㄙㄨㄣ", "sou": "ㄙㄡ", "sin": "ㄒㄧㄣ", "sih": "ㄙ", "sia": "ㄒㄧㄚ", "shu": "ㄕㄨ", "she": "ㄕㄜ", "sha": "ㄕㄚ", + "sen": "ㄙㄣ", "sao": "ㄙㄠ", "san": "ㄙㄢ", "sai": "ㄙㄞ", "ruo": "ㄖㄨㄛ", "run": "ㄖㄨㄣ", "rou": "ㄖㄡ", "rih": "ㄖ", + "ren": "ㄖㄣ", "rao": "ㄖㄠ", "ran": "ㄖㄢ", "pou": "ㄆㄡ", "pin": "ㄆㄧㄣ", "pia": "ㄆㄧㄚ", "pen": "ㄆㄣ", "pei": "ㄆㄟ", + "pao": "ㄆㄠ", "pan": "ㄆㄢ", "pai": "ㄆㄞ", "nyu": "ㄋㄩ", "nuo": "ㄋㄨㄛ", "nun": "ㄋㄨㄣ", "nou": "ㄋㄡ", "nin": "ㄋㄧㄣ", + "nen": "ㄋㄣ", "nei": "ㄋㄟ", "nao": "ㄋㄠ", "nan": "ㄋㄢ", "nai": "ㄋㄞ", "mou": "ㄇㄡ", "min": "ㄇㄧㄣ", "men": "ㄇㄣ", + "mei": "ㄇㄟ", "mao": "ㄇㄠ", "man": "ㄇㄢ", "mai": "ㄇㄞ", "lyu": "ㄌㄩ", "luo": "ㄌㄨㄛ", "lun": "ㄌㄨㄣ", "lou": "ㄌㄡ", + "lin": "ㄌㄧㄣ", "lia": "ㄌㄧㄚ", "lei": "ㄌㄟ", "lao": "ㄌㄠ", "lan": "ㄌㄢ", "lai": "ㄌㄞ", "kuo": "ㄎㄨㄛ", "kun": "ㄎㄨㄣ", + "kua": "ㄎㄨㄚ", "kou": "ㄎㄡ", "ken": "ㄎㄣ", "kao": "ㄎㄠ", "kan": "ㄎㄢ", "kai": "ㄎㄞ", "jyu": "ㄐㄩ", "jin": "ㄐㄧㄣ", + "jia": "ㄐㄧㄚ", "jhu": "ㄓㄨ", "jhe": "ㄓㄜ", "jha": "ㄓㄚ", "huo": "ㄏㄨㄛ", "hun": "ㄏㄨㄣ", "hua": "ㄏㄨㄚ", "hou": "ㄏㄡ", + "hen": "ㄏㄣ", "hei": "ㄏㄟ", "hao": "ㄏㄠ", "han": "ㄏㄢ", "hai": "ㄏㄞ", "guo": "ㄍㄨㄛ", "gun": "ㄍㄨㄣ", "gue": "ㄍㄨㄜ", + "gua": "ㄍㄨㄚ", "gou": "ㄍㄡ", "gen": "ㄍㄣ", "gei": "ㄍㄟ", "gao": "ㄍㄠ", "gan": "ㄍㄢ", "gai": "ㄍㄞ", "fou": "ㄈㄡ", + "fen": "ㄈㄣ", "fei": "ㄈㄟ", "fan": "ㄈㄢ", "eng": "ㄥ", "duo": "ㄉㄨㄛ", "dun": "ㄉㄨㄣ", "dou": "ㄉㄡ", "dia": "ㄉㄧㄚ", + "dei": "ㄉㄟ", "dao": "ㄉㄠ", "dan": "ㄉㄢ", "dai": "ㄉㄞ", "chu": "ㄔㄨ", "che": "ㄔㄜ", "cha": "ㄔㄚ", "bin": "ㄅㄧㄣ", + "ben": "ㄅㄣ", "bei": "ㄅㄟ", "bao": "ㄅㄠ", "ban": "ㄅㄢ", "bai": "ㄅㄞ", "ang": "ㄤ", "yia": "ㄧㄚ", "ye": "ㄧㄝ", "cu": "ㄘㄨ", + "ci": "ㄑㄧ", "ce": "ㄘㄜ", "ca": "ㄘㄚ", "zu": "ㄗㄨ", "ze": "ㄗㄜ", "za": "ㄗㄚ", "yu": "ㄩ", "yo": "ㄧㄛ", "yi": "ㄧ", "wu": "ㄨ", + "wo": "ㄨㄛ", "wa": "ㄨㄚ", "tu": "ㄊㄨ", "ti": "ㄊㄧ", "te": "ㄊㄜ", "ta": "ㄊㄚ", "su": "ㄙㄨ", "si": "ㄒㄧ", "se": "ㄙㄜ", + "sa": "ㄙㄚ", "ru": "ㄖㄨ", "re": "ㄖㄜ", "pu": "ㄆㄨ", "po": "ㄆㄛ", "pi": "ㄆㄧ", "pa": "ㄆㄚ", "ou": "ㄡ", "nu": "ㄋㄨ", + "ni": "ㄋㄧ", "ne": "ㄋㄜ", "na": "ㄋㄚ", "mu": "ㄇㄨ", "mo": "ㄇㄛ", "mi": "ㄇㄧ", "me": "ㄇㄜ", "ma": "ㄇㄚ", "lu": "ㄌㄨ", + "lo": "ㄌㄛ", "li": "ㄌㄧ", "le": "ㄌㄜ", "la": "ㄌㄚ", "ku": "ㄎㄨ", "ke": "ㄎㄜ", "ka": "ㄎㄚ", "ji": "ㄐㄧ", "hu": "ㄏㄨ", + "he": "ㄏㄜ", "ha": "ㄏㄚ", "gu": "ㄍㄨ", "ge": "ㄍㄜ", "ga": "ㄍㄚ", "fu": "ㄈㄨ", "fo": "ㄈㄛ", "fa": "ㄈㄚ", "er": "ㄦ", + "en": "ㄣ", "ei": "ㄟ", "eh": "ㄝ", "du": "ㄉㄨ", "di": "ㄉㄧ", "de": "ㄉㄜ", "da": "ㄉㄚ", "bu": "ㄅㄨ", "bo": "ㄅㄛ", "bi": "ㄅㄧ", + "ba": "ㄅㄚ", "ao": "ㄠ", "an": "ㄢ", "ai": "ㄞ", "c": "ㄑ", "o": "ㄛ", "e": "ㄜ", "a": "ㄚ", ] // MARK: - Maps for Keyboard-to-Phonabet parsers - /// 任何形式的拼音排列都會用到的陣列,用 Strings 反而省事一些。 - static let mapArayuruPinyin: String = "abcdefghijklmnopqrstuvwxyz12345 " - /// 標準大千排列專用處理陣列。 /// @--DISCUSSION--@ /// 威注音輸入法 macOS 版使用了 Ukelele 佈局來完成對諸如倚天傳統等其它注音鍵盤排列的支援。 @@ -712,12 +1247,22 @@ public struct Tekkon { "s": "ㄋ", "t": "ㄔ", "u": "ㄧ", "v": "ㄒ", "w": "ㄊ", "x": "ㄌ", "y": "ㄗ", "z": "ㄈ", " ": " ", ] + /// 大千忘形排列專用處理陣列,但未包含全部的處理內容。 + /// @--DISCUSSION--@ + /// 在這裡將二十六個字母寫全,也只是為了方便做 validity check。 + /// 這裡提前對複音按鍵做處理,然後再用程式判斷介母類型、據此判斷是否需要做複音切換。 + static let mapDachenCP26StaticKeys: [String: String] = [ + "a": "ㄇ", "b": "ㄖ", "c": "ㄏ", "d": "ㄎ", "e": "ㄍ", "f": "ㄑ", "g": "ㄕ", "h": "ㄘ", "i": "ㄛ", "j": "ㄨ", "k": "ㄜ", + "l": "ㄠ", "m": "ㄩ", "n": "ㄙ", "o": "ㄟ", "p": "ㄣ", "q": "ㄆ", "r": "ㄐ", "s": "ㄋ", "t": "ㄔ", "u": "ㄧ", "v": "ㄒ", + "w": "ㄊ", "x": "ㄌ", "y": "ㄗ", "z": "ㄈ", " ": " ", + ] + /// 許氏排列專用處理陣列,但未包含全部的映射內容。 /// @--DISCUSSION--@ /// 在這裡將二十六個字母寫全,也只是為了方便做 validity check。 /// 這裡提前對複音按鍵做處理,然後再用程式判斷介母類型、據此判斷是否需要做複音切換。 static let mapHsuStaticKeys: [String: String] = [ - "a": "ㄘ", "b": "ㄅ", "c": "ㄕ", "d": "ㄉ", "e": "ㄧ", "f": "ㄈ", "g": "ㄍ", "h": "ㄏ", "i": "ㄞ", "j": "ㄓ", "k": "ㄎ", + "a": "ㄘ", "b": "ㄅ", "c": "ㄒ", "d": "ㄉ", "e": "ㄧ", "f": "ㄈ", "g": "ㄍ", "h": "ㄏ", "i": "ㄞ", "j": "ㄐ", "k": "ㄎ", "l": "ㄌ", "m": "ㄇ", "n": "ㄋ", "o": "ㄡ", "p": "ㄆ", "r": "ㄖ", "s": "ㄙ", "t": "ㄊ", "u": "ㄩ", "v": "ㄑ", "w": "ㄠ", "x": "ㄨ", "y": "ㄚ", "z": "ㄗ", " ": " ", ] From 6e6cce7f4f71b873edb55239e41b312fe8fb072b Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 15 May 2022 14:55:36 +0800 Subject: [PATCH 03/24] KeyHandler // Refactor if-let to guard-let for state conditioning. --- .../ControllerModules/KeyHandler_States.swift | 148 ++++++++---------- 1 file changed, 62 insertions(+), 86 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index f547322b..1261b9d3 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -256,16 +256,10 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback _: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard let currentState = state as? InputState.Inputting else { return false } clear() - - if let current = state as? InputState.Inputting { - stateCallback(InputState.Committing(poppedText: current.composingBuffer)) - } - + stateCallback(InputState.Committing(poppedText: currentState.composingBuffer)) stateCallback(InputState.Empty()) return true } @@ -277,9 +271,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback _: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } var composingBuffer = currentReadings().joined(separator: "-") if mgrPrefs.inlineDumpPinyinInLieuOfZhuyin { @@ -305,9 +297,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback _: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } var composed = "" @@ -346,9 +336,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } if _composer.hasToneMarker(withNothingElse: true) { _composer.clear() @@ -381,9 +369,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } if _composer.isEmpty { if getBuilderCursorIndex() != getBuilderLength() { @@ -417,9 +403,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } if !_composer.isEmpty { IME.prtDebugIntel("9B6F908D") errorCallback() @@ -435,9 +419,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } if !_composer.isEmpty { IME.prtDebugIntel("ABC44080") @@ -465,9 +447,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { - return false - } + guard state is InputState.Inputting else { return false } if !_composer.isEmpty { IME.prtDebugIntel("9B69908D") @@ -495,7 +475,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback _: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { return false } + guard state is InputState.Inputting else { return false } let escToClearInputBufferEnabled: Bool = mgrPrefs.escToCleanInputBuffer @@ -528,7 +508,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { return false } + guard let currentState = state as? InputState.Inputting else { return false } if !_composer.isEmpty { IME.prtDebugIntel("B3BA5257") @@ -537,34 +517,32 @@ extension KeyHandler { return true } - if let currentState = state as? InputState.Inputting { - if input.isShiftHold { - // Shift + Right - if currentState.cursorIndex < (currentState.composingBuffer as NSString).length { - let nextPosition = (currentState.composingBuffer as NSString).nextUtf16Position( - for: Int(currentState.cursorIndex)) - let marking: InputState.Marking! = InputState.Marking( - composingBuffer: currentState.composingBuffer, - cursorIndex: currentState.cursorIndex, - markerIndex: UInt(nextPosition), - readings: currentReadings() - ) - marking.tooltipForInputting = currentState.tooltip - stateCallback(marking) - } else { - IME.prtDebugIntel("BB7F6DB9") - errorCallback() - stateCallback(state) - } + if input.isShiftHold { + // Shift + Right + if currentState.cursorIndex < (currentState.composingBuffer as NSString).length { + let nextPosition = (currentState.composingBuffer as NSString).nextUtf16Position( + for: Int(currentState.cursorIndex)) + let marking: InputState.Marking! = InputState.Marking( + composingBuffer: currentState.composingBuffer, + cursorIndex: currentState.cursorIndex, + markerIndex: UInt(nextPosition), + readings: currentReadings() + ) + marking.tooltipForInputting = currentState.tooltip + stateCallback(marking) } else { - if getBuilderCursorIndex() < getBuilderLength() { - setBuilderCursorIndex(value: getBuilderCursorIndex() + 1) - stateCallback(buildInputtingState()) - } else { - IME.prtDebugIntel("A96AAD58") - errorCallback() - stateCallback(state) - } + IME.prtDebugIntel("BB7F6DB9") + errorCallback() + stateCallback(state) + } + } else { + if getBuilderCursorIndex() < getBuilderLength() { + setBuilderCursorIndex(value: getBuilderCursorIndex() + 1) + stateCallback(buildInputtingState()) + } else { + IME.prtDebugIntel("A96AAD58") + errorCallback() + stateCallback(state) } } @@ -579,7 +557,7 @@ extension KeyHandler { stateCallback: @escaping (InputState) -> Void, errorCallback: @escaping () -> Void ) -> Bool { - if !(state is InputState.Inputting) { return false } + guard let currentState = state as? InputState.Inputting else { return false } if !_composer.isEmpty { IME.prtDebugIntel("6ED95318") @@ -588,34 +566,32 @@ extension KeyHandler { return true } - if let currentState = state as? InputState.Inputting { - if input.isShiftHold { - // Shift + left - if currentState.cursorIndex > 0 { - let previousPosition = (currentState.composingBuffer as NSString).previousUtf16Position( - for: Int(currentState.cursorIndex)) - let marking: InputState.Marking! = InputState.Marking( - composingBuffer: currentState.composingBuffer, - cursorIndex: currentState.cursorIndex, - markerIndex: UInt(previousPosition), - readings: currentReadings() - ) - marking.tooltipForInputting = currentState.tooltip - stateCallback(marking) - } else { - IME.prtDebugIntel("D326DEA3") - errorCallback() - stateCallback(state) - } + if input.isShiftHold { + // Shift + left + if currentState.cursorIndex > 0 { + let previousPosition = (currentState.composingBuffer as NSString).previousUtf16Position( + for: Int(currentState.cursorIndex)) + let marking: InputState.Marking! = InputState.Marking( + composingBuffer: currentState.composingBuffer, + cursorIndex: currentState.cursorIndex, + markerIndex: UInt(previousPosition), + readings: currentReadings() + ) + marking.tooltipForInputting = currentState.tooltip + stateCallback(marking) } else { - if getBuilderCursorIndex() > 0 { - setBuilderCursorIndex(value: getBuilderCursorIndex() - 1) - stateCallback(buildInputtingState()) - } else { - IME.prtDebugIntel("7045E6F3") - errorCallback() - stateCallback(state) - } + IME.prtDebugIntel("D326DEA3") + errorCallback() + stateCallback(state) + } + } else { + if getBuilderCursorIndex() > 0 { + setBuilderCursorIndex(value: getBuilderCursorIndex() - 1) + stateCallback(buildInputtingState()) + } else { + IME.prtDebugIntel("7045E6F3") + errorCallback() + stateCallback(state) } } From 48d434f087104c885f3d1d16c791e7ac03336085 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 15 May 2022 15:21:41 +0800 Subject: [PATCH 04/24] KeyHandler // Add DachenCP26 and Hanyu-Pinyin support, etc. - Also use getComposition() in lieu of realComposition(). --- Source/Modules/ControllerModules/KeyHandler_Core.swift | 4 ++++ Source/Modules/ControllerModules/KeyHandler_HandleInput.swift | 2 +- Source/Modules/ControllerModules/KeyHandler_States.swift | 2 +- Source/Modules/IMEModules/mgrPrefs.swift | 3 +++ Source/Resources/Base.lproj/Localizable.strings | 1 + Source/Resources/en.lproj/Localizable.strings | 1 + Source/Resources/ja.lproj/Localizable.strings | 1 + Source/Resources/zh-Hans.lproj/Localizable.strings | 1 + Source/Resources/zh-Hant.lproj/Localizable.strings | 1 + Source/UI/PrefUI/suiPrefPaneKeyboard.swift | 1 + Source/WindowNIBs/Base.lproj/frmPrefWindow.xib | 1 + Source/WindowNIBs/en.lproj/frmPrefWindow.strings | 3 +++ Source/WindowNIBs/ja.lproj/frmPrefWindow.strings | 3 +++ Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings | 3 +++ Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings | 3 +++ 15 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index 2a15095b..b408cba4 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -328,6 +328,8 @@ class KeyHandler: NSObject { switch mgrPrefs.mandarinParser { case MandarinParser.ofStandard.rawValue: _composer.ensureParser(arrange: .ofDachen) + case MandarinParser.ofDachen26.rawValue: + _composer.ensureParser(arrange: .ofDachen26) case MandarinParser.ofEten.rawValue: _composer.ensureParser(arrange: .ofEten) case MandarinParser.ofHsu.rawValue: @@ -340,6 +342,8 @@ class KeyHandler: NSObject { _composer.ensureParser(arrange: .ofMiTAC) case MandarinParser.ofFakeSeigyou.rawValue: _composer.ensureParser(arrange: .ofFakeSeigyou) + case MandarinParser.ofHanyuPinyin.rawValue: + _composer.ensureParser(arrange: .ofHanyuPinyin) default: _composer.ensureParser(arrange: .ofDachen) mgrPrefs.mandarinParser = MandarinParser.ofStandard.rawValue diff --git a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift index d75239db..ebcfdc6d 100644 --- a/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift +++ b/Source/Modules/ControllerModules/KeyHandler_HandleInput.swift @@ -166,7 +166,7 @@ extension KeyHandler { // However, Swift does not support "|=". composeReading = composeReading || (!_composer.isEmpty && (input.isSpace || input.isEnter)) if composeReading { - let reading = _composer.realComposition + let reading = _composer.getComposition() // See whether we have a unigram for this... if !ifLangModelHasUnigrams(forKey: reading) { diff --git a/Source/Modules/ControllerModules/KeyHandler_States.swift b/Source/Modules/ControllerModules/KeyHandler_States.swift index 1261b9d3..6a361d80 100644 --- a/Source/Modules/ControllerModules/KeyHandler_States.swift +++ b/Source/Modules/ControllerModules/KeyHandler_States.swift @@ -89,7 +89,7 @@ extension KeyHandler { } let head = rawHead - let reading = _composer.getComposition(isHanyuPinyin: mgrPrefs.showHanyuPinyinInCompositionBuffer) + let reading = _composer.getInlineCompositionForIMK(isHanyuPinyin: mgrPrefs.showHanyuPinyinInCompositionBuffer) let tail = rawEnd let composedText = head + reading + tail let cursorIndex = composedStringCursorIndex + reading.count diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index 8a99c805..72a927a0 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -174,6 +174,7 @@ struct ComposingBufferSize { case ofIBM = 4 case ofMiTAC = 5 case ofFakeSeigyou = 6 + case ofDachen26 = 7 case ofHanyuPinyin = 10 var name: String { @@ -192,6 +193,8 @@ struct ComposingBufferSize { return "MiTAC" case .ofFakeSeigyou: return "FakeSeigyou" + case .ofDachen26: + return "Dachen26" case .ofHanyuPinyin: return "HanyuPinyin" } diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index 743c812f..6e057c4d 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -104,6 +104,7 @@ "Choose your preferred layout of the candidate window." = "Choose your preferred layout of the candidate window."; "Cursor Selection:" = "Cursor Selection:"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "Dachen (Microsoft Standard / Wang / 01, etc.)"; +"Dachen 26 (libChewing)" = "Dachen 26 (libChewing)"; "Debug Mode" = "Debug Mode"; "Dictionary" = "Dictionary"; "Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode"; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 743c812f..6e057c4d 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -104,6 +104,7 @@ "Choose your preferred layout of the candidate window." = "Choose your preferred layout of the candidate window."; "Cursor Selection:" = "Cursor Selection:"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "Dachen (Microsoft Standard / Wang / 01, etc.)"; +"Dachen 26 (libChewing)" = "Dachen 26 (libChewing)"; "Debug Mode" = "Debug Mode"; "Dictionary" = "Dictionary"; "Emulating select-candidate-per-character mode" = "Emulating select-candidate-per-character mode"; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index 65baca8c..30838c5e 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -104,6 +104,7 @@ "Choose your preferred layout of the candidate window." = "入力候補陳列の仕様をご指定ください。"; "Cursor Selection:" = "カーソル候補呼出:"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千配列 (Microsoft 標準・王安・零壹など)"; +"Dachen 26 (libChewing)" = "酷音大千二十六キー"; "Debug Mode" = "欠陥辿着モード"; "Dictionary" = "辞書設定"; "Emulating select-candidate-per-character mode" = "漢字1つづつ全候補選択入力モード"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index 8e53b332..4892b95f 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -104,6 +104,7 @@ "Choose your preferred layout of the candidate window." = "选择您所偏好的候选字窗布局。"; "Cursor Selection:" = "选字游标:"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微软标准/王安/零壹/仲鼎/国乔)"; +"Dachen 26 (libChewing)" = "酷音大千二十六键"; "Debug Mode" = "侦错模式"; "Dictionary" = "辞典"; "Emulating select-candidate-per-character mode" = "模拟 90 年代前期注音逐字选字输入风格"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index bd7d11a4..f6c8a79e 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -104,6 +104,7 @@ "Choose your preferred layout of the candidate window." = "選擇您所偏好的候選字窗佈局。"; "Cursor Selection:" = "選字游標:"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千排列 (微軟標準/王安/零壹/仲鼎/國喬)"; +"Dachen 26 (libChewing)" = "酷音大千二十六鍵"; "Debug Mode" = "偵錯模式"; "Dictionary" = "辭典"; "Emulating select-candidate-per-character mode" = "模擬 90 年代前期注音逐字選字輸入風格"; diff --git a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift index 35809ec6..a5226eb4 100644 --- a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift +++ b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift @@ -47,6 +47,7 @@ struct suiPrefPaneKeyboard: View { Preferences.Section(label: { Text(LocalizedStringKey("Phonetic Parser:")) }) { Picker("", selection: $selMandarinParser) { Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0) + Text(LocalizedStringKey("Dachen 26 (libChewing)")).tag(7) Text(LocalizedStringKey("Eten Traditional")).tag(1) Text(LocalizedStringKey("Eten 26")).tag(3) Text(LocalizedStringKey("IBM")).tag(4) diff --git a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index dd35eeab..0d4d9ee2 100644 --- a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -782,6 +782,7 @@ + diff --git a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings index 1175822a..35d08a8c 100644 --- a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings @@ -232,3 +232,6 @@ /* Class = "NSButtonCell"; title = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; ObjectID = "iWy-Nw-QKB"; */ "iWy-Nw-QKB.title" = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; + +/* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ +"xjP-r7-GaK.title" = "Dachen 26 (libChewing)"; diff --git a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings index 2a891d5d..32664b25 100644 --- a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings @@ -232,3 +232,6 @@ /* Class = "NSButtonCell"; title = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; ObjectID = "iWy-Nw-QKB"; */ "iWy-Nw-QKB.title" = "Ctrl(+Alt)+CMD+Enter で出すのを漢語弁音と変換"; + +/* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ +"xjP-r7-GaK.title" = "酷音大千二十六キー"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings index d660e0f4..f8a93fff 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings @@ -232,3 +232,6 @@ /* Class = "NSButtonCell"; title = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; ObjectID = "iWy-Nw-QKB"; */ "iWy-Nw-QKB.title" = "Ctrl(+Alt)+CMD+Enter 输出汉语拼音而非注音"; + +/* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ +"xjP-r7-GaK.title" = "酷音大千二十六键"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings index efc928c4..2627a7c5 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings @@ -232,3 +232,6 @@ /* Class = "NSButtonCell"; title = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; ObjectID = "iWy-Nw-QKB"; */ "iWy-Nw-QKB.title" = "Ctrl(+Alt)+CMD+Enter 輸出漢語拼音而非注音"; + +/* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ +"xjP-r7-GaK.title" = "酷音大千二十六鍵"; From a6177fe0aa65d5bb2360f3ff5e0dcdcc00aecba6 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 14:53:26 +0800 Subject: [PATCH 05/24] PrefUI & PrefWindow // Reenable the menu item of Hanyu-Pinyin parser. --- Source/UI/PrefUI/suiPrefPaneKeyboard.swift | 2 +- Source/WindowNIBs/Base.lproj/frmPrefWindow.xib | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift index a5226eb4..fae2960c 100644 --- a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift +++ b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift @@ -54,7 +54,7 @@ struct suiPrefPaneKeyboard: View { Text(LocalizedStringKey("Hsu")).tag(2) Text(LocalizedStringKey("MiTAC")).tag(5) Text(LocalizedStringKey("Fake Seigyou")).tag(6) - // Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) + Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) }.onChange(of: selMandarinParser) { value in mgrPrefs.mandarinParser = value } diff --git a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index 0d4d9ee2..cf92ce9f 100644 --- a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -789,6 +789,7 @@ + From e0ca2874dab06454a6b24e3b8113da25bfdf054d Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 15:37:05 +0800 Subject: [PATCH 06/24] mgrPrefs // Add options for 2ndary / Yale / Hualuo / Univ. pinyin. --- Source/Modules/IMEModules/mgrPrefs.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index 72a927a0..0bee5acc 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -176,6 +176,10 @@ struct ComposingBufferSize { case ofFakeSeigyou = 6 case ofDachen26 = 7 case ofHanyuPinyin = 10 + case ofSecondaryPinyin = 11 + case ofYalePinyin = 12 + case ofHualuoPinyin = 13 + case ofUniversalPinyin = 14 var name: String { switch self { @@ -197,6 +201,14 @@ struct ComposingBufferSize { return "Dachen26" case .ofHanyuPinyin: return "HanyuPinyin" + case .ofSecondaryPinyin: + return "SecondaryPinyin" + case .ofYalePinyin: + return "YalePinyin" + case .ofHualuoPinyin: + return "HualuoPinyin" + case .ofUniversalPinyin: + return "UniversalPinyin" } } } From 01095a9bcd15b29570bceb0cdef805245a48889f Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 15:40:50 +0800 Subject: [PATCH 07/24] Repo // Add options for 2ndary / Yale / Hualuo / Univ. pinyin. --- .../ControllerModules/KeyHandler_Core.swift | 8 ++++++ .../Resources/Base.lproj/Localizable.strings | 8 ++++-- Source/Resources/en.lproj/Localizable.strings | 8 ++++-- Source/Resources/ja.lproj/Localizable.strings | 10 ++++--- .../zh-Hans.lproj/Localizable.strings | 12 +++++++-- .../zh-Hant.lproj/Localizable.strings | 8 ++++-- Source/UI/PrefUI/suiPrefPaneKeyboard.swift | 27 ++++++++++++------- .../WindowNIBs/Base.lproj/frmPrefWindow.xib | 4 +++ .../WindowNIBs/en.lproj/frmPrefWindow.strings | 16 +++++++++-- .../WindowNIBs/ja.lproj/frmPrefWindow.strings | 16 +++++++++-- .../zh-Hans.lproj/frmPrefWindow.strings | 16 +++++++++-- .../zh-Hant.lproj/frmPrefWindow.strings | 16 +++++++++-- 12 files changed, 121 insertions(+), 28 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index b408cba4..f05f659a 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -344,6 +344,14 @@ class KeyHandler: NSObject { _composer.ensureParser(arrange: .ofFakeSeigyou) case MandarinParser.ofHanyuPinyin.rawValue: _composer.ensureParser(arrange: .ofHanyuPinyin) + case MandarinParser.ofSecondaryPinyin.rawValue: + _composer.ensureParser(arrange: .ofSecondaryPinyin) + case MandarinParser.ofYalePinyin.rawValue: + _composer.ensureParser(arrange: .ofYalePinyin) + case MandarinParser.ofHualuoPinyin.rawValue: + _composer.ensureParser(arrange: .ofHualuoPinyin) + case MandarinParser.ofUniversalPinyin.rawValue: + _composer.ensureParser(arrange: .ofUniversalPinyin) default: _composer.ensureParser(arrange: .ofDachen) mgrPrefs.mandarinParser = MandarinParser.ofStandard.rawValue diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index 6e057c4d..750ae13e 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -85,6 +85,7 @@ "Apple Chewing - Dachen" = "Apple Chewing - Dachen"; "Apple Chewing - Eten Traditional" = "Apple Chewing - Eten Traditional"; "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional." = "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional."; +"at anyplace else (like Windows Yahoo KeyKey)" = "at anyplace else (like Windows Yahoo KeyKey)"; "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters" = "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters"; "Auto-convert traditional Chinese glyphs to KangXi characters" = "Auto-convert traditional Chinese glyphs to KangXi characters"; "Automatically reload user data files if changes detected" = "Automatically reload user data files if changes detected"; @@ -123,7 +124,9 @@ "Hanyu Pinyin with Numeral Intonation" = "Hanyu Pinyin with Numeral Intonation"; "Horizontal" = "Horizontal"; "Hsu" = "Hsu"; +"Hualuo Pinyin with Numeral Intonation" = "Hualuo Pinyin with Numeral Intonation"; "IBM" = "IBM"; +"in front of the phrase (like macOS built-in Zhuyin IME)" = "in front of the phrase (like macOS built-in Zhuyin IME)"; "Japanese" = "Japanese"; "Keyboard" = "Keyboard"; "Misc Settings:" = "Misc Settings:"; @@ -133,6 +136,7 @@ "Output Settings:" = "Output Settings:"; "Phonetic Parser:" = "Phonetic Parser:"; "Push the cursor in front of the phrase after selection" = "Push the cursor in front of the phrase after selection"; +"Secondary Pinyin with Numeral Intonation" = "Secondary Pinyin with Numeral Intonation"; "Selection Keys:" = "Selection Keys:"; "Show Hanyu-Pinyin in the inline composition buffer" = "Show Hanyu-Pinyin in the inline composition buffer"; "Show page buttons in candidate window" = "Show page buttons in candidate window"; @@ -141,10 +145,10 @@ "Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates"; "Stop farting (when typed phonetic combination is invalid, etc.)" = "Stop farting (when typed phonetic combination is invalid, etc.)"; -"in front of the phrase (like macOS built-in Zhuyin IME)" = "in front of the phrase (like macOS built-in Zhuyin IME)"; -"at anyplace else (like Windows Yahoo KeyKey)" = "at anyplace else (like Windows Yahoo KeyKey)"; "Traditional Chinese" = "Traditional Chinese"; "Typing Style:" = "Typing Style:"; "UI Language:" = "UI Language:"; +"Universal Pinyin with Numeral Intonation" = "Universal Pinyin with Numeral Intonation"; "Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer"; "Vertical" = "Vertical"; +"Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation"; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 6e057c4d..750ae13e 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -85,6 +85,7 @@ "Apple Chewing - Dachen" = "Apple Chewing - Dachen"; "Apple Chewing - Eten Traditional" = "Apple Chewing - Eten Traditional"; "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional." = "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional."; +"at anyplace else (like Windows Yahoo KeyKey)" = "at anyplace else (like Windows Yahoo KeyKey)"; "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters" = "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters"; "Auto-convert traditional Chinese glyphs to KangXi characters" = "Auto-convert traditional Chinese glyphs to KangXi characters"; "Automatically reload user data files if changes detected" = "Automatically reload user data files if changes detected"; @@ -123,7 +124,9 @@ "Hanyu Pinyin with Numeral Intonation" = "Hanyu Pinyin with Numeral Intonation"; "Horizontal" = "Horizontal"; "Hsu" = "Hsu"; +"Hualuo Pinyin with Numeral Intonation" = "Hualuo Pinyin with Numeral Intonation"; "IBM" = "IBM"; +"in front of the phrase (like macOS built-in Zhuyin IME)" = "in front of the phrase (like macOS built-in Zhuyin IME)"; "Japanese" = "Japanese"; "Keyboard" = "Keyboard"; "Misc Settings:" = "Misc Settings:"; @@ -133,6 +136,7 @@ "Output Settings:" = "Output Settings:"; "Phonetic Parser:" = "Phonetic Parser:"; "Push the cursor in front of the phrase after selection" = "Push the cursor in front of the phrase after selection"; +"Secondary Pinyin with Numeral Intonation" = "Secondary Pinyin with Numeral Intonation"; "Selection Keys:" = "Selection Keys:"; "Show Hanyu-Pinyin in the inline composition buffer" = "Show Hanyu-Pinyin in the inline composition buffer"; "Show page buttons in candidate window" = "Show page buttons in candidate window"; @@ -141,10 +145,10 @@ "Space to +cycle candidates, Shift+Space to +cycle pages" = "Space to +cycle candidates, Shift+Space to +cycle pages"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "Space to +cycle pages, Shift+Space to +cycle candidates"; "Stop farting (when typed phonetic combination is invalid, etc.)" = "Stop farting (when typed phonetic combination is invalid, etc.)"; -"in front of the phrase (like macOS built-in Zhuyin IME)" = "in front of the phrase (like macOS built-in Zhuyin IME)"; -"at anyplace else (like Windows Yahoo KeyKey)" = "at anyplace else (like Windows Yahoo KeyKey)"; "Traditional Chinese" = "Traditional Chinese"; "Typing Style:" = "Typing Style:"; "UI Language:" = "UI Language:"; +"Universal Pinyin with Numeral Intonation" = "Universal Pinyin with Numeral Intonation"; "Use ESC key to clear the entire input buffer" = "Use ESC key to clear the entire input buffer"; "Vertical" = "Vertical"; +"Yale Pinyin with Numeral Intonation" = "Yale Pinyin with Numeral Intonation"; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index 30838c5e..361b74b4 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -85,6 +85,7 @@ "Apple Chewing - Dachen" = "Apple 大千注音キーボード"; "Apple Chewing - Eten Traditional" = "Apple 倚天傳統キーボード"; "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional." = "Apple 動態注音キーボード (大千と倚天伝統) を使うには、共通語分析器の配列を大千と設定すべきである。"; +"at anyplace else (like Windows Yahoo KeyKey)" = "単語の中・後で // Windows Yahoo KeyKey のやり方"; "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters" = "入力した繁体字を日文 JIS 新字体と自動変換"; "Auto-convert traditional Chinese glyphs to KangXi characters" = "入力した繁体字を康熙字体と自動変換"; "Automatically reload user data files if changes detected" = "ユーザー辞書データの変更を自動検出し、自動的に再読込"; @@ -104,7 +105,7 @@ "Choose your preferred layout of the candidate window." = "入力候補陳列の仕様をご指定ください。"; "Cursor Selection:" = "カーソル候補呼出:"; "Dachen (Microsoft Standard / Wang / 01, etc.)" = "大千配列 (Microsoft 標準・王安・零壹など)"; -"Dachen 26 (libChewing)" = "酷音大千二十六キー"; +"Dachen 26 (libChewing)" = "酷音大千 26 キー配列"; "Debug Mode" = "欠陥辿着モード"; "Dictionary" = "辞書設定"; "Emulating select-candidate-per-character mode" = "漢字1つづつ全候補選択入力モード"; @@ -123,7 +124,9 @@ "Hanyu Pinyin with Numeral Intonation" = "漢語弁音 (ローマ字+数字音調)"; "Horizontal" = "横型陳列"; "Hsu" = "許氏国音自然配列"; +"Hualuo Pinyin with Numeral Intonation" = "中華ローマ弁音 (ローマ字+数字音調)"; "IBM" = "IBM 配列"; +"in front of the phrase (like macOS built-in Zhuyin IME)" = "単語の前で // macOS 内蔵注音入力のやり方"; "Japanese" = "和語"; "Keyboard" = "配列設定"; "Misc Settings:" = "他の設定:"; @@ -133,6 +136,7 @@ "Output Settings:" = "出力設定:"; "Phonetic Parser:" = "注音配列:"; "Push the cursor in front of the phrase after selection" = "候補選択の直後、すぐカーソルを単語の向こうに推し進める"; +"Secondary Pinyin with Numeral Intonation" = "国音二式 (ローマ字+数字音調)"; "Selection Keys:" = "言選り用キー:"; "Show Hanyu-Pinyin in the inline composition buffer" = "弁音合併入力(入力緩衝列で代わりに漢語弁音の音読み)"; "Show page buttons in candidate window" = "入力候補陳列の側にページボタンを表示"; @@ -141,10 +145,10 @@ "Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+Space で次のページ、Space で次の候補文字を"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "Space で次のページ、Shift+Space で次の候補文字を"; "Stop farting (when typed phonetic combination is invalid, etc.)" = "マナーモード // 外すと入力間違った時に変な声が出る"; -"in front of the phrase (like macOS built-in Zhuyin IME)" = "単語の前で // macOS 内蔵注音入力のやり方"; -"at anyplace else (like Windows Yahoo KeyKey)" = "単語の中・後で // Windows Yahoo KeyKey のやり方"; "Traditional Chinese" = "繁体中国語"; "Typing Style:" = "入力習慣:"; "UI Language:" = "表示用言語:"; +"Universal Pinyin with Numeral Intonation" = "汎用弁音 (ローマ字+数字音調)"; "Use ESC key to clear the entire input buffer" = "ESC キーで入力緩衝列を消す"; "Vertical" = "縦型陳列"; +"Yale Pinyin with Numeral Intonation" = "イェール弁音 (ローマ字+数字音調)"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index 4892b95f..8928773e 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -85,6 +85,7 @@ "Apple Chewing - Dachen" = "Apple 大千注音键盘排列"; "Apple Chewing - Eten Traditional" = "Apple 倚天传统键盘排列"; "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional." = "Apple 动态注音键盘布局(大千与倚天)要求普通话/国音分析器得配置为大千排列。"; +"at anyplace else (like Windows Yahoo KeyKey)" = "将游标置于词语中后方 // Windows 奇摩注音风格"; "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters" = "自动将繁体中文字转为日文 JIS 新字体"; "Auto-convert traditional Chinese glyphs to KangXi characters" = "自动将繁体中文字转为康熙正体字"; "Automatically reload user data files if changes detected" = "自动检测并载入使用者语汇档案变更"; @@ -123,7 +124,10 @@ "Hanyu Pinyin with Numeral Intonation" = "汉语拼音+数字标调"; "Horizontal" = "横向布局"; "Hsu" = "许氏国音自然排列"; +"Hualuo Pinyin with Numeral Intonation" = "华罗拼音+数字标调"; +"Hualuo Pinyin with Numeral Intonation" = "華羅拼音+数字标调"; "IBM" = "IBM 排列"; +"in front of the phrase (like macOS built-in Zhuyin IME)" = "将游标置于词语前方 // macOS 内建注音风格"; "Japanese" = "和语"; "Keyboard" = "键盘"; "Misc Settings:" = "杂项:"; @@ -133,6 +137,8 @@ "Output Settings:" = "输出设定:"; "Phonetic Parser:" = "注音排列:"; "Push the cursor in front of the phrase after selection" = "在选字后将游标置于该字词的前方"; +"Secondary Pinyin with Numeral Intonation" = "国音二式+数字标调"; +"Secondary Pinyin with Numeral Intonation" = "國音二式+数字标调"; "Selection Keys:" = "选字键:"; "Show Hanyu-Pinyin in the inline composition buffer" = "拼音并击模式(组字区内看到的是汉语拼音)"; "Show page buttons in candidate window" = "在选字窗内显示翻页按钮"; @@ -141,10 +147,12 @@ "Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格键 换下一页,空格键 换选下一个后选字"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "空格键 换下一页,Shift+空格键 换选下一个后选字"; "Stop farting (when typed phonetic combination is invalid, etc.)" = "廉耻模式 // 取消勾选的话,敲错字时会有异音"; -"in front of the phrase (like macOS built-in Zhuyin IME)" = "将游标置于词语前方 // macOS 内建注音风格"; -"at anyplace else (like Windows Yahoo KeyKey)" = "将游标置于词语中后方 // Windows 奇摩注音风格"; "Traditional Chinese" = "繁体中文"; "Typing Style:" = "输入风格:"; "UI Language:" = "介面语言:"; +"Universal Pinyin with Numeral Intonation" = "通用拼音+数字标调"; +"Universal Pinyin with Numeral Intonation" = "通用拼音+数字标调"; "Use ESC key to clear the entire input buffer" = "敲 ESC 键以清空整个组字缓冲区"; "Vertical" = "纵向布局"; +"Yale Pinyin with Numeral Intonation" = "耶鲁拼音+数字标调"; +"Yale Pinyin with Numeral Intonation" = "耶魯拼音+数字标调"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index f6c8a79e..0347c7db 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -85,6 +85,7 @@ "Apple Chewing - Dachen" = "Apple 大千注音鍵盤佈局"; "Apple Chewing - Eten Traditional" = "Apple 倚天傳統鍵盤佈局"; "Apple Dynamic Bopomofo Basic Keyboard Layouts (Dachen & Eten Traditional) must match the Dachen parser in order to be functional." = "Apple 動態注音鍵盤佈局(大千與倚天)要求普通話/國音分析器得配置為大千排列。"; +"at anyplace else (like Windows Yahoo KeyKey)" = "將游標置於詞語中後方 // Windows 奇摩注音風格"; "Auto-convert traditional Chinese glyphs to JIS Shinjitai characters" = "自動將繁體中文字轉為日文 JIS 新字體"; "Auto-convert traditional Chinese glyphs to KangXi characters" = "自動將繁體中文字轉為康熙正體字"; "Automatically reload user data files if changes detected" = "自動檢測並載入使用者語彙檔案變更"; @@ -123,7 +124,9 @@ "Hanyu Pinyin with Numeral Intonation" = "漢語拼音+數字標調"; "Horizontal" = "橫向佈局"; "Hsu" = "許氏國音自然排列"; +"Hualuo Pinyin with Numeral Intonation" = "華羅拼音+數字標調"; "IBM" = "IBM 排列"; +"in front of the phrase (like macOS built-in Zhuyin IME)" = "將游標置於詞語前方 // macOS 內建注音風格"; "Japanese" = "和語"; "Keyboard" = "鍵盤"; "Misc Settings:" = "雜項:"; @@ -133,6 +136,7 @@ "Output Settings:" = "輸出設定:"; "Phonetic Parser:" = "注音排列:"; "Push the cursor in front of the phrase after selection" = "在選字後將游標置於該字詞的前方"; +"Secondary Pinyin with Numeral Intonation" = "國音二式+數字標調"; "Selection Keys:" = "選字鍵:"; "Show Hanyu-Pinyin in the inline composition buffer" = "拼音並擊模式(組字區內看到的是漢語拼音)"; "Show page buttons in candidate window" = "在選字窗內顯示翻頁按鈕"; @@ -141,10 +145,10 @@ "Space to +cycle candidates, Shift+Space to +cycle pages" = "Shift+空格鍵 換下一頁,空格鍵 換選下一個後選字"; "Space to +cycle pages, Shift+Space to +cycle candidates" = "空格鍵 換下一頁,Shift+空格鍵 換選下一個後選字"; "Stop farting (when typed phonetic combination is invalid, etc.)" = "廉恥模式 // 取消勾選的話,敲錯字時會有異音"; -"in front of the phrase (like macOS built-in Zhuyin IME)" = "將游標置於詞語前方 // macOS 內建注音風格"; -"at anyplace else (like Windows Yahoo KeyKey)" = "將游標置於詞語中後方 // Windows 奇摩注音風格"; "Traditional Chinese" = "繁體中文"; "Typing Style:" = "輸入風格:"; "UI Language:" = "介面語言:"; +"Universal Pinyin with Numeral Intonation" = "通用拼音+數字標調"; "Use ESC key to clear the entire input buffer" = "敲 ESC 鍵以清空整個組字緩衝區"; "Vertical" = "縱向佈局"; +"Yale Pinyin with Numeral Intonation" = "耶魯拼音+數字標調"; diff --git a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift index fae2960c..15e7e66f 100644 --- a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift +++ b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift @@ -46,15 +46,24 @@ struct suiPrefPaneKeyboard: View { Preferences.Container(contentWidth: contentWidth) { Preferences.Section(label: { Text(LocalizedStringKey("Phonetic Parser:")) }) { Picker("", selection: $selMandarinParser) { - Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0) - Text(LocalizedStringKey("Dachen 26 (libChewing)")).tag(7) - Text(LocalizedStringKey("Eten Traditional")).tag(1) - Text(LocalizedStringKey("Eten 26")).tag(3) - Text(LocalizedStringKey("IBM")).tag(4) - Text(LocalizedStringKey("Hsu")).tag(2) - Text(LocalizedStringKey("MiTAC")).tag(5) - Text(LocalizedStringKey("Fake Seigyou")).tag(6) - Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) + Group { + Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0) + Text(LocalizedStringKey("Dachen 26 (libChewing)")).tag(7) + Text(LocalizedStringKey("Eten Traditional")).tag(1) + Text(LocalizedStringKey("Eten 26")).tag(3) + Text(LocalizedStringKey("IBM")).tag(4) + Text(LocalizedStringKey("Hsu")).tag(2) + Text(LocalizedStringKey("MiTAC")).tag(5) + Text(LocalizedStringKey("Fake Seigyou")).tag(6) + } + Divider() + Group { + Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) + Text(LocalizedStringKey("Secondary Pinyin with Numeral Intonation")).tag(11) + Text(LocalizedStringKey("Yale Pinyin with Numeral Intonation")).tag(12) + Text(LocalizedStringKey("Hualuo Pinyin with Numeral Intonation")).tag(13) + Text(LocalizedStringKey("Universal Pinyin with Numeral Intonation")).tag(14) + } }.onChange(of: selMandarinParser) { value in mgrPrefs.mandarinParser = value } diff --git a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index cf92ce9f..2c071710 100644 --- a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -790,6 +790,10 @@ + + + + diff --git a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings index 35d08a8c..0178fff6 100644 --- a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings @@ -20,8 +20,8 @@ /* Class = "NSMenuItem"; title = "ETen26"; ObjectID = "9"; */ "9.title" = "ETen26"; -/* Class = "NSMenuItem"; title = "Hanyu Pinyin"; ObjectID = "10"; */ -"10.title" = "Hanyu Pinyin"; +/* Class = "NSMenuItem"; title = "Hanyu Pinyin with Numeral Intonation"; ObjectID = "10"; */ +"10.title" = "Hanyu Pinyin with Numeral Intonation"; /* Class = "NSTextFieldCell"; title = "BPMF Parser:"; ObjectID = "12"; */ "12.title" = "BPMF Parser:"; @@ -235,3 +235,15 @@ /* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ "xjP-r7-GaK.title" = "Dachen 26 (libChewing)"; + +/* Class = "NSMenuItem"; title = "Secondary Pinyin with Numeral Intonation"; ObjectID = "Parser11"; */ +"Parser11.title" = "Secondary Pinyin with Numeral Intonation"; + +/* Class = "NSMenuItem"; title = "Yale Pinyin with Numeral Intonation"; ObjectID = "Parser12"; */ +"Parser12.title" = "Yale Pinyin with Numeral Intonation"; + +/* Class = "NSMenuItem"; title = "Hualuo Pinyin with Numeral Intonation"; ObjectID = "Parser13"; */ +"Parser13.title" = "Hualuo Pinyin with Numeral Intonation"; + +/* Class = "NSMenuItem"; title = "Universal Pinyin with Numeral Intonation"; ObjectID = "Parser14"; */ +"Parser14.title" = "Universal Pinyin with Numeral Intonation"; diff --git a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings index 32664b25..3d8e876a 100644 --- a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings @@ -20,7 +20,7 @@ /* Class = "NSMenuItem"; title = "ETen26"; ObjectID = "9"; */ "9.title" = "倚天形忘れ配列 (26キー)"; -/* Class = "NSMenuItem"; title = "Hanyu Pinyin"; ObjectID = "10"; */ +/* Class = "NSMenuItem"; title = "Hanyu Pinyin with Numeral Intonation"; ObjectID = "10"; */ "10.title" = "漢語弁音(ローマ字+数字音調)"; /* Class = "NSTextFieldCell"; title = "BPMF Parser:"; ObjectID = "12"; */ @@ -234,4 +234,16 @@ "iWy-Nw-QKB.title" = "Ctrl(+Alt)+CMD+Enter で出すのを漢語弁音と変換"; /* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ -"xjP-r7-GaK.title" = "酷音大千二十六キー"; +"xjP-r7-GaK.title" = "酷音大千 26 キー配列"; + +/* Class = "NSMenuItem"; title = "Secondary Pinyin with Numeral Intonation"; ObjectID = "Parser11"; */ +"Parser11.title" = "国音二式 (ローマ字+数字音調)"; + +/* Class = "NSMenuItem"; title = "Yale Pinyin with Numeral Intonation"; ObjectID = "Parser12"; */ +"Parser12.title" = "イェール弁音 (ローマ字+数字音調)"; + +/* Class = "NSMenuItem"; title = "Hualuo Pinyin with Numeral Intonation"; ObjectID = "Parser13"; */ +"Parser13.title" = "中華ローマ弁音 (ローマ字+数字音調)"; + +/* Class = "NSMenuItem"; title = "Universal Pinyin with Numeral Intonation"; ObjectID = "Parser14"; */ +"Parser14.title" = "汎用弁音 (ローマ字+数字音調)"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings index f8a93fff..8bcf7678 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings @@ -20,8 +20,8 @@ /* Class = "NSMenuItem"; title = "ETen26"; ObjectID = "9"; */ "9.title" = "倚天二十六键"; -/* Class = "NSMenuItem"; title = "Hanyu Pinyin"; ObjectID = "10"; */ -"10.title" = "汉语拼音二式(字母拼音+数字标调)"; +/* Class = "NSMenuItem"; title = "Hanyu Pinyin with Numeral Intonation"; ObjectID = "10"; */ +"10.title" = "汉语拼音+数字标调"; /* Class = "NSTextFieldCell"; title = "BPMF Parser:"; ObjectID = "12"; */ "12.title" = "基础键盘布局:"; @@ -235,3 +235,15 @@ /* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ "xjP-r7-GaK.title" = "酷音大千二十六键"; + +/* Class = "NSMenuItem"; title = "Secondary Pinyin with Numeral Intonation"; ObjectID = "Parser11"; */ +"Parser11.title" = "国音二式+数字标调"; + +/* Class = "NSMenuItem"; title = "Yale Pinyin with Numeral Intonation"; ObjectID = "Parser12"; */ +"Parser12.title" = "耶鲁拼音+数字标调"; + +/* Class = "NSMenuItem"; title = "Hualuo Pinyin with Numeral Intonation"; ObjectID = "Parser13"; */ +"Parser13.title" = "华罗拼音+数字标调"; + +/* Class = "NSMenuItem"; title = "Universal Pinyin with Numeral Intonation"; ObjectID = "Parser14"; */ +"Parser14.title" = "通用拼音+数字标调"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings index 2627a7c5..2f939ed2 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings @@ -20,8 +20,8 @@ /* Class = "NSMenuItem"; title = "ETen26"; ObjectID = "9"; */ "9.title" = "倚天二十六鍵"; -/* Class = "NSMenuItem"; title = "Hanyu Pinyin"; ObjectID = "10"; */ -"10.title" = "漢語拼音二式(字母拼音+數字標調)"; +/* Class = "NSMenuItem"; title = "Hanyu Pinyin with Numeral Intonation"; ObjectID = "10"; */ +"10.title" = "漢語拼音+數字標調"; /* Class = "NSTextFieldCell"; title = "BPMF Parser:"; ObjectID = "12"; */ "12.title" = "注音排列:"; @@ -235,3 +235,15 @@ /* Class = "NSMenuItem"; title = "Dachen 26 (libChewing)"; ObjectID = "xjP-r7-GaK"; */ "xjP-r7-GaK.title" = "酷音大千二十六鍵"; + +/* Class = "NSMenuItem"; title = "Secondary Pinyin with Numeral Intonation"; ObjectID = "Parser11"; */ +"Parser11.title" = "國音二式+數字標調"; + +/* Class = "NSMenuItem"; title = "Yale Pinyin with Numeral Intonation"; ObjectID = "Parser12"; */ +"Parser12.title" = "耶魯拼音+數字標調"; + +/* Class = "NSMenuItem"; title = "Hualuo Pinyin with Numeral Intonation"; ObjectID = "Parser13"; */ +"Parser13.title" = "華羅拼音+數字標調"; + +/* Class = "NSMenuItem"; title = "Universal Pinyin with Numeral Intonation"; ObjectID = "Parser14"; */ +"Parser14.title" = "通用拼音+數字標調"; From 5f078d7c400c8c1eceb9eb1c8679eddb0a79b29c Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 16:54:04 +0800 Subject: [PATCH 08/24] PrefUI_Keyboard // Add reset buttons and mistake-proofing. --- .../zh-Hans.lproj/Localizable.strings | 2 - Source/UI/PrefUI/suiPrefPaneKeyboard.swift | 76 ++++++++++++++----- 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index 8928773e..ab0f3f6a 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -138,7 +138,6 @@ "Phonetic Parser:" = "注音排列:"; "Push the cursor in front of the phrase after selection" = "在选字后将游标置于该字词的前方"; "Secondary Pinyin with Numeral Intonation" = "国音二式+数字标调"; -"Secondary Pinyin with Numeral Intonation" = "國音二式+数字标调"; "Selection Keys:" = "选字键:"; "Show Hanyu-Pinyin in the inline composition buffer" = "拼音并击模式(组字区内看到的是汉语拼音)"; "Show page buttons in candidate window" = "在选字窗内显示翻页按钮"; @@ -155,4 +154,3 @@ "Use ESC key to clear the entire input buffer" = "敲 ESC 键以清空整个组字缓冲区"; "Vertical" = "纵向布局"; "Yale Pinyin with Numeral Intonation" = "耶鲁拼音+数字标调"; -"Yale Pinyin with Numeral Intonation" = "耶魯拼音+数字标调"; diff --git a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift index 15e7e66f..edeed2b8 100644 --- a/Source/UI/PrefUI/suiPrefPaneKeyboard.swift +++ b/Source/UI/PrefUI/suiPrefPaneKeyboard.swift @@ -45,30 +45,60 @@ struct suiPrefPaneKeyboard: View { var body: some View { Preferences.Container(contentWidth: contentWidth) { Preferences.Section(label: { Text(LocalizedStringKey("Phonetic Parser:")) }) { - Picker("", selection: $selMandarinParser) { - Group { - Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0) - Text(LocalizedStringKey("Dachen 26 (libChewing)")).tag(7) - Text(LocalizedStringKey("Eten Traditional")).tag(1) - Text(LocalizedStringKey("Eten 26")).tag(3) - Text(LocalizedStringKey("IBM")).tag(4) - Text(LocalizedStringKey("Hsu")).tag(2) - Text(LocalizedStringKey("MiTAC")).tag(5) - Text(LocalizedStringKey("Fake Seigyou")).tag(6) + HStack { + Picker("", selection: $selMandarinParser) { + Group { + Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0) + Text(LocalizedStringKey("Dachen 26 (libChewing)")).tag(7) + Text(LocalizedStringKey("Eten Traditional")).tag(1) + Text(LocalizedStringKey("Eten 26")).tag(3) + Text(LocalizedStringKey("IBM")).tag(4) + Text(LocalizedStringKey("Hsu")).tag(2) + Text(LocalizedStringKey("MiTAC")).tag(5) + Text(LocalizedStringKey("Fake Seigyou")).tag(6) + } + Divider() + Group { + Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) + Text(LocalizedStringKey("Secondary Pinyin with Numeral Intonation")).tag(11) + Text(LocalizedStringKey("Yale Pinyin with Numeral Intonation")).tag(12) + Text(LocalizedStringKey("Hualuo Pinyin with Numeral Intonation")).tag(13) + Text(LocalizedStringKey("Universal Pinyin with Numeral Intonation")).tag(14) + } + }.onChange(of: selMandarinParser) { value in + mgrPrefs.mandarinParser = value + switch value { + case 0: + if !AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) { + mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ZhuyinBopomofo" + selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout + } + default: + if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) { + mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC" + selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout + } + } } - Divider() - Group { - Text(LocalizedStringKey("Hanyu Pinyin with Numeral Intonation")).tag(10) - Text(LocalizedStringKey("Secondary Pinyin with Numeral Intonation")).tag(11) - Text(LocalizedStringKey("Yale Pinyin with Numeral Intonation")).tag(12) - Text(LocalizedStringKey("Hualuo Pinyin with Numeral Intonation")).tag(13) - Text(LocalizedStringKey("Universal Pinyin with Numeral Intonation")).tag(14) + .labelsHidden() + Button { + mgrPrefs.mandarinParser = 0 + selMandarinParser = mgrPrefs.mandarinParser + mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ZhuyinBopomofo" + selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout + } label: { + Text("↻ㄅ") + } + Button { + mgrPrefs.mandarinParser = 10 + selMandarinParser = mgrPrefs.mandarinParser + mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC" + selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout + } label: { + Text("↻A") } - }.onChange(of: selMandarinParser) { value in - mgrPrefs.mandarinParser = value } - .labelsHidden() - .frame(width: 320.0) + .frame(width: 380.0) Text(LocalizedStringKey("Choose the phonetic layout for Mandarin parser.")) .preferenceDescription() } @@ -81,6 +111,10 @@ struct suiPrefPaneKeyboard: View { }.id(UUID()) }.onChange(of: selBasicKeyboardLayout) { value in mgrPrefs.basicKeyboardLayout = value + if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(value) { + mgrPrefs.mandarinParser = 0 + selMandarinParser = mgrPrefs.mandarinParser + } } .labelsHidden() .frame(width: 240.0) From f11063fbb00ce94b111ed3c3612260e3f8ba49b3 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 15 May 2022 18:23:55 +0800 Subject: [PATCH 09/24] AppDelegate // DispatchQueue the userdata loading when finish launching. --- Source/Modules/AppDelegate.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Modules/AppDelegate.swift b/Source/Modules/AppDelegate.swift index c6c3965a..92ac189d 100644 --- a/Source/Modules/AppDelegate.swift +++ b/Source/Modules/AppDelegate.swift @@ -64,7 +64,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega } func applicationDidFinishLaunching(_: Notification) { - IME.initLangModels(userOnly: false) + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) { + IME.initLangModels(userOnly: false) + } + fsStreamHelper.delegate = self _ = fsStreamHelper.start() From 82707e89b60b1bc5cc527784fb8bcce61585fadf Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 00:09:06 +0800 Subject: [PATCH 10/24] IME // Add UniChar.isPrintable() --- Source/Modules/IMEModules/IME.swift | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Source/Modules/IMEModules/IME.swift b/Source/Modules/IMEModules/IME.swift index 0704414a..df50d1b3 100644 --- a/Source/Modules/IMEModules/IME.swift +++ b/Source/Modules/IMEModules/IME.swift @@ -364,7 +364,7 @@ extension String: LocalizedError { } } -// MARK: - Ensuring trailing slash of a string: +// MARK: - Ensuring trailing slash of a string extension String { mutating func ensureTrailingSlash() { @@ -373,3 +373,16 @@ extension String { } } } + +// MARK: - CharCode printability check + +// Ref: https://forums.swift.org/t/57085/5 +extension UniChar { + public func isPrintable() -> Bool { + guard Unicode.Scalar(UInt32(self)) != nil else { + struct NotAWholeScalar: Error {} + return false + } + return true + } +} From 7bc0b5cc251e74ff23aa32a440cf8973f9be88b0 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Mon, 16 May 2022 23:15:39 +0800 Subject: [PATCH 11/24] ctlIME // Refactor handle(event:client:) with guard let. --- Source/Modules/IMEModules/ctlInputMethod.swift | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Source/Modules/IMEModules/ctlInputMethod.swift b/Source/Modules/IMEModules/ctlInputMethod.swift index 08cb21e6..fb4a2a33 100644 --- a/Source/Modules/IMEModules/ctlInputMethod.swift +++ b/Source/Modules/IMEModules/ctlInputMethod.swift @@ -148,7 +148,7 @@ class ctlInputMethod: IMKInputController { return Int(events.rawValue) } - override func handle(_ event: NSEvent!, client: Any!) -> Bool { + @objc(handleEvent:client:) override func handle(_ event: NSEvent!, client sender: Any!) -> Bool { // 這裡仍舊需要判斷 flags。之前使輸入法狀態卡住無法敲漢字的問題已在 KeyHandler 內修復。 // 這裡不判斷 flags 的話,用方向鍵前後定位光標之後,再次試圖觸發組字區時、反而會在首次按鍵時失敗。 // 同時注意:必須在 event.type == .flagsChanged 結尾插入 return false, @@ -161,13 +161,18 @@ class ctlInputMethod: IMKInputController { ctlInputMethod.areWeDeleting = event.modifierFlags.contains([.shift, .command]) var textFrame = NSRect.zero - let attributes: [AnyHashable: Any]? = (client as? IMKTextInput)?.attributes( + guard let client = sender as? IMKTextInput else { + return false + } + + let attributes: [AnyHashable: Any]? = client.attributes( forCharacterIndex: 0, lineHeightRectangle: &textFrame ) + let useVerticalMode = (attributes?["IMKTextOrientation"] as? NSNumber)?.intValue == 0 || false - if (client as? IMKTextInput)?.bundleIdentifier() + if client.bundleIdentifier() == "org.atelierInmu.vChewing.vChewingPhraseEditor" { IME.areWeUsingOurOwnPhraseEditor = true @@ -177,6 +182,12 @@ class ctlInputMethod: IMKInputController { let input = InputHandler(event: event, isVerticalMode: useVerticalMode) + // 無法列印的訊號輸入,一概不作處理。 + // 這個過程不能放在 KeyHandler 內,否則不會起作用。 + if !input.charCode.isPrintable() { + return false + } + let result = keyHandler.handle(input: input, state: state) { newState in self.handle(state: newState, client: client) } errorCallback: { From 9127a2bb2eb4b77d88af55d3bfa832a3c05477b3 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 16:28:06 +0800 Subject: [PATCH 12/24] Repo // Remove Cpp files of UserOverrideModel. --- .../OldFileReferences/UserOverrideModel.cpp | 220 ------------------ .../OldFileReferences/UserOverrideModel.h | 82 ------- vChewing.xcodeproj/project.pbxproj | 12 - 3 files changed, 314 deletions(-) delete mode 100644 Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.cpp delete mode 100644 Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.h diff --git a/Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.cpp b/Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.cpp deleted file mode 100644 index 8b4fb8ac..00000000 --- a/Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (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 "UserOverrideModel.h" - -#include -#include -#include - -namespace vChewing -{ - -// About 20 generations. -static const double DecayThreshold = 1.0 / 1048576.0; - -static double Score(size_t eventCount, size_t totalCount, double eventTimestamp, double timestamp, double lambda); -static bool IsEndingPunctuation(const std::string &value); -static std::string WalkedNodesToKey(const std::vector &walkedNodes, size_t cursorIndex); - -UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant) : m_capacity(capacity) -{ - assert(m_capacity > 0); - m_decayExponent = log(0.5) / decayConstant; -} - -void UserOverrideModel::observe(const std::vector &walkedNodes, size_t cursorIndex, - const std::string &candidate, double timestamp) -{ - std::string key = WalkedNodesToKey(walkedNodes, cursorIndex); - auto mapIter = m_lruMap.find(key); - if (mapIter == m_lruMap.end()) - { - auto keyValuePair = KeyObservationPair(key, Observation()); - Observation &observation = keyValuePair.second; - observation.update(candidate, timestamp); - - m_lruList.push_front(keyValuePair); - auto listIter = m_lruList.begin(); - auto lruKeyValue = std::pair::iterator>(key, listIter); - m_lruMap.insert(lruKeyValue); - - if (m_lruList.size() > m_capacity) - { - auto lastKeyValuePair = m_lruList.end(); - --lastKeyValuePair; - m_lruMap.erase(lastKeyValuePair->first); - m_lruList.pop_back(); - } - } - else - { - auto listIter = mapIter->second; - m_lruList.splice(m_lruList.begin(), m_lruList, listIter); - - auto &keyValuePair = *listIter; - Observation &observation = keyValuePair.second; - observation.update(candidate, timestamp); - } -} - -std::string UserOverrideModel::suggest(const std::vector &walkedNodes, size_t cursorIndex, - double timestamp) -{ - std::string key = WalkedNodesToKey(walkedNodes, cursorIndex); - auto mapIter = m_lruMap.find(key); - if (mapIter == m_lruMap.end()) - { - return std::string(); - } - - auto listIter = mapIter->second; - auto &keyValuePair = *listIter; - const Observation &observation = keyValuePair.second; - - std::string candidate; - double score = 0.0; - for (auto i = observation.overrides.begin(); i != observation.overrides.end(); ++i) - { - const Override &o = i->second; - double overrideScore = Score(o.count, observation.count, o.timestamp, timestamp, m_decayExponent); - if (overrideScore == 0.0) - { - continue; - } - - if (overrideScore > score) - { - candidate = i->first; - score = overrideScore; - } - } - return candidate; -} - -void UserOverrideModel::Observation::update(const std::string &candidate, double timestamp) -{ - count++; - auto &o = overrides[candidate]; - o.timestamp = timestamp; - o.count++; -} - -static double Score(size_t eventCount, size_t totalCount, double eventTimestamp, double timestamp, double lambda) -{ - double decay = exp((timestamp - eventTimestamp) * lambda); - if (decay < DecayThreshold) - { - return 0.0; - } - - double prob = (double)eventCount / (double)totalCount; - return prob * decay; -} - -static bool IsEndingPunctuation(const std::string &value) -{ - return value == "," || value == "。" || value == "!" || value == "?" || value == "」" || value == "』" || - value == "”" || value == "’"; -} -static std::string WalkedNodesToKey(const std::vector &walkedNodes, size_t cursorIndex) -{ - std::stringstream s; - std::vector n; - size_t ll = 0; - for (std::vector::const_iterator i = walkedNodes.begin(); i != walkedNodes.end(); ++i) - { - const auto &nn = *i; - n.push_back(nn); - ll += nn.spanningLength; - if (ll >= cursorIndex) - { - break; - } - } - - std::vector::const_reverse_iterator r = n.rbegin(); - - if (r == n.rend()) - { - return ""; - } - - std::string current = (*r).node->currentKeyValue().key; - ++r; - - s.clear(); - s.str(std::string()); - if (r != n.rend()) - { - std::string value = (*r).node->currentKeyValue().value; - if (IsEndingPunctuation(value)) - { - s << "()"; - r = n.rend(); - } - else - { - s << "(" << (*r).node->currentKeyValue().key << "," << value << ")"; - ++r; - } - } - else - { - s << "()"; - } - std::string prev = s.str(); - - s.clear(); - s.str(std::string()); - if (r != n.rend()) - { - std::string value = (*r).node->currentKeyValue().value; - if (IsEndingPunctuation(value)) - { - s << "()"; - r = n.rend(); - } - else - { - s << "(" << (*r).node->currentKeyValue().key << "," << value << ")"; - ++r; - } - } - else - { - s << "()"; - } - std::string anterior = s.str(); - - s.clear(); - s.str(std::string()); - s << "(" << anterior << "," << prev << "," << current << ")"; - - return s.str(); -} - -} // namespace vChewing diff --git a/Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.h b/Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.h deleted file mode 100644 index 6479c2d6..00000000 --- a/Source/Modules/LangModelRelated/OldFileReferences/UserOverrideModel.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License). -// All possible vChewing-specific modifications are of: -// (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 USEROVERRIDEMODEL_H -#define USEROVERRIDEMODEL_H - -#include -#include - -#include "Gramambular.h" - -namespace vChewing -{ - -using namespace Gramambular; - -class UserOverrideModel -{ - public: - UserOverrideModel(size_t capacity, double decayConstant); - - void observe(const std::vector &walkedNodes, size_t cursorIndex, - const std::string &candidate, double timestamp); - - std::string suggest(const std::vector &walkedNodes, size_t cursorIndex, double timestamp); - - private: - struct Override - { - size_t count; - double timestamp; - - Override() : count(0), timestamp(0.0) - { - } - }; - - struct Observation - { - size_t count; - std::map overrides; - - Observation() : count(0) - { - } - void update(const std::string &candidate, double timestamp); - }; - - typedef std::pair KeyObservationPair; - - size_t m_capacity; - double m_decayExponent; - std::list m_lruList; - std::map::iterator> m_lruMap; -}; - -}; // namespace vChewing - -#endif diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index dea262d5..504beb88 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -318,8 +318,6 @@ D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = main.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlPrefWindow.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D47F7DCF278C0897002F9DD7 /* ctlNonModalAlertWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlNonModalAlertWindow.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; - D47F7DD1278C1263002F9DD7 /* UserOverrideModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = UserOverrideModel.h; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; - D47F7DD2278C1263002F9DD7 /* UserOverrideModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = UserOverrideModel.cpp; sourceTree = ""; tabWidth = 4; usesTabs = 0; }; D4A13D5927A59D5C003BE359 /* ctlInputMethod.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlInputMethod.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; D4E33D8927A838CF006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; D4E33D8E27A838F0006DB1CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -470,7 +468,6 @@ 5B62A32427AE757300A19448 /* LangModelRelated */ = { isa = PBXGroup; children = ( - 5B62A32527AE758000A19448 /* OldFileReferences */, 5B407308281672610023DFFF /* SubLMs */, 5B949BDA2816DDBC00D87B5D /* LMConsolidator.swift */, 5BD0113A28180D6100609769 /* LMInstantiator.swift */, @@ -479,15 +476,6 @@ path = LangModelRelated; sourceTree = ""; }; - 5B62A32527AE758000A19448 /* OldFileReferences */ = { - isa = PBXGroup; - children = ( - D47F7DD2278C1263002F9DD7 /* UserOverrideModel.cpp */, - D47F7DD1278C1263002F9DD7 /* UserOverrideModel.h */, - ); - path = OldFileReferences; - sourceTree = ""; - }; 5B62A33027AE78E500A19448 /* Resources */ = { isa = PBXGroup; children = ( From dd317455e2003f2558f473ceb31d4eaf9a9546f0 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 00:19:25 +0800 Subject: [PATCH 13/24] Megrez // Refactor certain functions in Grid and Walker. --- .../LanguageParsers/Megrez/1_Walker.swift | 19 ++++++++++ .../LanguageParsers/Megrez/2_Grid.swift | 38 +++++++++---------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/Source/Modules/LanguageParsers/Megrez/1_Walker.swift b/Source/Modules/LanguageParsers/Megrez/1_Walker.swift index 26e4502d..5bd934b8 100644 --- a/Source/Modules/LanguageParsers/Megrez/1_Walker.swift +++ b/Source/Modules/LanguageParsers/Megrez/1_Walker.swift @@ -31,6 +31,25 @@ extension Megrez { mutGrid = grid } + public func walk( + at location: Int, + score accumulatedScore: Double = 0.0, + nodesLimit: Int = 0, + balanced: Bool = false + ) -> [NodeAnchor] { + var arrReturn: [NodeAnchor] = [] + let arrReversedSource = reverseWalk( + at: location, score: accumulatedScore, + nodesLimit: nodesLimit, balanced: balanced + ).reversed() + + for neta in arrReversedSource { + arrReturn.append(neta) + } + + return arrReturn + } + public func reverseWalk( at location: Int, score accumulatedScore: Double = 0.0, diff --git a/Source/Modules/LanguageParsers/Megrez/2_Grid.swift b/Source/Modules/LanguageParsers/Megrez/2_Grid.swift index ada025f4..9f71f3b5 100644 --- a/Source/Modules/LanguageParsers/Megrez/2_Grid.swift +++ b/Source/Modules/LanguageParsers/Megrez/2_Grid.swift @@ -128,15 +128,17 @@ extension Megrez { public func fixNodeSelectedCandidate(location: Int, value: String) -> NodeAnchor { var node = NodeAnchor() - for (index, nodeAnchor) in nodesCrossingOrEndingAt(location: location).enumerated() { + for nodeAnchor in nodesCrossingOrEndingAt(location: location) { + guard let theNode = nodeAnchor.node else { + continue + } + let candidates = theNode.candidates() // Reset the candidate-fixed state of every node at the location. - let candidates = nodeAnchor.node?.candidates() ?? [] - nodesCrossingOrEndingAt(location: location)[index].node?.resetCandidate() - + theNode.resetCandidate() for (i, candidate) in candidates.enumerated() { if candidate.value == value { - nodesCrossingOrEndingAt(location: location)[index].node?.selectCandidateAt(index: i) - node = nodesCrossingOrEndingAt(location: location)[index] + theNode.selectCandidateAt(index: i) + node = nodeAnchor break } } @@ -145,19 +147,17 @@ extension Megrez { } public func overrideNodeScoreForSelectedCandidate(location: Int, value: String, overridingScore: Double) { - for (index, nodeAnchor) in nodesCrossingOrEndingAt(location: location).enumerated() { - if let theNode = nodeAnchor.node { - let candidates = theNode.candidates() - // Reset the candidate-fixed state of every node at the location. - nodesCrossingOrEndingAt(location: location)[index].node?.resetCandidate() - - for (i, candidate) in candidates.enumerated() { - if candidate.value == value { - nodesCrossingOrEndingAt(location: location)[index].node?.selectFloatingCandidateAt( - index: i, score: overridingScore - ) - break - } + for nodeAnchor in nodesCrossingOrEndingAt(location: location) { + guard let theNode = nodeAnchor.node else { + continue + } + let candidates = theNode.candidates() + // Reset the candidate-fixed state of every node at the location. + theNode.resetCandidate() + for (i, candidate) in candidates.enumerated() { + if candidate.value == value { + theNode.selectFloatingCandidateAt(index: i, score: overridingScore) + break } } } From b466c571373bd590c2eb6d22e2c64ed936b240d2 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 15:56:53 +0800 Subject: [PATCH 14/24] lmUserOverride // Another attempt to make it functional. - Now it successfully generates keys and starts observing things. The rest issue is that it cannot give a useful suggestion. --- .../SubLMs/lmUserOverride.swift | 118 ++++++++---------- 1 file changed, 53 insertions(+), 65 deletions(-) diff --git a/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift b/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift index dd2157df..7791275b 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmUserOverride.swift @@ -1,6 +1,5 @@ // Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License). -// Refactored from the ObjCpp-version of this class by: -// (c) 2011 and onwards The OpenVanilla Project (MIT License). +// Refactored from the ObjCpp-version of this class by Mengjuei Hsieh (MIT 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 @@ -68,7 +67,7 @@ extension vChewing { var mutCapacity: Int var mutDecayExponent: Double - var mutLRUList = [KeyObservationPair]() + var mutLRUList: [KeyObservationPair] = [] var mutLRUMap: [String: KeyObservationPair] = [:] let kDecayThreshold: Double = 1.0 / 1_048_576.0 @@ -86,27 +85,27 @@ extension vChewing { candidate: String, timestamp: Double ) { - let key = getWalkedNodesToKey(walkedNodes: walkedNodes, cursorIndex: cursorIndex) - guard !key.isEmpty - else { - return - } + let key = convertKeyFrom(walkedNodes: walkedNodes, cursorIndex: cursorIndex) + guard mutLRUMap[key] != nil else { var observation: Observation = .init() observation.update(candidate: candidate, timestamp: timestamp) - mutLRUMap[key] = KeyObservationPair(key: key, observation: observation) - mutLRUList.insert(KeyObservationPair(key: key, observation: observation), at: 0) + let koPair = KeyObservationPair(key: key, observation: observation) + mutLRUMap[key] = koPair + mutLRUList.insert(koPair, at: 0) if mutLRUList.count > mutCapacity { - mutLRUMap[mutLRUList.reversed()[0].key] = nil + mutLRUMap[mutLRUList[mutLRUList.endIndex].key] = nil mutLRUList.removeLast() } + IME.prtDebugIntel("UOM: Observation finished with new observation: \(key)") return } - mutLRUList.insert(contentsOf: mutLRUMap.values, at: 0) - - if mutLRUMap[key] != nil { - mutLRUMap[key]?.observation.update(candidate: candidate, timestamp: timestamp) + if var theNeta = mutLRUMap[key] { + theNeta.observation.update(candidate: candidate, timestamp: timestamp) + mutLRUList.insert(theNeta, at: 0) + mutLRUMap[key] = theNeta + IME.prtDebugIntel("UOM: Observation finished with existing observation: \(key)") } } @@ -115,25 +114,22 @@ extension vChewing { cursorIndex: Int, timestamp: Double ) -> String { - let key = getWalkedNodesToKey(walkedNodes: walkedNodes, cursorIndex: cursorIndex) - guard let keyValuePair = mutLRUMap[key], - !key.isEmpty - else { + let key = convertKeyFrom(walkedNodes: walkedNodes, cursorIndex: cursorIndex) + guard let koPair = mutLRUMap[key] else { + IME.prtDebugIntel("UOM: mutLRUMap[key] is nil, throwing blank suggestion for key: \(key).") return "" } - IME.prtDebugIntel("Suggest - A: \(key)") - IME.prtDebugIntel("Suggest - B: \(keyValuePair.key)") - - let observation = keyValuePair.observation + let observation = koPair.observation var candidate = "" var score = 0.0 for overrideNeta in Array(observation.overrides) { - let overrideScore = getScore( - eventCount: overrideNeta.value.count, + let override: Override = overrideNeta.value + let overrideScore: Double = getScore( + eventCount: override.count, totalCount: observation.count, - eventTimestamp: overrideNeta.value.timestamp, + eventTimestamp: override.timestamp, timestamp: timestamp, lambda: mutDecayExponent ) @@ -147,13 +143,12 @@ extension vChewing { score = overrideScore } } + if candidate.isEmpty { + IME.prtDebugIntel("UOM: No usable suggestions in the result for key: \(key).") + } return candidate } - func isEndingPunctuation(value: String) -> Bool { - [",", "。", "!", "?", "」", "』", "”", "’"].contains(value) - } - public func getScore( eventCount: Int, totalCount: Int, @@ -170,58 +165,51 @@ extension vChewing { return prob * decay } - func getWalkedNodesToKey( + func convertKeyFrom( walkedNodes: [Megrez.NodeAnchor], cursorIndex: Int ) -> String { - var strOutput = "" - var arrNodes: [Megrez.NodeAnchor] = [] + let arrEndingPunctuation = [",", "。", "!", "?", "」", "』", "”", "’"] + var arrNodesReversed: [Megrez.NodeAnchor] = [] var intLength = 0 - for nodeNeta in walkedNodes { - arrNodes.append(nodeNeta) - intLength += nodeNeta.spanningLength + for theNodeAnchor in walkedNodes { + // 這裡直接生成一個反向排序的陣列,之後就不用再「.reverse()」了。 + arrNodesReversed = [theNodeAnchor] + arrNodesReversed + intLength += theNodeAnchor.spanningLength if intLength >= cursorIndex { break } } - // 一個被 .reversed 過的陣列不能直接使用,因為不是正常的 Swift 陣列。 - // 那就新開一個正常的陣列、然後將內容拓印過去。 - var arrNodesReversed: [Megrez.NodeAnchor] = [] - arrNodesReversed.append(contentsOf: arrNodes.reversed()) + if arrNodesReversed.isEmpty { return "" } - if arrNodesReversed.isEmpty { + var strCurrent = "()" + var strPrevious = "()" + var strAnterior = "()" + + guard let kvCurrent = arrNodesReversed[0].node?.currentKeyValue(), + !arrEndingPunctuation.contains(kvCurrent.value) + else { return "" } - var strCurrent = "()" - var strPrev = "()" - var strAnterior = "()" + // 前置單元只記錄讀音,在其後的單元則同時記錄讀音與字詞 + strCurrent = kvCurrent.key - for (theIndex, theAnchor) in arrNodesReversed.enumerated() { - if strCurrent != "()", let nodeCurrent = theAnchor.node { - let keyCurrent = nodeCurrent.currentKeyValue().key - let valCurrent = nodeCurrent.currentKeyValue().value - strCurrent = "(\(keyCurrent), \(valCurrent))" - if let nodePrev = arrNodesReversed[theIndex + 1].node { - let keyPrev = nodePrev.currentKeyValue().key - let valPrev = nodePrev.currentKeyValue().value - strPrev = "(\(keyPrev), \(valPrev))" - } - if let nodeAnterior = arrNodesReversed[theIndex + 2].node { - let keyAnterior = nodeAnterior.currentKeyValue().key - let valAnterior = nodeAnterior.currentKeyValue().value - strAnterior = "(\(keyAnterior), \(valAnterior))" - } - break // 我們只取第一個有效結果。 - } + if arrNodesReversed.count >= 2, + let kvPrevious = arrNodesReversed[1].node?.currentKeyValue(), + !arrEndingPunctuation.contains(kvPrevious.value) + { + strPrevious = "(\(kvPrevious.key),\(kvPrevious.value))" } - strOutput = "(\(strAnterior),\(strPrev),\(strCurrent))" - if strOutput == "((),(),())" { - strOutput = "" + if arrNodesReversed.count >= 3, + let kvAnterior = arrNodesReversed[2].node?.currentKeyValue(), + !arrEndingPunctuation.contains(kvAnterior.value) + { + strAnterior = "(\(kvAnterior.key),\(kvAnterior.value))" } - return strOutput + return "(\(strAnterior),\(strPrevious),\(strCurrent))" } } } From 2b38dd28e64858150c9b71d2f671b816165c5e8c Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 15:57:11 +0800 Subject: [PATCH 15/24] KeyHandler_Core // Add debug messages for LMUserOverride. --- Source/Modules/ControllerModules/KeyHandler_Core.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index f05f659a..329d8301 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -171,17 +171,20 @@ class KeyHandler: NSObject { // in the user override model. var addToUserOverrideModel = true if selectedNode.spanningLength != value.count { + IME.prtDebugIntel("UOM: SpanningLength != value.count, dismissing.") addToUserOverrideModel = false } if addToUserOverrideModel { if let theNode = selectedNode.node { // 威注音的 SymbolLM 的 Score 是 -12。 if theNode.scoreFor(candidate: value) <= -12 { + IME.prtDebugIntel("UOM: Score <= -12, dismissing.") addToUserOverrideModel = false } } } if addToUserOverrideModel { + IME.prtDebugIntel("UOM: Start Observation.") _userOverrideModel.observe( walkedNodes: _walkedNodes, cursorIndex: cursorIndex, candidate: value, timestamp: NSDate().timeIntervalSince1970 @@ -237,11 +240,15 @@ class KeyHandler: NSObject { ) if !overrideValue.isEmpty { + IME.prtDebugIntel( + "UOM: Suggestion retrieved, overriding the node score of the selected candidate.") _builder.grid().overrideNodeScoreForSelectedCandidate( location: getActualCandidateCursorIndex(), value: overrideValue, overridingScore: findHighestScore(nodes: getRawNodes(), epsilon: kEpsilon) ) + } else { + IME.prtDebugIntel("UOM: Blank suggestion retrieved, dismissing.") } } From 461f94fec45bbd6eb7ca37d1dcd52e444eb49783 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 16:00:45 +0800 Subject: [PATCH 16/24] KeyHandler_Core // Use walk() in lieu of reverseWalk(). --- .../ControllerModules/KeyHandler_Core.swift | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index 329d8301..7c7b0ff6 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -117,15 +117,11 @@ class KeyHandler: NSObject { func walk() { // Retrieve the most likely grid, i.e. a Maximum Likelihood Estimation // of the best possible Mandarin characters given the input syllables, - // using the Viterbi algorithm implemented in the Megrez library - let walker = Megrez.Walker(grid: _builder.grid()) - - // the reverse walk traces the grid from the end - let walked = walker.reverseWalk(at: _builder.grid().width(), nodesLimit: 3, balanced: true) - - // then we use ".reversed()" to reverse the nodes so that we get the forward-walked nodes - _walkedNodes.removeAll() - _walkedNodes.append(contentsOf: walked.reversed()) + // using the Viterbi algorithm implemented in the Megrez library. + // The walk() traces the grid to the end, hence no need to use .reversed() here. + _walkedNodes = Megrez.Walker( + grid: _builder.grid() + ).walk(at: _builder.grid().width(), nodesLimit: 3, balanced: true) } func popOverflowComposingTextAndWalk() -> String { @@ -365,5 +361,4 @@ class KeyHandler: NSObject { } _composer.clear() } - } From 2c23ba3a118df66c44b191dce4ce820bcc1b2ff5 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Mon, 16 May 2022 23:50:51 +0800 Subject: [PATCH 17/24] Repo // Remove NSObject(Protocol) wherever it's safe to remove. --- .../Modules/ControllerModules/InputState.swift | 18 ++++++++---------- .../ControllerModules/KeyHandler_Core.swift | 9 ++++----- .../vChewingKanjiConverter.swift | 2 +- .../FileHandlers/FSEventStreamHelper.swift | 2 +- Source/Modules/IMEModules/IME.swift | 2 +- Source/Modules/IMEModules/mgrPrefs.swift | 2 +- .../LangModelRelated/mgrLangModel.swift | 2 +- 7 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Source/Modules/ControllerModules/InputState.swift b/Source/Modules/ControllerModules/InputState.swift index f03ecda2..c262c933 100644 --- a/Source/Modules/ControllerModules/InputState.swift +++ b/Source/Modules/ControllerModules/InputState.swift @@ -57,10 +57,10 @@ import Cocoa /// create a new user phrase. /// - Choosing Candidate: The candidate window is open to let the user to choose /// one among the candidates. -class InputState: NSObject { +class InputState { /// Represents that the input controller is deactivated. class Deactivated: InputState { - override var description: String { + var description: String { "" } } @@ -73,7 +73,7 @@ class InputState: NSObject { "" } - override var description: String { + var description: String { "" } } @@ -86,7 +86,7 @@ class InputState: NSObject { "" } - override var description: String { + var description: String { "" } } @@ -102,7 +102,7 @@ class InputState: NSObject { self.poppedText = poppedText } - override var description: String { + var description: String { "" } } @@ -119,7 +119,7 @@ class InputState: NSObject { self.cursorIndex = cursorIndex } - override var description: String { + var description: String { "" } } @@ -398,7 +398,7 @@ class InputState: NSObject { super.init() } - override var description: String { + var description: String { "" } } @@ -421,20 +421,18 @@ class InputState: NSObject { } } -class SymbolNode: NSObject { +class SymbolNode { var title: String var children: [SymbolNode]? init(_ title: String, _ children: [SymbolNode]? = nil) { self.title = title self.children = children - super.init() } init(_ title: String, symbols: String) { self.title = title children = Array(symbols).map { SymbolNode(String($0), nil) } - super.init() } static let catCommonSymbols = String( diff --git a/Source/Modules/ControllerModules/KeyHandler_Core.swift b/Source/Modules/ControllerModules/KeyHandler_Core.swift index 7c7b0ff6..74883d32 100644 --- a/Source/Modules/ControllerModules/KeyHandler_Core.swift +++ b/Source/Modules/ControllerModules/KeyHandler_Core.swift @@ -34,7 +34,7 @@ public enum InputMode: String { // MARK: - Delegate. -protocol KeyHandlerDelegate: NSObjectProtocol { +protocol KeyHandlerDelegate { func ctlCandidate(for _: KeyHandler) -> Any func keyHandler( _: KeyHandler, didSelectCandidateAt index: Int, @@ -46,7 +46,7 @@ protocol KeyHandlerDelegate: NSObjectProtocol { // MARK: - Kernel. -class KeyHandler: NSObject { +class KeyHandler { let kEpsilon: Double = 0.000001 var _composer: Tekkon.Composer = .init() var _inputMode: String = "" @@ -55,7 +55,7 @@ class KeyHandler: NSObject { var _builder: Megrez.BlockReadingBuilder var _walkedNodes: [Megrez.NodeAnchor] = [] - weak var delegate: KeyHandlerDelegate? + var delegate: KeyHandlerDelegate? var inputMode: InputMode { get { @@ -71,9 +71,8 @@ class KeyHandler: NSObject { set { setInputMode(newValue.rawValue) } } - override init() { + public init() { _builder = Megrez.BlockReadingBuilder(lm: _languageModel) - super.init() ensureParser() setInputMode(ctlInputMethod.currentInputMode) } diff --git a/Source/Modules/ControllerModules/vChewingKanjiConverter.swift b/Source/Modules/ControllerModules/vChewingKanjiConverter.swift index c87692a3..bf95a42e 100644 --- a/Source/Modules/ControllerModules/vChewingKanjiConverter.swift +++ b/Source/Modules/ControllerModules/vChewingKanjiConverter.swift @@ -30,7 +30,7 @@ extension String { } } -class vChewingKanjiConverter: NSObject { +class vChewingKanjiConverter { class func cnvTradToKangXi(_ strObj: String) -> String { var strObj = strObj strObj.selfReplace("偽", "僞") diff --git a/Source/Modules/FileHandlers/FSEventStreamHelper.swift b/Source/Modules/FileHandlers/FSEventStreamHelper.swift index 69e5eff5..fe27953d 100644 --- a/Source/Modules/FileHandlers/FSEventStreamHelper.swift +++ b/Source/Modules/FileHandlers/FSEventStreamHelper.swift @@ -30,7 +30,7 @@ public protocol FSEventStreamHelperDelegate: AnyObject { func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event]) } -public class FSEventStreamHelper: NSObject { +public class FSEventStreamHelper { public struct Event { var path: String var flags: FSEventStreamEventFlags diff --git a/Source/Modules/IMEModules/IME.swift b/Source/Modules/IMEModules/IME.swift index df50d1b3..146316ec 100644 --- a/Source/Modules/IMEModules/IME.swift +++ b/Source/Modules/IMEModules/IME.swift @@ -28,7 +28,7 @@ import Cocoa // The namespace of this input method. public enum vChewing {} -public class IME: NSObject { +public class IME { static let arrSupportedLocales = ["en", "zh-Hant", "zh-Hans", "ja"] static let dlgOpenPath = NSOpenPanel() diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index 0bee5acc..0419b3b1 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -215,7 +215,7 @@ struct ComposingBufferSize { // MARK: - -public class mgrPrefs: NSObject { +public class mgrPrefs { static var allKeys: [String] { [ UserDef.kIsDebugModeEnabled, diff --git a/Source/Modules/LangModelRelated/mgrLangModel.swift b/Source/Modules/LangModelRelated/mgrLangModel.swift index b72c0441..09ce44a4 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.swift +++ b/Source/Modules/LangModelRelated/mgrLangModel.swift @@ -36,7 +36,7 @@ private var gLangModelCHT = vChewing.LMInstantiator() private var gUserOverrideModelCHS = vChewing.LMUserOverride() private var gUserOverrideModelCHT = vChewing.LMUserOverride() -class mgrLangModel: NSObject { +class mgrLangModel { /// 寫幾個回傳函數、供其餘控制模組來讀取那些被設為 fileprivate 的器外變數。 public static var lmCHS: vChewing.LMInstantiator { gLangModelCHS } public static var lmCHT: vChewing.LMInstantiator { gLangModelCHT } From bab4399860954ca22c55878c6c247e7f9368bf2e Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 16:45:36 +0800 Subject: [PATCH 18/24] Repo // Use enum in lieu of class when appropriate. --- Source/Modules/IMEModules/IME.swift | 2 +- Source/Modules/IMEModules/mgrPrefs.swift | 8 +++++--- Source/Modules/LangModelRelated/mgrLangModel.swift | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Modules/IMEModules/IME.swift b/Source/Modules/IMEModules/IME.swift index 146316ec..4ae72006 100644 --- a/Source/Modules/IMEModules/IME.swift +++ b/Source/Modules/IMEModules/IME.swift @@ -28,7 +28,7 @@ import Cocoa // The namespace of this input method. public enum vChewing {} -public class IME { +public enum IME { static let arrSupportedLocales = ["en", "zh-Hant", "zh-Hans", "ja"] static let dlgOpenPath = NSOpenPanel() diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index 0419b3b1..fa2ff9b1 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -215,7 +215,7 @@ struct ComposingBufferSize { // MARK: - -public class mgrPrefs { +public enum mgrPrefs { static var allKeys: [String] { [ UserDef.kIsDebugModeEnabled, @@ -293,9 +293,11 @@ public class mgrPrefs { UserDefaults.standard.setDefault(mgrPrefs.phraseReplacementEnabled, forKey: UserDef.kPhraseReplacementEnabled) UserDefaults.standard.setDefault(mgrPrefs.shouldNotFartInLieuOfBeep, forKey: UserDef.kShouldNotFartInLieuOfBeep) UserDefaults.standard.setDefault( - mgrPrefs.showHanyuPinyinInCompositionBuffer, forKey: UserDef.kShowHanyuPinyinInCompositionBuffer) + mgrPrefs.showHanyuPinyinInCompositionBuffer, forKey: UserDef.kShowHanyuPinyinInCompositionBuffer + ) UserDefaults.standard.setDefault( - mgrPrefs.inlineDumpPinyinInLieuOfZhuyin, forKey: UserDef.kInlineDumpPinyinInLieuOfZhuyin) + mgrPrefs.inlineDumpPinyinInLieuOfZhuyin, forKey: UserDef.kInlineDumpPinyinInLieuOfZhuyin + ) UserDefaults.standard.synchronize() } diff --git a/Source/Modules/LangModelRelated/mgrLangModel.swift b/Source/Modules/LangModelRelated/mgrLangModel.swift index 09ce44a4..ab6a17d7 100644 --- a/Source/Modules/LangModelRelated/mgrLangModel.swift +++ b/Source/Modules/LangModelRelated/mgrLangModel.swift @@ -36,7 +36,7 @@ private var gLangModelCHT = vChewing.LMInstantiator() private var gUserOverrideModelCHS = vChewing.LMUserOverride() private var gUserOverrideModelCHT = vChewing.LMUserOverride() -class mgrLangModel { +enum mgrLangModel { /// 寫幾個回傳函數、供其餘控制模組來讀取那些被設為 fileprivate 的器外變數。 public static var lmCHS: vChewing.LMInstantiator { gLangModelCHS } public static var lmCHT: vChewing.LMInstantiator { gLangModelCHT } From 3b24f802c1f7694d0f3ed46579c107abcb887f45 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 18:06:27 +0800 Subject: [PATCH 19/24] LMInstantiator // Reenable previous procedure of deduplicating candidates. --- Source/Modules/LangModelRelated/LMInstantiator.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Modules/LangModelRelated/LMInstantiator.swift b/Source/Modules/LangModelRelated/LMInstantiator.swift index 583a942f..00794148 100644 --- a/Source/Modules/LangModelRelated/LMInstantiator.swift +++ b/Source/Modules/LangModelRelated/LMInstantiator.swift @@ -270,6 +270,7 @@ extension vChewing { filter filteredPairs: Set ) -> [Megrez.Unigram] { var results: [Megrez.Unigram] = [] + var insertedPairs: Set = [] for unigram in unigrams { var pair: Megrez.KeyValuePair = unigram.keyValue @@ -284,12 +285,13 @@ extension vChewing { pair.value = replacement } } - results.append(Megrez.Unigram(keyValue: pair, score: unigram.score)) - } - // Swift 不見得非得用 Swift-Collections 才可以用 OrderedSet,還有 NSOrderedSet 可用來去重複。 - let resultsDeduplicated = Array(NSOrderedSet(array: results).array as! [Megrez.Unigram]) - return resultsDeduplicated + if !insertedPairs.contains(pair) { + results.append(Megrez.Unigram(keyValue: pair, score: unigram.score)) + insertedPairs.insert(pair) + } + } + return results } } } From 3b3ef8ca0e25692da52974a208ce0634403dddb3 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 16:44:57 +0800 Subject: [PATCH 20/24] LMAssociates // Clang-format. --- Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift index e45554c6..2740e293 100644 --- a/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift +++ b/Source/Modules/LangModelRelated/SubLMs/lmAssociates.swift @@ -95,7 +95,7 @@ extension vChewing { if let arrRangeRecords: [Range] = rangeMap[key] { for netaRange in arrRangeRecords { let neta = strData[netaRange].split(separator: " ") - let theValue: String = String(neta[1]) + let theValue: String = .init(neta[1]) pairs.append(theValue) } } From 346eb537d72b5b63ec2b506118aa1c5ad24c87f7 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 16:54:09 +0800 Subject: [PATCH 21/24] Repo // Remove @objc whenever necessary. --- Source/Modules/FileHandlers/FSEventStreamHelper.swift | 2 +- Source/Modules/IMEModules/mgrPrefs.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Modules/FileHandlers/FSEventStreamHelper.swift b/Source/Modules/FileHandlers/FSEventStreamHelper.swift index fe27953d..49cc7878 100644 --- a/Source/Modules/FileHandlers/FSEventStreamHelper.swift +++ b/Source/Modules/FileHandlers/FSEventStreamHelper.swift @@ -41,7 +41,7 @@ public class FSEventStreamHelper { public let dispatchQueue: DispatchQueue public weak var delegate: FSEventStreamHelperDelegate? - @objc public init(path: String, queue: DispatchQueue) { + public init(path: String, queue: DispatchQueue) { self.path = path dispatchQueue = queue } diff --git a/Source/Modules/IMEModules/mgrPrefs.swift b/Source/Modules/IMEModules/mgrPrefs.swift index fa2ff9b1..70d80662 100644 --- a/Source/Modules/IMEModules/mgrPrefs.swift +++ b/Source/Modules/IMEModules/mgrPrefs.swift @@ -166,7 +166,7 @@ struct ComposingBufferSize { // MARK: - -@objc enum MandarinParser: Int { +enum MandarinParser: Int { case ofStandard = 0 case ofEten = 1 case ofHsu = 2 @@ -327,7 +327,7 @@ public enum mgrPrefs { static var appleLanguages: [String] @UserDefault(key: UserDef.kMandarinParser, defaultValue: 0) - @objc static var mandarinParser: Int + static var mandarinParser: Int static var mandarinParserName: String { (MandarinParser(rawValue: mandarinParser) ?? MandarinParser.ofStandard).name From 03e3a394899a4123aed69370580d1a4e175b3aa0 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 17:08:07 +0800 Subject: [PATCH 22/24] Makefile // Remove Cpp clang-format commands. --- Makefile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 5a9608c9..991783cd 100644 --- a/Makefile +++ b/Makefile @@ -24,21 +24,19 @@ VC_APP_ROOT = $(DSTROOT)/vChewing.app format: batchfix clang-format lint -clang-format: clang-format-swift clang-format-cpp - -clang-format-swift: +clang-format: @git ls-files --exclude-standard | grep -E '\.swift$$' | xargs swift-format format --in-place --configuration ./.clang-format-swift.json --parallel @git ls-files --exclude-standard | grep -E '\.swift$$' | xargs swift-format lint --configuration ./.clang-format-swift.json --parallel -clang-format-cpp: - @git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx|h|m|mm|hh)$$' | xargs clang-format -i - lint: @git ls-files --exclude-standard | grep -E '\.swift$$' | xargs swift-format lint --configuration ./.clang-format-swift.json --parallel batchfix: @git ls-files --exclude-standard | grep -E '\.swift$$' | swiftlint --fix --autocorrect +advanced-lint: + @swiftformat --swiftversion 5.5 --indent 2 ./ + .PHONY: permission-check install-debug install-release permission-check: From 3a358d0022de6c8b95cdcf21558d0c65daf8b074 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Tue, 17 May 2022 23:23:48 +0800 Subject: [PATCH 23/24] Update Data - 20220518 --- Source/Data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Data b/Source/Data index 383ad9af..1d2c6ac9 160000 --- a/Source/Data +++ b/Source/Data @@ -1 +1 @@ -Subproject commit 383ad9af7dd6f9ffa58ad2560e186bf06ffea3ad +Subproject commit 1d2c6ac9571e3ef3552a1b610e26626d38af69cb From 6b942e148e69712411db43ccf31029ddb53e679d Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 18 May 2022 00:10:49 +0800 Subject: [PATCH 24/24] Bump version to 1.5.9 Build 1959. --- Update-Info.plist | 4 ++-- vChewing.pkgproj | 2 +- vChewing.xcodeproj/project.pbxproj | 24 ++++++++++++------------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Update-Info.plist b/Update-Info.plist index c718e716..e7e30f11 100644 --- a/Update-Info.plist +++ b/Update-Info.plist @@ -3,9 +3,9 @@ CFBundleShortVersionString - 1.5.8 + 1.5.9 CFBundleVersion - 1958 + 1959 UpdateInfoEndpoint https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist UpdateInfoSite diff --git a/vChewing.pkgproj b/vChewing.pkgproj index eab600c5..ed9d49b0 100644 --- a/vChewing.pkgproj +++ b/vChewing.pkgproj @@ -726,7 +726,7 @@ USE_HFS+_COMPRESSION VERSION - 1.5.8 + 1.5.9 TYPE 0 diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 504beb88..eb37c133 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -1296,7 +1296,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1958; + CURRENT_PROJECT_VERSION = 1959; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; @@ -1319,7 +1319,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1352,7 +1352,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1958; + CURRENT_PROJECT_VERSION = 1959; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -1371,7 +1371,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; @@ -1486,7 +1486,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1958; + CURRENT_PROJECT_VERSION = 1959; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1521,7 +1521,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1553,7 +1553,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1958; + CURRENT_PROJECT_VERSION = 1959; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = ""; @@ -1583,7 +1583,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1666,7 +1666,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1958; + CURRENT_PROJECT_VERSION = 1959; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; @@ -1691,7 +1691,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1718,7 +1718,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1958; + CURRENT_PROJECT_VERSION = 1959; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1738,7 +1738,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11.5; - MARKETING_VERSION = 1.5.8; + MARKETING_VERSION = 1.5.9; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";