1.8.1 // Associates. Merge Gitee PR!63 from upd/1.8.1
|
@ -60,9 +60,9 @@ extension String {
|
|||
// MARK: - 引入小數點位數控制函式
|
||||
|
||||
// Ref: https://stackoverflow.com/a/32581409/4162914
|
||||
extension Float {
|
||||
fileprivate func rounded(toPlaces places: Int) -> Float {
|
||||
let divisor = pow(10.0, Float(places))
|
||||
extension Double {
|
||||
fileprivate func rounded(toPlaces places: Int) -> Double {
|
||||
let divisor = pow(10.0, Double(places))
|
||||
return (self * divisor).rounded() / divisor
|
||||
}
|
||||
}
|
||||
|
@ -81,17 +81,16 @@ func ** (_ base: Double, _ exp: Double) -> Double {
|
|||
pow(base, exp)
|
||||
}
|
||||
|
||||
func ** (_ base: Float, _ exp: Float) -> Float {
|
||||
pow(base, exp)
|
||||
}
|
||||
|
||||
// MARK: - 定義檔案結構
|
||||
|
||||
struct Entry {
|
||||
var valPhone: String = ""
|
||||
var valPhrase: String = ""
|
||||
var valWeight: Float = -1.0
|
||||
var valCount: Int = 0
|
||||
struct Unigram: CustomStringConvertible {
|
||||
var key: String = ""
|
||||
var value: String = ""
|
||||
var score: Double = -1.0
|
||||
var count: Int = 0
|
||||
var description: String {
|
||||
"(\(key), \(value), \(score))"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 注音加密,減少 plist 體積
|
||||
|
@ -105,8 +104,8 @@ func cnvPhonabetToASCII(_ incoming: String) -> String {
|
|||
]
|
||||
var strOutput = incoming
|
||||
if !strOutput.contains("_") {
|
||||
for entry in dicPhonabet2ASCII {
|
||||
strOutput = strOutput.replacingOccurrences(of: entry.key, with: entry.value)
|
||||
for Unigram in dicPhonabet2ASCII {
|
||||
strOutput = strOutput.replacingOccurrences(of: Unigram.key, with: Unigram.value)
|
||||
}
|
||||
}
|
||||
return strOutput
|
||||
|
@ -146,8 +145,8 @@ private let urlPlistCHT: String = "./data-cht.plist"
|
|||
|
||||
// MARK: - 載入詞組檔案且輸出陣列
|
||||
|
||||
func rawDictForPhrases(isCHS: Bool) -> [Entry] {
|
||||
var arrEntryRAW: [Entry] = []
|
||||
func rawDictForPhrases(isCHS: Bool) -> [Unigram] {
|
||||
var arrUnigramRAW: [Unigram] = []
|
||||
var strRAW = ""
|
||||
let urlCustom: String = isCHS ? urlCHSforCustom : urlCHTforCustom
|
||||
let urlTABE: String = isCHS ? urlCHSforTABE : urlCHTforTABE
|
||||
|
@ -195,7 +194,7 @@ func rawDictForPhrases(isCHS: Bool) -> [Entry] {
|
|||
varLineDataProcessed += currentCell
|
||||
}
|
||||
}
|
||||
// 然後直接乾脆就轉成 Entry 吧。
|
||||
// 然後直接乾脆就轉成 Unigram 吧。
|
||||
let arrCells: [String] = varLineDataProcessed.components(separatedBy: "\t")
|
||||
count = 0 // 不需要再定義,因為之前已經有定義過了。
|
||||
var phone = ""
|
||||
|
@ -211,22 +210,22 @@ func rawDictForPhrases(isCHS: Bool) -> [Entry] {
|
|||
}
|
||||
}
|
||||
if phrase != "" { // 廢掉空數據;之後無須再這樣處理。
|
||||
arrEntryRAW += [
|
||||
Entry(
|
||||
valPhone: phone, valPhrase: phrase, valWeight: 0.0,
|
||||
valCount: occurrence
|
||||
arrUnigramRAW += [
|
||||
Unigram(
|
||||
key: phone, value: phrase, score: 0.0,
|
||||
count: occurrence
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
||||
NSLog(" - \(i18n): 成功生成詞語語料辭典(權重待計算)。")
|
||||
return arrEntryRAW
|
||||
return arrUnigramRAW
|
||||
}
|
||||
|
||||
// MARK: - 載入單字檔案且輸出陣列
|
||||
|
||||
func rawDictForKanjis(isCHS: Bool) -> [Entry] {
|
||||
var arrEntryRAW: [Entry] = []
|
||||
func rawDictForKanjis(isCHS: Bool) -> [Unigram] {
|
||||
var arrUnigramRAW: [Unigram] = []
|
||||
var strRAW = ""
|
||||
let i18n: String = isCHS ? "簡體中文" : "繁體中文"
|
||||
// 讀取內容
|
||||
|
@ -272,7 +271,7 @@ func rawDictForKanjis(isCHS: Bool) -> [Entry] {
|
|||
varLineDataProcessed += currentCell
|
||||
}
|
||||
}
|
||||
// 然後直接乾脆就轉成 Entry 吧。
|
||||
// 然後直接乾脆就轉成 Unigram 吧。
|
||||
let arrCells: [String] = varLineDataProcessed.components(separatedBy: "\t")
|
||||
count = 0 // 不需要再定義,因為之前已經有定義過了。
|
||||
var phone = ""
|
||||
|
@ -288,22 +287,22 @@ func rawDictForKanjis(isCHS: Bool) -> [Entry] {
|
|||
}
|
||||
}
|
||||
if phrase != "" { // 廢掉空數據;之後無須再這樣處理。
|
||||
arrEntryRAW += [
|
||||
Entry(
|
||||
valPhone: phone, valPhrase: phrase, valWeight: 0.0,
|
||||
valCount: occurrence
|
||||
arrUnigramRAW += [
|
||||
Unigram(
|
||||
key: phone, value: phrase, score: 0.0,
|
||||
count: occurrence
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
||||
NSLog(" - \(i18n): 成功生成單字語料辭典(權重待計算)。")
|
||||
return arrEntryRAW
|
||||
return arrUnigramRAW
|
||||
}
|
||||
|
||||
// MARK: - 載入非漢字檔案且輸出陣列
|
||||
|
||||
func rawDictForNonKanjis(isCHS: Bool) -> [Entry] {
|
||||
var arrEntryRAW: [Entry] = []
|
||||
func rawDictForNonKanjis(isCHS: Bool) -> [Unigram] {
|
||||
var arrUnigramRAW: [Unigram] = []
|
||||
var strRAW = ""
|
||||
let i18n: String = isCHS ? "簡體中文" : "繁體中文"
|
||||
// 讀取內容
|
||||
|
@ -347,7 +346,7 @@ func rawDictForNonKanjis(isCHS: Bool) -> [Entry] {
|
|||
varLineDataProcessed += currentCell
|
||||
}
|
||||
}
|
||||
// 然後直接乾脆就轉成 Entry 吧。
|
||||
// 然後直接乾脆就轉成 Unigram 吧。
|
||||
let arrCells: [String] = varLineDataProcessed.components(separatedBy: "\t")
|
||||
count = 0 // 不需要再定義,因為之前已經有定義過了。
|
||||
var phone = ""
|
||||
|
@ -363,60 +362,60 @@ func rawDictForNonKanjis(isCHS: Bool) -> [Entry] {
|
|||
}
|
||||
}
|
||||
if phrase != "" { // 廢掉空數據;之後無須再這樣處理。
|
||||
arrEntryRAW += [
|
||||
Entry(
|
||||
valPhone: phone, valPhrase: phrase, valWeight: 0.0,
|
||||
valCount: occurrence
|
||||
arrUnigramRAW += [
|
||||
Unigram(
|
||||
key: phone, value: phrase, score: 0.0,
|
||||
count: occurrence
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
||||
NSLog(" - \(i18n): 成功生成非漢字語料辭典(權重待計算)。")
|
||||
return arrEntryRAW
|
||||
return arrUnigramRAW
|
||||
}
|
||||
|
||||
func weightAndSort(_ arrStructUncalculated: [Entry], isCHS: Bool) -> [Entry] {
|
||||
func weightAndSort(_ arrStructUncalculated: [Unigram], isCHS: Bool) -> [Unigram] {
|
||||
let i18n: String = isCHS ? "簡體中文" : "繁體中文"
|
||||
var arrStructCalculated: [Entry] = []
|
||||
let fscale: Float = 2.7
|
||||
var norm: Float = 0.0
|
||||
for entry in arrStructUncalculated {
|
||||
if entry.valCount >= 0 {
|
||||
norm += fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0)
|
||||
* Float(entry.valCount)
|
||||
var arrStructCalculated: [Unigram] = []
|
||||
let fscale = 2.7
|
||||
var norm = 0.0
|
||||
for unigram in arrStructUncalculated {
|
||||
if unigram.count >= 0 {
|
||||
norm += fscale ** (Double(unigram.value.count) / 3.0 - 1.0)
|
||||
* Double(unigram.count)
|
||||
}
|
||||
}
|
||||
// norm 計算完畢,開始將 norm 作為新的固定常數來為每個詞條記錄計算權重。
|
||||
// 將新酷音的詞語出現次數數據轉換成小麥引擎可讀的數據形式。
|
||||
// 對出現次數小於 1 的詞條,將 0 當成 0.5 來處理、以防止除零。
|
||||
for entry in arrStructUncalculated {
|
||||
var weight: Float = 0
|
||||
switch entry.valCount {
|
||||
for unigram in arrStructUncalculated {
|
||||
var weight: Double = 0
|
||||
switch unigram.count {
|
||||
case -2: // 拗音假名
|
||||
weight = -13
|
||||
case -1: // 單個假名
|
||||
weight = -13
|
||||
case 0: // 墊底低頻漢字與詞語
|
||||
weight = log10(
|
||||
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0) * 0.25 / norm)
|
||||
fscale ** (Double(unigram.value.count) / 3.0 - 1.0) * 0.25 / norm)
|
||||
default:
|
||||
weight = log10(
|
||||
fscale ** (Float(entry.valPhrase.count) / 3.0 - 1.0)
|
||||
* Float(entry.valCount) / norm) // Credit: MJHsieh.
|
||||
fscale ** (Double(unigram.value.count) / 3.0 - 1.0)
|
||||
* Double(unigram.count) / norm) // Credit: MJHsieh.
|
||||
}
|
||||
let weightRounded: Float = weight.rounded(toPlaces: 3) // 為了節省生成的檔案體積,僅保留小數點後三位。
|
||||
let weightRounded: Double = weight.rounded(toPlaces: 3) // 為了節省生成的檔案體積,僅保留小數點後三位。
|
||||
arrStructCalculated += [
|
||||
Entry(
|
||||
valPhone: entry.valPhone, valPhrase: entry.valPhrase, valWeight: weightRounded,
|
||||
valCount: entry.valCount
|
||||
Unigram(
|
||||
key: unigram.key, value: unigram.value, score: weightRounded,
|
||||
count: unigram.count
|
||||
)
|
||||
]
|
||||
}
|
||||
NSLog(" - \(i18n): 成功計算權重。")
|
||||
// ==========================================
|
||||
// 接下來是排序,先按照注音遞減排序一遍、再按照權重遞減排序一遍。
|
||||
let arrStructSorted: [Entry] = arrStructCalculated.sorted(by: { lhs, rhs -> Bool in
|
||||
(lhs.valPhone, rhs.valCount) < (rhs.valPhone, lhs.valCount)
|
||||
let arrStructSorted: [Unigram] = arrStructCalculated.sorted(by: { lhs, rhs -> Bool in
|
||||
(lhs.key, rhs.count) < (rhs.key, lhs.count)
|
||||
})
|
||||
NSLog(" - \(i18n): 排序整理完畢,準備編譯要寫入的檔案內容。")
|
||||
return arrStructSorted
|
||||
|
@ -434,9 +433,11 @@ func fileOutput(isCHS: Bool) {
|
|||
// 讀取標點內容
|
||||
do {
|
||||
strPunctuation = try String(contentsOfFile: urlPunctuation, encoding: .utf8).replacingOccurrences(
|
||||
of: "\t", with: " ")
|
||||
of: "\t", with: " "
|
||||
)
|
||||
strPrintLine += try String(contentsOfFile: urlPunctuation, encoding: .utf8).replacingOccurrences(
|
||||
of: "\t", with: " ")
|
||||
of: "\t", with: " "
|
||||
)
|
||||
} catch {
|
||||
NSLog(" - \(i18n): Exception happened when reading raw punctuation data.")
|
||||
}
|
||||
|
@ -453,18 +454,33 @@ func fileOutput(isCHS: Bool) {
|
|||
}
|
||||
}
|
||||
}
|
||||
var arrStructUnified: [Entry] = []
|
||||
var arrStructUnified: [Unigram] = []
|
||||
arrStructUnified += rawDictForKanjis(isCHS: isCHS)
|
||||
arrStructUnified += rawDictForNonKanjis(isCHS: isCHS)
|
||||
arrStructUnified += rawDictForPhrases(isCHS: isCHS)
|
||||
// 計算權重且排序
|
||||
arrStructUnified = weightAndSort(arrStructUnified, isCHS: isCHS)
|
||||
for entry in arrStructUnified {
|
||||
let theKey = entry.valPhone
|
||||
let theValue = (String(entry.valWeight) + " " + entry.valPhrase)
|
||||
|
||||
// 資料重複性檢查
|
||||
NSLog(" - \(i18n): 執行資料重複性檢查,會在之後再給出對應的檢查結果。")
|
||||
var setAlreadyInserted = Set<String>()
|
||||
var arrFoundedDuplications = [String]()
|
||||
|
||||
// 健康狀況檢查
|
||||
NSLog(" - \(i18n): 執行資料健康狀況檢查。")
|
||||
print(healthCheck(arrStructUnified))
|
||||
for unigram in arrStructUnified {
|
||||
if setAlreadyInserted.contains(unigram.value + "\t" + unigram.key) {
|
||||
arrFoundedDuplications.append(unigram.value + "\t" + unigram.key)
|
||||
} else {
|
||||
setAlreadyInserted.insert(unigram.value + "\t" + unigram.key)
|
||||
}
|
||||
|
||||
let theKey = unigram.key
|
||||
let theValue = (String(unigram.score) + " " + unigram.value)
|
||||
rangeMap[cnvPhonabetToASCII(theKey), default: []].append(theValue.data(using: .utf8)!)
|
||||
strPrintLine +=
|
||||
entry.valPhone + " " + entry.valPhrase + " " + String(entry.valWeight)
|
||||
unigram.key + " " + unigram.value + " " + String(unigram.score)
|
||||
+ "\n"
|
||||
}
|
||||
NSLog(" - \(i18n): 要寫入檔案的 txt 內容編譯完畢。")
|
||||
|
@ -476,6 +492,12 @@ func fileOutput(isCHS: Bool) {
|
|||
NSLog(" - \(i18n): Error on writing strings to file: \(error)")
|
||||
}
|
||||
NSLog(" - \(i18n): 寫入完成。")
|
||||
if !arrFoundedDuplications.isEmpty {
|
||||
NSLog(" - \(i18n): 尋得下述重複項目,請務必手動排查:")
|
||||
print("-------------------")
|
||||
print(arrFoundedDuplications.joined(separator: "\n"))
|
||||
}
|
||||
print("===================")
|
||||
}
|
||||
|
||||
func commonFileOutput() {
|
||||
|
@ -555,3 +577,268 @@ func main() {
|
|||
}
|
||||
|
||||
main()
|
||||
|
||||
// MARK: - 辭庫健康狀況檢查專用函式
|
||||
|
||||
func healthCheck(_ data: [Unigram]) -> String {
|
||||
var result = ""
|
||||
var unigramMonoChar = [String: Unigram]()
|
||||
var valueToScore = [String: Double]()
|
||||
let unigramMonoCharCounter = data.filter { $0.score > -14 && $0.key.split(separator: "-").count == 1 }.count
|
||||
let unigramPolyCharCounter = data.filter { $0.score > -14 && $0.key.split(separator: "-").count > 1 }.count
|
||||
|
||||
// 核心字詞庫的內容頻率一般大於 -10,但也得考慮某些包含假名的合成詞。
|
||||
for neta in data.filter({ $0.score > -14 }) {
|
||||
valueToScore[neta.value] = max(neta.score, valueToScore[neta.value] ?? -14)
|
||||
let theKeySliceArr = neta.key.split(separator: "-")
|
||||
guard let theKey = theKeySliceArr.first, theKeySliceArr.count == 1 else { continue }
|
||||
if unigramMonoChar.keys.contains(String(theKey)), let theRecord = unigramMonoChar[String(theKey)] {
|
||||
if neta.score > theRecord.score { unigramMonoChar[String(theKey)] = neta }
|
||||
} else {
|
||||
unigramMonoChar[String(theKey)] = neta
|
||||
}
|
||||
}
|
||||
|
||||
var faulty = [Unigram]()
|
||||
var indifferents: [(String, String, Double, [Unigram], Double)] = []
|
||||
var insufficients: [(String, String, Double, [Unigram], Double)] = []
|
||||
var competingUnigrams = [(String, Double, String, Double)]()
|
||||
|
||||
for neta in data.filter({ $0.key.split(separator: "-").count >= 2 && $0.score > -14 }) {
|
||||
var competants = [Unigram]()
|
||||
var tscore: Double = 0
|
||||
var bad = false
|
||||
for x in neta.key.split(separator: "-") {
|
||||
if !unigramMonoChar.keys.contains(String(x)) {
|
||||
bad = true
|
||||
break
|
||||
}
|
||||
guard let u = unigramMonoChar[String(x)] else { continue }
|
||||
tscore += u.score
|
||||
competants.append(u)
|
||||
}
|
||||
if bad {
|
||||
faulty.append(neta)
|
||||
continue
|
||||
}
|
||||
if tscore >= neta.score {
|
||||
let instance = (neta.key, neta.value, neta.score, competants, neta.score - tscore)
|
||||
let valueJoined = String(competants.map(\.value).joined(separator: ""))
|
||||
if neta.value == valueJoined {
|
||||
indifferents.append(instance)
|
||||
} else {
|
||||
if valueToScore.keys.contains(valueJoined), neta.value != valueJoined {
|
||||
if let valueJoinedScore = valueToScore[valueJoined], neta.score < valueJoinedScore {
|
||||
competingUnigrams.append((neta.value, neta.score, valueJoined, valueJoinedScore))
|
||||
}
|
||||
}
|
||||
insufficients.append(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insufficients = insufficients.sorted(by: { lhs, rhs -> Bool in
|
||||
(lhs.2) > (rhs.2)
|
||||
})
|
||||
competingUnigrams = competingUnigrams.sorted(by: { lhs, rhs -> Bool in
|
||||
(lhs.1 - lhs.3) > (rhs.1 - rhs.3)
|
||||
})
|
||||
|
||||
let separator: String = {
|
||||
var result = ""
|
||||
for _ in 0..<72 { result += "-" }
|
||||
return result
|
||||
}()
|
||||
|
||||
func printl(_ input: String) {
|
||||
result += input + "\n"
|
||||
}
|
||||
|
||||
printl(separator)
|
||||
printl("持單個字符的有效單元圖數量:\(unigramMonoCharCounter)")
|
||||
printl("持多個字符的有效單元圖數量:\(unigramPolyCharCounter)")
|
||||
|
||||
printl(separator)
|
||||
printl("總結一下那些容易被單個漢字的字頻干擾輸入的詞組單元圖:")
|
||||
printl("因干擾組件和字詞本身完全重疊、而不需要處理的單元圖的數量:\(indifferents.count)")
|
||||
printl(
|
||||
"有 \(insufficients.count) 個複字單元圖被自身成分讀音對應的其它單字單元圖奪權,約佔全部有效單元圖的 \(insufficients.count / unigramPolyCharCounter * 100)%,"
|
||||
)
|
||||
printl("\n其中有:")
|
||||
|
||||
var insufficientsMap = [Int: [(String, String, Double, [Unigram], Double)]]()
|
||||
for x in 2...10 {
|
||||
insufficientsMap[x] = insufficients.filter { $0.0.split(separator: "-").count == x }
|
||||
}
|
||||
|
||||
printl(" \(insufficientsMap[2]?.count ?? 0) 個有效雙字單元圖")
|
||||
printl(" \(insufficientsMap[3]?.count ?? 0) 個有效三字單元圖")
|
||||
printl(" \(insufficientsMap[4]?.count ?? 0) 個有效四字單元圖")
|
||||
printl(" \(insufficientsMap[5]?.count ?? 0) 個有效五字單元圖")
|
||||
printl(" \(insufficientsMap[6]?.count ?? 0) 個有效六字單元圖")
|
||||
printl(" \(insufficientsMap[7]?.count ?? 0) 個有效七字單元圖")
|
||||
printl(" \(insufficientsMap[8]?.count ?? 0) 個有效八字單元圖")
|
||||
printl(" \(insufficientsMap[9]?.count ?? 0) 個有效九字單元圖")
|
||||
printl(" \(insufficientsMap[10]?.count ?? 0) 個有效十字單元圖")
|
||||
|
||||
if let insufficientsMap2 = insufficientsMap[2], !insufficientsMap2.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效雙字單元圖")
|
||||
for (i, content) in insufficientsMap2.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap3 = insufficientsMap[3], !insufficientsMap3.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效三字單元圖")
|
||||
for (i, content) in insufficientsMap3.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap4 = insufficientsMap[4], !insufficientsMap4.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效四字單元圖")
|
||||
for (i, content) in insufficientsMap4.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap5 = insufficientsMap[5], !insufficientsMap5.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效五字單元圖")
|
||||
for (i, content) in insufficientsMap5.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap6 = insufficientsMap[6], !insufficientsMap6.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效六字單元圖")
|
||||
for (i, content) in insufficientsMap6.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap7 = insufficientsMap[7], !insufficientsMap7.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效七字單元圖")
|
||||
for (i, content) in insufficientsMap7.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap8 = insufficientsMap[8], !insufficientsMap8.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效八字單元圖")
|
||||
for (i, content) in insufficientsMap8.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap9 = insufficientsMap[9], !insufficientsMap9.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效九字單元圖")
|
||||
for (i, content) in insufficientsMap9.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if let insufficientsMap10 = insufficientsMap[10], !insufficientsMap10.isEmpty {
|
||||
printl(separator)
|
||||
printl("前二十五個被奪權的有效十字單元圖")
|
||||
for (i, content) in insufficientsMap10.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += content.1 + ","
|
||||
contentToPrint += String(content.2) + ","
|
||||
contentToPrint += "[" + content.3.map(\.description).joined(separator: ",") + "]" + ","
|
||||
contentToPrint += String(content.4) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if !competingUnigrams.isEmpty {
|
||||
printl(separator)
|
||||
printl("也發現有 \(competingUnigrams.count) 個複字單元圖被某些由高頻單字組成的複字單元圖奪權的情況,")
|
||||
printl("例如(前二十五例):")
|
||||
for (i, content) in competingUnigrams.enumerated() {
|
||||
if i == 25 { break }
|
||||
var contentToPrint = "{"
|
||||
contentToPrint += content.0 + ","
|
||||
contentToPrint += String(content.1) + ","
|
||||
contentToPrint += content.2 + ","
|
||||
contentToPrint += String(content.3) + "}"
|
||||
printl(contentToPrint)
|
||||
}
|
||||
}
|
||||
|
||||
if !faulty.isEmpty {
|
||||
printl(separator)
|
||||
printl("下述單元圖用到了漢字核心表當中尚未收錄的讀音,可能無法正常輸入:")
|
||||
for content in faulty {
|
||||
printl(content.description)
|
||||
}
|
||||
}
|
||||
|
||||
result += "\n"
|
||||
return result
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 430 KiB |
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 1.3 MiB |
|
@ -114,7 +114,7 @@
|
|||
|
||||
## 參與研發時的注意事項
|
||||
|
||||
歡迎參與威注音的研發。論及相關細則,請洽請洽該倉庫內的「[CONTRIBUTING.md](./CONTRIBUTING.md)」檔案、以及《[常見問題解答](./FAQ.md)》。
|
||||
歡迎參與威注音的研發。論及相關細則,請洽該倉庫內的「[CONTRIBUTING.md](./CONTRIBUTING.md)」檔案、以及《[常見問題解答](./FAQ.md)》。
|
||||
|
||||
敝專案採用了《[貢獻者品行準則承約書 v2.1](./code-of-conduct.md)》。考慮到上游鏈接給出的中文版翻譯與英文原文嚴重不符合的情況(會出現因執法與被執法雙方的認知偏差導致的矛盾,非常容易變成敵我矛盾),敝專案使用了自行翻譯的版本、且新增了一些能促進雙方共識的註解。
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
|
||||
## 参与研发时的注意事项
|
||||
|
||||
欢迎参与威注音的研发。论及相关细则,请洽请洽该仓库内的「[CONTRIBUTING.md](./CONTRIBUTING.md)」档案、以及《[常见问题解答](./FAQ.md)》。
|
||||
欢迎参与威注音的研发。论及相关细则,请洽该仓库内的「[CONTRIBUTING.md](./CONTRIBUTING.md)」档案、以及《[常见问题解答](./FAQ.md)》。
|
||||
|
||||
敝专案采用了《[贡献者品行准则承约书 v2.1](./code-of-conduct.md)》。考虑到上游链接给出的中文版翻译与英文原文严重不符合的情况(会出现因执法与被执法双方的认知偏差导致的矛盾,非常容易变成敌我矛盾),敝专案使用了自行翻译的版本、且新增了一些能促进双方共识的注解。
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 50250d970a3481ec7653a71120413708a76224d8
|
||||
Subproject commit 345b21db6510caf63184716178837c5563e68123
|
|
@ -149,10 +149,10 @@ class KeyHandler {
|
|||
/// - Parameter key: 給定的聯想詞的開頭字。
|
||||
/// - Returns: 抓取到的聯想詞陣列。
|
||||
/// 不會是 nil,但那些負責接收結果的函式會對空白陣列結果做出正確的處理。
|
||||
func buildAssociatePhraseArray(withKey key: String) -> [(String, String)] {
|
||||
func buildAssociatePhraseArray(withPair pair: Megrez.KeyValuePaired) -> [(String, String)] {
|
||||
var arrResult: [(String, String)] = []
|
||||
if currentLM.hasAssociatedPhrasesFor(key: key) {
|
||||
arrResult = currentLM.associatedPhrasesFor(key: key).map { ("", $0) }
|
||||
if currentLM.hasAssociatedPhrasesFor(pair: pair) {
|
||||
arrResult = currentLM.associatedPhrasesFor(pair: pair).map { ("", $0) }
|
||||
}
|
||||
return arrResult
|
||||
}
|
||||
|
|
|
@ -78,11 +78,6 @@ extension KeyHandler {
|
|||
// MARK: Enter
|
||||
|
||||
if input.isEnter {
|
||||
if state is InputState.AssociatedPhrases {
|
||||
clear()
|
||||
stateCallback(InputState.EmptyIgnoringPreviousState())
|
||||
return true
|
||||
}
|
||||
delegate!.keyHandler(
|
||||
self,
|
||||
didSelectCandidateAt: ctlCandidateCurrent.selectedCandidateIndex,
|
||||
|
|
|
@ -225,6 +225,7 @@ extension KeyHandler {
|
|||
)
|
||||
if choosingCandidates.candidates.count == 1 {
|
||||
clear()
|
||||
let reading: String = choosingCandidates.candidates.first?.0 ?? ""
|
||||
let text: String = choosingCandidates.candidates.first?.1 ?? ""
|
||||
stateCallback(InputState.Committing(textToCommit: text))
|
||||
|
||||
|
@ -233,7 +234,7 @@ extension KeyHandler {
|
|||
} else {
|
||||
if let associatedPhrases =
|
||||
buildAssociatePhraseState(
|
||||
withKey: text,
|
||||
withPair: .init(key: reading, value: text),
|
||||
isTypingVertical: input.isTypingVertical
|
||||
), !associatedPhrases.candidates.isEmpty
|
||||
{
|
||||
|
@ -261,7 +262,7 @@ extension KeyHandler {
|
|||
|
||||
// MARK: 用上下左右鍵呼叫選字窗 (Calling candidate window using Up / Down or PageUp / PageDn.)
|
||||
|
||||
if let currentState = state as? InputState.NotEmpty, composer.isEmpty,
|
||||
if let currentState = state as? InputState.NotEmpty, composer.isEmpty, !input.isOptionHold,
|
||||
input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse || input.isSpace
|
||||
|| input.isPageDown || input.isPageUp || (input.isTab && mgrPrefs.specifyShiftTabKeyBehavior)
|
||||
|| (input.isTypingVertical && (input.isVerticalTypingOnlyChooseCandidateKey))
|
||||
|
@ -353,6 +354,17 @@ extension KeyHandler {
|
|||
// MARK: AbsorbedArrowKey
|
||||
|
||||
if input.isAbsorbedArrowKey || input.isExtraChooseCandidateKey || input.isExtraChooseCandidateKeyReverse {
|
||||
if input.isOptionHold, state.type == .ofInputting {
|
||||
if input.isExtraChooseCandidateKey {
|
||||
return handleInlineCandidateRotation(
|
||||
state: state, reverseModifier: false, stateCallback: stateCallback, errorCallback: errorCallback
|
||||
)
|
||||
} else if input.isExtraChooseCandidateKeyReverse {
|
||||
return handleInlineCandidateRotation(
|
||||
state: state, reverseModifier: true, stateCallback: stateCallback, errorCallback: errorCallback
|
||||
)
|
||||
}
|
||||
}
|
||||
return handleAbsorbedArrowKey(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
|
||||
}
|
||||
|
||||
|
|
|
@ -198,12 +198,12 @@ extension KeyHandler {
|
|||
/// - isTypingVertical: 是否縱排輸入?
|
||||
/// - Returns: 回呼一個新的聯想詞狀態,來就給定的聯想詞陣列資料內容顯示選字窗。
|
||||
func buildAssociatePhraseState(
|
||||
withKey key: String!,
|
||||
withPair pair: Megrez.KeyValuePaired,
|
||||
isTypingVertical: Bool
|
||||
) -> InputState.AssociatedPhrases! {
|
||||
// 上一行必須要用驚嘆號,否則 Xcode 會誤導你砍掉某些實際上必需的語句。
|
||||
InputState.AssociatedPhrases(
|
||||
candidates: buildAssociatePhraseArray(withKey: key), isTypingVertical: isTypingVertical
|
||||
candidates: buildAssociatePhraseArray(withPair: pair), isTypingVertical: isTypingVertical
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,8 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
handle(state: InputState.Committing(textToCommit: composingBuffer))
|
||||
if mgrPrefs.associatedPhrasesEnabled,
|
||||
let associatePhrases = keyHandler.buildAssociatePhraseState(
|
||||
withKey: composingBuffer, isTypingVertical: state.isTypingVertical
|
||||
withPair: .init(key: selectedValue.0, value: selectedValue.1),
|
||||
isTypingVertical: state.isTypingVertical
|
||||
), !associatePhrases.candidates.isEmpty
|
||||
{
|
||||
handle(state: associatePhrases)
|
||||
|
@ -140,7 +141,8 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
handle(state: InputState.Committing(textToCommit: selectedValue.1))
|
||||
if mgrPrefs.associatedPhrasesEnabled,
|
||||
let associatePhrases = keyHandler.buildAssociatePhraseState(
|
||||
withKey: selectedValue.1, isTypingVertical: state.isTypingVertical
|
||||
withPair: .init(key: selectedValue.0, value: selectedValue.1),
|
||||
isTypingVertical: state.isTypingVertical
|
||||
), !associatePhrases.candidates.isEmpty
|
||||
{
|
||||
handle(state: associatePhrases)
|
||||
|
|
|
@ -117,15 +117,18 @@ extension ctlInputMethod {
|
|||
action: #selector(openExcludedPhrases(_:)), keyEquivalent: ""
|
||||
)
|
||||
|
||||
if optionKeyPressed || mgrPrefs.associatedPhrasesEnabled {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Associated Phrases…", comment: ""),
|
||||
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: ""
|
||||
)
|
||||
}
|
||||
|
||||
if optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Phrase Replacement Table…", comment: ""),
|
||||
action: #selector(openPhraseReplacement(_:)), keyEquivalent: ""
|
||||
)
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Associated Phrases…", comment: ""),
|
||||
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: ""
|
||||
)
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit User Symbol & Emoji Data…", comment: ""),
|
||||
action: #selector(openUserSymbols(_:)), keyEquivalent: ""
|
||||
|
@ -139,6 +142,8 @@ extension ctlInputMethod {
|
|||
)
|
||||
}
|
||||
|
||||
menu.addItem(NSMenuItem.separator()) // ---------------------
|
||||
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Optimize Memorized Phrases", comment: ""),
|
||||
action: #selector(removeUnigramsFromUOM(_:)), keyEquivalent: ""
|
||||
|
|
|
@ -88,6 +88,8 @@ public enum IME {
|
|||
// MARK: - Initializing Language Models.
|
||||
|
||||
static func initLangModels(userOnly: Bool) {
|
||||
mgrLangModel.chkUserLMFilesExist(.imeModeCHT)
|
||||
mgrLangModel.chkUserLMFilesExist(.imeModeCHS)
|
||||
// mgrLangModel 的 loadUserPhrases 等函式在自動讀取 dataFolderPath 時,
|
||||
// 如果發現自訂目錄不可用,則會自動抹去自訂目錄設定、改採預設目錄。
|
||||
// 所以這裡不需要特別處理。
|
||||
|
|
|
@ -82,7 +82,7 @@ extension vChewing {
|
|||
// 聲明使用者語言模組。
|
||||
// 使用者語言模組使用多執行緒的話,可能會導致一些問題。有時間再仔細排查看看。
|
||||
var lmUserPhrases = LMCoreEX(
|
||||
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true
|
||||
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: false
|
||||
)
|
||||
var lmFiltered = LMCoreEX(
|
||||
reverse: true, consolidate: true, defaultScore: 0, forceDefaultScore: true
|
||||
|
@ -249,13 +249,21 @@ extension vChewing {
|
|||
}
|
||||
|
||||
public func associatedPhrasesFor(key: String) -> [String] {
|
||||
lmAssociates.valuesFor(key: key) ?? []
|
||||
lmAssociates.valuesFor(key: key)
|
||||
}
|
||||
|
||||
public func hasAssociatedPhrasesFor(key: String) -> Bool {
|
||||
lmAssociates.hasValuesFor(key: key)
|
||||
}
|
||||
|
||||
public func associatedPhrasesFor(pair: Megrez.KeyValuePaired) -> [String] {
|
||||
lmAssociates.valuesFor(pair: pair)
|
||||
}
|
||||
|
||||
public func hasAssociatedPhrasesFor(pair: Megrez.KeyValuePaired) -> Bool {
|
||||
lmAssociates.hasValuesFor(pair: pair)
|
||||
}
|
||||
|
||||
/// 該函式不起作用,僅用來滿足 LangModelProtocol 協定的要求。
|
||||
public func bigramsFor(precedingKey _: String, key _: String) -> [Megrez.Bigram] { .init() }
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import Foundation
|
|||
|
||||
extension vChewing {
|
||||
@frozen public struct LMAssociates {
|
||||
var rangeMap: [String: [Range<String.Index>]] = [:]
|
||||
var rangeMap: [String: [(Range<String.Index>, Int)]] = [:]
|
||||
var strData: String = ""
|
||||
|
||||
public var count: Int {
|
||||
|
@ -52,13 +52,16 @@ extension vChewing {
|
|||
|
||||
do {
|
||||
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
|
||||
strData.ranges(splitBy: "\n").forEach {
|
||||
strData = strData.replacingOccurrences(of: "\r", with: "\n")
|
||||
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
|
||||
let neta = strData[$0].split(separator: " ")
|
||||
if neta.count >= 2 {
|
||||
let theKey = String(neta[0])
|
||||
if !neta[0].isEmpty, !neta[1].isEmpty, theKey.first != "#" {
|
||||
let theValue = $0
|
||||
rangeMap[theKey, default: []].append(theValue)
|
||||
if !theKey.isEmpty, theKey.first != "#" {
|
||||
for (i, _) in neta.filter({ $0.first != "#" && !$0.isEmpty }).enumerated() {
|
||||
if i == 0 { continue }
|
||||
rangeMap[theKey, default: []].append(($0, i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,24 +81,16 @@ extension vChewing {
|
|||
}
|
||||
|
||||
public func dump() {
|
||||
var strDump = ""
|
||||
for entry in rangeMap {
|
||||
let netaRanges: [Range<String.Index>] = entry.value
|
||||
for netaRange in netaRanges {
|
||||
let neta = strData[netaRange]
|
||||
let addline = neta + "\n"
|
||||
strDump += addline
|
||||
}
|
||||
}
|
||||
IME.prtDebugIntel(strDump)
|
||||
// We remove this function in order to reduce out maintenance workload.
|
||||
// This function will be implemented only if further hard-necessity comes.
|
||||
}
|
||||
|
||||
public func valuesFor(key: String) -> [String]? {
|
||||
public func valuesFor(key: String) -> [String] {
|
||||
var pairs: [String] = []
|
||||
if let arrRangeRecords: [Range<String.Index>] = rangeMap[key] {
|
||||
for netaRange in arrRangeRecords {
|
||||
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[key] {
|
||||
for (netaRange, index) in arrRangeRecords {
|
||||
let neta = strData[netaRange].split(separator: " ")
|
||||
let theValue: String = .init(neta[1])
|
||||
let theValue: String = .init(neta[index])
|
||||
pairs.append(theValue)
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +100,40 @@ extension vChewing {
|
|||
public func hasValuesFor(key: String) -> Bool {
|
||||
rangeMap[key] != nil
|
||||
}
|
||||
|
||||
public func valuesFor(pair: Megrez.KeyValuePaired) -> [String] {
|
||||
var pairPinyin = pair
|
||||
pairPinyin.key = Tekkon.cnvPhonaToHanyuPinyin(target: pairPinyin.key)
|
||||
var pairs: [String] = []
|
||||
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pair.toNGramKey] {
|
||||
for (netaRange, index) in arrRangeRecords {
|
||||
let neta = strData[netaRange].split(separator: " ")
|
||||
let theValue: String = .init(neta[index])
|
||||
pairs.append(theValue)
|
||||
}
|
||||
}
|
||||
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pairPinyin.toNGramKey] {
|
||||
for (netaRange, index) in arrRangeRecords {
|
||||
let neta = strData[netaRange].split(separator: " ")
|
||||
let theValue: String = .init(neta[index])
|
||||
pairs.append(theValue)
|
||||
}
|
||||
}
|
||||
if let arrRangeRecords: [(Range<String.Index>, Int)] = rangeMap[pair.value] {
|
||||
for (netaRange, index) in arrRangeRecords {
|
||||
let neta = strData[netaRange].split(separator: " ")
|
||||
let theValue: String = .init(neta[index])
|
||||
pairs.append(theValue)
|
||||
}
|
||||
}
|
||||
var set = Set<String>()
|
||||
return pairs.filter { set.insert($0).inserted }
|
||||
}
|
||||
|
||||
public func hasValuesFor(pair: Megrez.KeyValuePaired) -> Bool {
|
||||
if rangeMap[pair.toNGramKey] != nil { return true }
|
||||
return rangeMap[pair.value] != nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,11 +86,13 @@ extension vChewing {
|
|||
|
||||
do {
|
||||
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
|
||||
strData.ranges(splitBy: "\n").forEach {
|
||||
strData = strData.replacingOccurrences(of: "\r", with: "\n")
|
||||
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
|
||||
let neta = strData[$0].split(separator: " ")
|
||||
if neta.count >= 2, String(neta[0]).first != "#" {
|
||||
if !neta[0].isEmpty, !neta[1].isEmpty {
|
||||
let theKey = shouldReverse ? String(neta[1]) : String(neta[0])
|
||||
var theKey = shouldReverse ? String(neta[1]) : String(neta[0])
|
||||
theKey.cnvPinyinToPhonabet()
|
||||
let theValue = $0
|
||||
rangeMap[theKey, default: []].append(theValue)
|
||||
}
|
||||
|
@ -153,7 +155,7 @@ extension vChewing {
|
|||
let theValue: String = shouldReverse ? String(neta[0]) : String(neta[1])
|
||||
let kvPair = Megrez.KeyValuePaired(key: key, value: theValue)
|
||||
var theScore = defaultScore
|
||||
if neta.count >= 3, !shouldForceDefaultScore {
|
||||
if neta.count >= 3, !shouldForceDefaultScore, !neta[2].contains("#") {
|
||||
theScore = .init(String(neta[2])) ?? defaultScore
|
||||
}
|
||||
if theScore > 0 {
|
||||
|
@ -190,3 +192,19 @@ extension String {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 拼音轉注音
|
||||
|
||||
extension String {
|
||||
fileprivate mutating func cnvPinyinToPhonabet() {
|
||||
if contains("_") { return }
|
||||
for key in Tekkon.mapHanyuPinyin.keys {
|
||||
guard let value = Tekkon.mapHanyuPinyin[key] else { continue }
|
||||
self = replacingOccurrences(of: key, with: value)
|
||||
}
|
||||
for key in Tekkon.mapArayuruPinyinIntonation.keys {
|
||||
guard let value = Tekkon.mapArayuruPinyinIntonation[key] else { continue }
|
||||
self = replacingOccurrences(of: key, with: value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,8 @@ extension vChewing {
|
|||
|
||||
do {
|
||||
strData = try String(contentsOfFile: path, encoding: .utf8).replacingOccurrences(of: "\t", with: " ")
|
||||
strData.ranges(splitBy: "\n").forEach {
|
||||
strData = strData.replacingOccurrences(of: "\r", with: "\n")
|
||||
strData.ranges(splitBy: "\n").filter({ !$0.isEmpty }).forEach {
|
||||
let neta = strData[$0].split(separator: " ")
|
||||
if neta.count >= 2 {
|
||||
let theKey = String(neta[0])
|
||||
|
|
|
@ -36,6 +36,14 @@ private var gLangModelCHT = vChewing.LMInstantiator()
|
|||
private var gUserOverrideModelCHS = vChewing.LMUserOverride()
|
||||
private var gUserOverrideModelCHT = vChewing.LMUserOverride()
|
||||
|
||||
/// 使用者辭典資料預設範例檔案名稱。
|
||||
private let kTemplateNameUserPhrases = "template-userphrases"
|
||||
private let kTemplateNameUserReplacements = "template-replacements"
|
||||
private let kTemplateNameUserExclusions = "template-exclusions"
|
||||
private let kTemplateNameUserSymbolPhrases = "template-usersymbolphrases"
|
||||
private let kTemplateNameUserAssociatesCHS = "template-associatedPhrases-chs"
|
||||
private let kTemplateNameUserAssociatesCHT = "template-associatedPhrases-cht"
|
||||
|
||||
enum mgrLangModel {
|
||||
/// 寫幾個回傳函式、供其餘控制模組來讀取那些被設為 fileprivate 的器外變數。
|
||||
public static var lmCHS: vChewing.LMInstantiator { gLangModelCHS }
|
||||
|
@ -307,18 +315,20 @@ enum mgrLangModel {
|
|||
return true
|
||||
}
|
||||
|
||||
static func chkUserLMFilesExist(_ mode: InputMode) -> Bool {
|
||||
@discardableResult static func chkUserLMFilesExist(_ mode: InputMode) -> Bool {
|
||||
if !userDataFolderExists {
|
||||
return false
|
||||
}
|
||||
/// SymbolNode 資料與 UserOverrideModel 半衰模組資料檔案不需要強行確保存在。
|
||||
/// 前者的話,需要該檔案存在的人自己會建立。
|
||||
/// 後者的話,你在敲字時自己就會建立。
|
||||
if !ensureFileExists(userPhrasesDataURL(mode))
|
||||
|| !ensureFileExists(userAssociatesDataURL(mode))
|
||||
|| !ensureFileExists(userFilteredDataURL(mode))
|
||||
|| !ensureFileExists(userReplacementsDataURL(mode))
|
||||
|| !ensureFileExists(userSymbolDataURL(mode))
|
||||
if !ensureFileExists(userPhrasesDataURL(mode), populateWithTemplate: kTemplateNameUserPhrases)
|
||||
|| !ensureFileExists(
|
||||
userAssociatesDataURL(mode),
|
||||
populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT)
|
||||
|| !ensureFileExists(userFilteredDataURL(mode), populateWithTemplate: kTemplateNameUserExclusions)
|
||||
|| !ensureFileExists(userReplacementsDataURL(mode), populateWithTemplate: kTemplateNameUserReplacements)
|
||||
|| !ensureFileExists(userSymbolDataURL(mode), populateWithTemplate: kTemplateNameUserSymbolPhrases)
|
||||
{
|
||||
return false
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 5.8 KiB |
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "64X64.png",
|
||||
"filename" : "64.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "128X128.png",
|
||||
"filename" : "128.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "192x192.png",
|
||||
"filename" : "192.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
@ -0,0 +1,12 @@
|
|||
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
|
||||
# 按照下述格式「字詞 注音-注音」的方式在本文內添入的字詞記錄會被輸入法的所有辭典都排除掉。
|
||||
# 按照下述格式「字词 注音-注音」的方式在本文内添入的字词记录会被输入法的所有辞典都排除掉。
|
||||
# 下記の格式「候補 注音-注音」のよう、このファイルで登録した入力候補は、全辞書から排除されます。
|
||||
# By using the format "Candidate Reading-Reading", all candidate pairs registered in this file will be blocked among all dictionaries.
|
||||
#
|
||||
# 北七 ㄅㄟˇ-ㄑㄧ
|
||||
#
|
||||
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
|
||||
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
|
||||
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
|
||||
# Lines begin with an ASCII sharp symbol or a space will be omitted.
|
|
@ -0,0 +1,12 @@
|
|||
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
|
||||
# 按照下述格式「字詞 新字詞」的方式在本文內添入的字詞記錄才會生效。
|
||||
# 按照下述格式「字词 新字词」的方式在本文内添入的字词记录才会生效。
|
||||
# 下記の格式「候補 新候補」のよう、このファイルで登録した入力候補は効きます。
|
||||
# By using the format "Candidate NewCandidate", all entries registered in this file will be effective.
|
||||
#
|
||||
# 歐陽修 歐陽脩
|
||||
#
|
||||
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
|
||||
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
|
||||
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
|
||||
# Lines begin with an ASCII sharp symbol or a space will be omitted.
|
|
@ -0,0 +1,12 @@
|
|||
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
|
||||
# 按照下述格式「字詞 注音-注音」的方式在本文內添入的字詞記錄才會生效。
|
||||
# 按照下述格式「字词 注音-注音」的方式在本文内添入的字词记录才会生效。
|
||||
# 下記の格式「候補 注音-注音」のよう、このファイルで登録した入力候補は効きます。
|
||||
# By using the format "Candidate Reading-Reading", all entries registered in this file will be effective.
|
||||
#
|
||||
# 我是自訂語彙 ㄨㄛˇ-ㄕˋ-ㄗˋ-ㄉㄧㄥˋ-ㄩˇ-ㄏㄨㄟˋ
|
||||
#
|
||||
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
|
||||
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
|
||||
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
|
||||
# Lines begin with an ASCII sharp symbol or a space will be omitted.
|
|
@ -0,0 +1,12 @@
|
|||
# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍
|
||||
# 按照下述格式「字詞 注音-注音」的方式在本文內添入的字詞記錄才會生效。
|
||||
# 按照下述格式「字词 注音-注音」的方式在本文内添入的字词记录才会生效。
|
||||
# 下記の格式「候補 注音-注音」のよう、このファイルで登録した入力候補は効きます。
|
||||
# By using the format "Candidate Reading-Reading", all entries registered in this file will be effective.
|
||||
#
|
||||
# ⚠︎ ㄐㄧㄥˇ-ㄍㄠˋ
|
||||
#
|
||||
# 如果任何一行以半形英數「#」或者空格開頭,則該行將被忽略。
|
||||
# 如果任何一行以半角英数「#」或者空格开头,则该行将被忽略。
|
||||
# 頭文字が半角英数「#」或いは「スペース」の行は効けません。
|
||||
# Lines begin with an ASCII sharp symbol or a space will be omitted.
|
|
@ -3,9 +3,9 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.8.0</string>
|
||||
<string>1.8.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1980</string>
|
||||
<string>1981</string>
|
||||
<key>UpdateInfoEndpoint</key>
|
||||
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
|
||||
<key>UpdateInfoSite</key>
|
||||
|
|
|
@ -78,7 +78,7 @@ class Document: NSDocument {
|
|||
/// - Tag: readExample
|
||||
override func read(from data: Data, ofType _: String) throws {
|
||||
var strToDealWith = String(decoding: data, as: UTF8.self)
|
||||
strToDealWith.formatConsolidate(cnvHYPYtoBPMF: false)
|
||||
strToDealWith.formatConsolidate()
|
||||
let processedIncomingData = Data(strToDealWith.utf8)
|
||||
content.read(from: processedIncomingData)
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class Document: NSDocument {
|
|||
/// - Tag: writeExample
|
||||
override func data(ofType _: String) throws -> Data {
|
||||
var strToDealWith = content.contentString
|
||||
strToDealWith.formatConsolidate(cnvHYPYtoBPMF: true)
|
||||
strToDealWith.formatConsolidate()
|
||||
let outputData = Data(strToDealWith.utf8)
|
||||
return outputData
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ extension String {
|
|||
self = replacingOccurrences(of: strOf, with: strWith)
|
||||
}
|
||||
|
||||
mutating func formatConsolidate(cnvHYPYtoBPMF: Bool) {
|
||||
mutating func formatConsolidate() {
|
||||
// Step 1: Consolidating formats per line.
|
||||
var strProcessed = self
|
||||
// 預處理格式
|
||||
|
@ -64,442 +64,6 @@ extension String {
|
|||
strProcessed.removeLast()
|
||||
}
|
||||
|
||||
if cnvHYPYtoBPMF {
|
||||
// Step 2: Convert HanyuPinyin to Bopomofo.
|
||||
// 漢語拼音轉注音,得先從最長的可能的拼音組合開始轉起,
|
||||
// 這樣等轉換到更短的可能的漢語拼音組合時就不會出錯。
|
||||
// 依此類推,聲調放在最後來轉換。
|
||||
strProcessed.selfReplace("chuang", "ㄔㄨㄤ")
|
||||
strProcessed.selfReplace("shuang", "ㄕㄨㄤ")
|
||||
strProcessed.selfReplace("zhuang", "ㄓㄨㄤ")
|
||||
strProcessed.selfReplace("chang", "ㄔㄤ")
|
||||
strProcessed.selfReplace("cheng", "ㄔㄥ")
|
||||
strProcessed.selfReplace("chong", "ㄔㄨㄥ")
|
||||
strProcessed.selfReplace("chuai", "ㄔㄨㄞ")
|
||||
strProcessed.selfReplace("chuan", "ㄔㄨㄢ")
|
||||
strProcessed.selfReplace("guang", "ㄍㄨㄤ")
|
||||
strProcessed.selfReplace("huang", "ㄏㄨㄤ")
|
||||
strProcessed.selfReplace("jiang", "ㄐㄧㄤ")
|
||||
strProcessed.selfReplace("jiong", "ㄐㄩㄥ")
|
||||
strProcessed.selfReplace("kuang", "ㄎㄨㄤ")
|
||||
strProcessed.selfReplace("liang", "ㄌㄧㄤ")
|
||||
strProcessed.selfReplace("niang", "ㄋㄧㄤ")
|
||||
strProcessed.selfReplace("qiang", "ㄑㄧㄤ")
|
||||
strProcessed.selfReplace("qiong", "ㄑㄩㄥ")
|
||||
strProcessed.selfReplace("shang", "ㄕㄤ")
|
||||
strProcessed.selfReplace("sheng", "ㄕㄥ")
|
||||
strProcessed.selfReplace("shuai", "ㄕㄨㄞ")
|
||||
strProcessed.selfReplace("shuan", "ㄕㄨㄢ")
|
||||
strProcessed.selfReplace("xiang", "ㄒㄧㄤ")
|
||||
strProcessed.selfReplace("xiong", "ㄒㄩㄥ")
|
||||
strProcessed.selfReplace("zhang", "ㄓㄤ")
|
||||
strProcessed.selfReplace("zheng", "ㄓㄥ")
|
||||
strProcessed.selfReplace("zhong", "ㄓㄨㄥ")
|
||||
strProcessed.selfReplace("zhuai", "ㄓㄨㄞ")
|
||||
strProcessed.selfReplace("zhuan", "ㄓㄨㄢ")
|
||||
strProcessed.selfReplace("bang", "ㄅㄤ")
|
||||
strProcessed.selfReplace("beng", "ㄅㄥ")
|
||||
strProcessed.selfReplace("bian", "ㄅㄧㄢ")
|
||||
strProcessed.selfReplace("biao", "ㄅㄧㄠ")
|
||||
strProcessed.selfReplace("bing", "ㄅㄧㄥ")
|
||||
strProcessed.selfReplace("cang", "ㄘㄤ")
|
||||
strProcessed.selfReplace("ceng", "ㄘㄥ")
|
||||
strProcessed.selfReplace("chai", "ㄔㄞ")
|
||||
strProcessed.selfReplace("chan", "ㄔㄢ")
|
||||
strProcessed.selfReplace("chao", "ㄔㄠ")
|
||||
strProcessed.selfReplace("chen", "ㄔㄣ")
|
||||
strProcessed.selfReplace("chou", "ㄔㄡ")
|
||||
strProcessed.selfReplace("chua", "ㄔㄨㄚ")
|
||||
strProcessed.selfReplace("chui", "ㄔㄨㄟ")
|
||||
strProcessed.selfReplace("chun", "ㄔㄨㄣ")
|
||||
strProcessed.selfReplace("chuo", "ㄔㄨㄛ")
|
||||
strProcessed.selfReplace("cong", "ㄘㄨㄥ")
|
||||
strProcessed.selfReplace("cuan", "ㄘㄨㄢ")
|
||||
strProcessed.selfReplace("dang", "ㄉㄤ")
|
||||
strProcessed.selfReplace("deng", "ㄉㄥ")
|
||||
strProcessed.selfReplace("dian", "ㄉㄧㄢ")
|
||||
strProcessed.selfReplace("diao", "ㄉㄧㄠ")
|
||||
strProcessed.selfReplace("ding", "ㄉㄧㄥ")
|
||||
strProcessed.selfReplace("dong", "ㄉㄨㄥ")
|
||||
strProcessed.selfReplace("duan", "ㄉㄨㄢ")
|
||||
strProcessed.selfReplace("fang", "ㄈㄤ")
|
||||
strProcessed.selfReplace("feng", "ㄈㄥ")
|
||||
strProcessed.selfReplace("fiao", "ㄈㄧㄠ")
|
||||
strProcessed.selfReplace("fong", "ㄈㄨㄥ")
|
||||
strProcessed.selfReplace("gang", "ㄍㄤ")
|
||||
strProcessed.selfReplace("geng", "ㄍㄥ")
|
||||
strProcessed.selfReplace("giao", "ㄍㄧㄠ")
|
||||
strProcessed.selfReplace("gong", "ㄍㄨㄥ")
|
||||
strProcessed.selfReplace("guai", "ㄍㄨㄞ")
|
||||
strProcessed.selfReplace("guan", "ㄍㄨㄢ")
|
||||
strProcessed.selfReplace("hang", "ㄏㄤ")
|
||||
strProcessed.selfReplace("heng", "ㄏㄥ")
|
||||
strProcessed.selfReplace("hong", "ㄏㄨㄥ")
|
||||
strProcessed.selfReplace("huai", "ㄏㄨㄞ")
|
||||
strProcessed.selfReplace("huan", "ㄏㄨㄢ")
|
||||
strProcessed.selfReplace("jian", "ㄐㄧㄢ")
|
||||
strProcessed.selfReplace("jiao", "ㄐㄧㄠ")
|
||||
strProcessed.selfReplace("jing", "ㄐㄧㄥ")
|
||||
strProcessed.selfReplace("juan", "ㄐㄩㄢ")
|
||||
strProcessed.selfReplace("kang", "ㄎㄤ")
|
||||
strProcessed.selfReplace("keng", "ㄎㄥ")
|
||||
strProcessed.selfReplace("kong", "ㄎㄨㄥ")
|
||||
strProcessed.selfReplace("kuai", "ㄎㄨㄞ")
|
||||
strProcessed.selfReplace("kuan", "ㄎㄨㄢ")
|
||||
strProcessed.selfReplace("lang", "ㄌㄤ")
|
||||
strProcessed.selfReplace("leng", "ㄌㄥ")
|
||||
strProcessed.selfReplace("lian", "ㄌㄧㄢ")
|
||||
strProcessed.selfReplace("liao", "ㄌㄧㄠ")
|
||||
strProcessed.selfReplace("ling", "ㄌㄧㄥ")
|
||||
strProcessed.selfReplace("long", "ㄌㄨㄥ")
|
||||
strProcessed.selfReplace("luan", "ㄌㄨㄢ")
|
||||
strProcessed.selfReplace("lvan", "ㄌㄩㄢ")
|
||||
strProcessed.selfReplace("mang", "ㄇㄤ")
|
||||
strProcessed.selfReplace("meng", "ㄇㄥ")
|
||||
strProcessed.selfReplace("mian", "ㄇㄧㄢ")
|
||||
strProcessed.selfReplace("miao", "ㄇㄧㄠ")
|
||||
strProcessed.selfReplace("ming", "ㄇㄧㄥ")
|
||||
strProcessed.selfReplace("nang", "ㄋㄤ")
|
||||
strProcessed.selfReplace("neng", "ㄋㄥ")
|
||||
strProcessed.selfReplace("nian", "ㄋㄧㄢ")
|
||||
strProcessed.selfReplace("niao", "ㄋㄧㄠ")
|
||||
strProcessed.selfReplace("ning", "ㄋㄧㄥ")
|
||||
strProcessed.selfReplace("nong", "ㄋㄨㄥ")
|
||||
strProcessed.selfReplace("nuan", "ㄋㄨㄢ")
|
||||
strProcessed.selfReplace("pang", "ㄆㄤ")
|
||||
strProcessed.selfReplace("peng", "ㄆㄥ")
|
||||
strProcessed.selfReplace("pian", "ㄆㄧㄢ")
|
||||
strProcessed.selfReplace("piao", "ㄆㄧㄠ")
|
||||
strProcessed.selfReplace("ping", "ㄆㄧㄥ")
|
||||
strProcessed.selfReplace("qian", "ㄑㄧㄢ")
|
||||
strProcessed.selfReplace("qiao", "ㄑㄧㄠ")
|
||||
strProcessed.selfReplace("qing", "ㄑㄧㄥ")
|
||||
strProcessed.selfReplace("quan", "ㄑㄩㄢ")
|
||||
strProcessed.selfReplace("rang", "ㄖㄤ")
|
||||
strProcessed.selfReplace("reng", "ㄖㄥ")
|
||||
strProcessed.selfReplace("rong", "ㄖㄨㄥ")
|
||||
strProcessed.selfReplace("ruan", "ㄖㄨㄢ")
|
||||
strProcessed.selfReplace("sang", "ㄙㄤ")
|
||||
strProcessed.selfReplace("seng", "ㄙㄥ")
|
||||
strProcessed.selfReplace("shai", "ㄕㄞ")
|
||||
strProcessed.selfReplace("shan", "ㄕㄢ")
|
||||
strProcessed.selfReplace("shao", "ㄕㄠ")
|
||||
strProcessed.selfReplace("shei", "ㄕㄟ")
|
||||
strProcessed.selfReplace("shen", "ㄕㄣ")
|
||||
strProcessed.selfReplace("shou", "ㄕㄡ")
|
||||
strProcessed.selfReplace("shua", "ㄕㄨㄚ")
|
||||
strProcessed.selfReplace("shui", "ㄕㄨㄟ")
|
||||
strProcessed.selfReplace("shun", "ㄕㄨㄣ")
|
||||
strProcessed.selfReplace("shuo", "ㄕㄨㄛ")
|
||||
strProcessed.selfReplace("song", "ㄙㄨㄥ")
|
||||
strProcessed.selfReplace("suan", "ㄙㄨㄢ")
|
||||
strProcessed.selfReplace("tang", "ㄊㄤ")
|
||||
strProcessed.selfReplace("teng", "ㄊㄥ")
|
||||
strProcessed.selfReplace("tian", "ㄊㄧㄢ")
|
||||
strProcessed.selfReplace("tiao", "ㄊㄧㄠ")
|
||||
strProcessed.selfReplace("ting", "ㄊㄧㄥ")
|
||||
strProcessed.selfReplace("tong", "ㄊㄨㄥ")
|
||||
strProcessed.selfReplace("tuan", "ㄊㄨㄢ")
|
||||
strProcessed.selfReplace("wang", "ㄨㄤ")
|
||||
strProcessed.selfReplace("weng", "ㄨㄥ")
|
||||
strProcessed.selfReplace("xian", "ㄒㄧㄢ")
|
||||
strProcessed.selfReplace("xiao", "ㄒㄧㄠ")
|
||||
strProcessed.selfReplace("xing", "ㄒㄧㄥ")
|
||||
strProcessed.selfReplace("xuan", "ㄒㄩㄢ")
|
||||
strProcessed.selfReplace("yang", "ㄧㄤ")
|
||||
strProcessed.selfReplace("ying", "ㄧㄥ")
|
||||
strProcessed.selfReplace("yong", "ㄩㄥ")
|
||||
strProcessed.selfReplace("yuan", "ㄩㄢ")
|
||||
strProcessed.selfReplace("zang", "ㄗㄤ")
|
||||
strProcessed.selfReplace("zeng", "ㄗㄥ")
|
||||
strProcessed.selfReplace("zhai", "ㄓㄞ")
|
||||
strProcessed.selfReplace("zhan", "ㄓㄢ")
|
||||
strProcessed.selfReplace("zhao", "ㄓㄠ")
|
||||
strProcessed.selfReplace("zhei", "ㄓㄟ")
|
||||
strProcessed.selfReplace("zhen", "ㄓㄣ")
|
||||
strProcessed.selfReplace("zhou", "ㄓㄡ")
|
||||
strProcessed.selfReplace("zhua", "ㄓㄨㄚ")
|
||||
strProcessed.selfReplace("zhui", "ㄓㄨㄟ")
|
||||
strProcessed.selfReplace("zhun", "ㄓㄨㄣ")
|
||||
strProcessed.selfReplace("zhuo", "ㄓㄨㄛ")
|
||||
strProcessed.selfReplace("zong", "ㄗㄨㄥ")
|
||||
strProcessed.selfReplace("zuan", "ㄗㄨㄢ")
|
||||
strProcessed.selfReplace("jun", "ㄐㄩㄣ")
|
||||
strProcessed.selfReplace("ang", "ㄤ")
|
||||
strProcessed.selfReplace("bai", "ㄅㄞ")
|
||||
strProcessed.selfReplace("ban", "ㄅㄢ")
|
||||
strProcessed.selfReplace("bao", "ㄅㄠ")
|
||||
strProcessed.selfReplace("bei", "ㄅㄟ")
|
||||
strProcessed.selfReplace("ben", "ㄅㄣ")
|
||||
strProcessed.selfReplace("bie", "ㄅㄧㄝ")
|
||||
strProcessed.selfReplace("bin", "ㄅㄧㄣ")
|
||||
strProcessed.selfReplace("cai", "ㄘㄞ")
|
||||
strProcessed.selfReplace("can", "ㄘㄢ")
|
||||
strProcessed.selfReplace("cao", "ㄘㄠ")
|
||||
strProcessed.selfReplace("cei", "ㄘㄟ")
|
||||
strProcessed.selfReplace("cen", "ㄘㄣ")
|
||||
strProcessed.selfReplace("cha", "ㄔㄚ")
|
||||
strProcessed.selfReplace("che", "ㄔㄜ")
|
||||
strProcessed.selfReplace("chi", "ㄔ")
|
||||
strProcessed.selfReplace("chu", "ㄔㄨ")
|
||||
strProcessed.selfReplace("cou", "ㄘㄡ")
|
||||
strProcessed.selfReplace("cui", "ㄘㄨㄟ")
|
||||
strProcessed.selfReplace("cun", "ㄘㄨㄣ")
|
||||
strProcessed.selfReplace("cuo", "ㄘㄨㄛ")
|
||||
strProcessed.selfReplace("dai", "ㄉㄞ")
|
||||
strProcessed.selfReplace("dan", "ㄉㄢ")
|
||||
strProcessed.selfReplace("dao", "ㄉㄠ")
|
||||
strProcessed.selfReplace("dei", "ㄉㄟ")
|
||||
strProcessed.selfReplace("den", "ㄉㄣ")
|
||||
strProcessed.selfReplace("dia", "ㄉㄧㄚ")
|
||||
strProcessed.selfReplace("die", "ㄉㄧㄝ")
|
||||
strProcessed.selfReplace("diu", "ㄉㄧㄡ")
|
||||
strProcessed.selfReplace("dou", "ㄉㄡ")
|
||||
strProcessed.selfReplace("dui", "ㄉㄨㄟ")
|
||||
strProcessed.selfReplace("dun", "ㄉㄨㄣ")
|
||||
strProcessed.selfReplace("duo", "ㄉㄨㄛ")
|
||||
strProcessed.selfReplace("eng", "ㄥ")
|
||||
strProcessed.selfReplace("fan", "ㄈㄢ")
|
||||
strProcessed.selfReplace("fei", "ㄈㄟ")
|
||||
strProcessed.selfReplace("fen", "ㄈㄣ")
|
||||
strProcessed.selfReplace("fou", "ㄈㄡ")
|
||||
strProcessed.selfReplace("gai", "ㄍㄞ")
|
||||
strProcessed.selfReplace("gan", "ㄍㄢ")
|
||||
strProcessed.selfReplace("gao", "ㄍㄠ")
|
||||
strProcessed.selfReplace("gei", "ㄍㄟ")
|
||||
strProcessed.selfReplace("gin", "ㄍㄧㄣ")
|
||||
strProcessed.selfReplace("gen", "ㄍㄣ")
|
||||
strProcessed.selfReplace("gou", "ㄍㄡ")
|
||||
strProcessed.selfReplace("gua", "ㄍㄨㄚ")
|
||||
strProcessed.selfReplace("gue", "ㄍㄨㄜ")
|
||||
strProcessed.selfReplace("gui", "ㄍㄨㄟ")
|
||||
strProcessed.selfReplace("gun", "ㄍㄨㄣ")
|
||||
strProcessed.selfReplace("guo", "ㄍㄨㄛ")
|
||||
strProcessed.selfReplace("hai", "ㄏㄞ")
|
||||
strProcessed.selfReplace("han", "ㄏㄢ")
|
||||
strProcessed.selfReplace("hao", "ㄏㄠ")
|
||||
strProcessed.selfReplace("hei", "ㄏㄟ")
|
||||
strProcessed.selfReplace("hen", "ㄏㄣ")
|
||||
strProcessed.selfReplace("hou", "ㄏㄡ")
|
||||
strProcessed.selfReplace("hua", "ㄏㄨㄚ")
|
||||
strProcessed.selfReplace("hui", "ㄏㄨㄟ")
|
||||
strProcessed.selfReplace("hun", "ㄏㄨㄣ")
|
||||
strProcessed.selfReplace("huo", "ㄏㄨㄛ")
|
||||
strProcessed.selfReplace("jia", "ㄐㄧㄚ")
|
||||
strProcessed.selfReplace("jie", "ㄐㄧㄝ")
|
||||
strProcessed.selfReplace("jin", "ㄐㄧㄣ")
|
||||
strProcessed.selfReplace("jiu", "ㄐㄧㄡ")
|
||||
strProcessed.selfReplace("jue", "ㄐㄩㄝ")
|
||||
strProcessed.selfReplace("kai", "ㄎㄞ")
|
||||
strProcessed.selfReplace("kan", "ㄎㄢ")
|
||||
strProcessed.selfReplace("kao", "ㄎㄠ")
|
||||
strProcessed.selfReplace("ken", "ㄎㄣ")
|
||||
strProcessed.selfReplace("kiu", "ㄎㄧㄡ")
|
||||
strProcessed.selfReplace("kou", "ㄎㄡ")
|
||||
strProcessed.selfReplace("kua", "ㄎㄨㄚ")
|
||||
strProcessed.selfReplace("kui", "ㄎㄨㄟ")
|
||||
strProcessed.selfReplace("kun", "ㄎㄨㄣ")
|
||||
strProcessed.selfReplace("kuo", "ㄎㄨㄛ")
|
||||
strProcessed.selfReplace("lai", "ㄌㄞ")
|
||||
strProcessed.selfReplace("lan", "ㄌㄢ")
|
||||
strProcessed.selfReplace("lao", "ㄌㄠ")
|
||||
strProcessed.selfReplace("lei", "ㄌㄟ")
|
||||
strProcessed.selfReplace("lia", "ㄌㄧㄚ")
|
||||
strProcessed.selfReplace("lie", "ㄌㄧㄝ")
|
||||
strProcessed.selfReplace("lin", "ㄌㄧㄣ")
|
||||
strProcessed.selfReplace("liu", "ㄌㄧㄡ")
|
||||
strProcessed.selfReplace("lou", "ㄌㄡ")
|
||||
strProcessed.selfReplace("lun", "ㄌㄨㄣ")
|
||||
strProcessed.selfReplace("luo", "ㄌㄨㄛ")
|
||||
strProcessed.selfReplace("lve", "ㄌㄩㄝ")
|
||||
strProcessed.selfReplace("mai", "ㄇㄞ")
|
||||
strProcessed.selfReplace("man", "ㄇㄢ")
|
||||
strProcessed.selfReplace("mao", "ㄇㄠ")
|
||||
strProcessed.selfReplace("mei", "ㄇㄟ")
|
||||
strProcessed.selfReplace("men", "ㄇㄣ")
|
||||
strProcessed.selfReplace("mie", "ㄇㄧㄝ")
|
||||
strProcessed.selfReplace("min", "ㄇㄧㄣ")
|
||||
strProcessed.selfReplace("miu", "ㄇㄧㄡ")
|
||||
strProcessed.selfReplace("mou", "ㄇㄡ")
|
||||
strProcessed.selfReplace("nai", "ㄋㄞ")
|
||||
strProcessed.selfReplace("nan", "ㄋㄢ")
|
||||
strProcessed.selfReplace("nao", "ㄋㄠ")
|
||||
strProcessed.selfReplace("nei", "ㄋㄟ")
|
||||
strProcessed.selfReplace("nen", "ㄋㄣ")
|
||||
strProcessed.selfReplace("nie", "ㄋㄧㄝ")
|
||||
strProcessed.selfReplace("nin", "ㄋㄧㄣ")
|
||||
strProcessed.selfReplace("niu", "ㄋㄧㄡ")
|
||||
strProcessed.selfReplace("nou", "ㄋㄡ")
|
||||
strProcessed.selfReplace("nui", "ㄋㄨㄟ")
|
||||
strProcessed.selfReplace("nun", "ㄋㄨㄣ")
|
||||
strProcessed.selfReplace("nuo", "ㄋㄨㄛ")
|
||||
strProcessed.selfReplace("nve", "ㄋㄩㄝ")
|
||||
strProcessed.selfReplace("pai", "ㄆㄞ")
|
||||
strProcessed.selfReplace("pan", "ㄆㄢ")
|
||||
strProcessed.selfReplace("pao", "ㄆㄠ")
|
||||
strProcessed.selfReplace("pei", "ㄆㄟ")
|
||||
strProcessed.selfReplace("pen", "ㄆㄣ")
|
||||
strProcessed.selfReplace("pia", "ㄆㄧㄚ")
|
||||
strProcessed.selfReplace("pie", "ㄆㄧㄝ")
|
||||
strProcessed.selfReplace("pin", "ㄆㄧㄣ")
|
||||
strProcessed.selfReplace("pou", "ㄆㄡ")
|
||||
strProcessed.selfReplace("qia", "ㄑㄧㄚ")
|
||||
strProcessed.selfReplace("qie", "ㄑㄧㄝ")
|
||||
strProcessed.selfReplace("qin", "ㄑㄧㄣ")
|
||||
strProcessed.selfReplace("qiu", "ㄑㄧㄡ")
|
||||
strProcessed.selfReplace("que", "ㄑㄩㄝ")
|
||||
strProcessed.selfReplace("qun", "ㄑㄩㄣ")
|
||||
strProcessed.selfReplace("ran", "ㄖㄢ")
|
||||
strProcessed.selfReplace("rao", "ㄖㄠ")
|
||||
strProcessed.selfReplace("ren", "ㄖㄣ")
|
||||
strProcessed.selfReplace("rou", "ㄖㄡ")
|
||||
strProcessed.selfReplace("rui", "ㄖㄨㄟ")
|
||||
strProcessed.selfReplace("run", "ㄖㄨㄣ")
|
||||
strProcessed.selfReplace("ruo", "ㄖㄨㄛ")
|
||||
strProcessed.selfReplace("sai", "ㄙㄞ")
|
||||
strProcessed.selfReplace("san", "ㄙㄢ")
|
||||
strProcessed.selfReplace("sao", "ㄙㄠ")
|
||||
strProcessed.selfReplace("sei", "ㄙㄟ")
|
||||
strProcessed.selfReplace("sen", "ㄙㄣ")
|
||||
strProcessed.selfReplace("sha", "ㄕㄚ")
|
||||
strProcessed.selfReplace("she", "ㄕㄜ")
|
||||
strProcessed.selfReplace("shi", "ㄕ")
|
||||
strProcessed.selfReplace("shu", "ㄕㄨ")
|
||||
strProcessed.selfReplace("sou", "ㄙㄡ")
|
||||
strProcessed.selfReplace("sui", "ㄙㄨㄟ")
|
||||
strProcessed.selfReplace("sun", "ㄙㄨㄣ")
|
||||
strProcessed.selfReplace("suo", "ㄙㄨㄛ")
|
||||
strProcessed.selfReplace("tai", "ㄊㄞ")
|
||||
strProcessed.selfReplace("tan", "ㄊㄢ")
|
||||
strProcessed.selfReplace("tao", "ㄊㄠ")
|
||||
strProcessed.selfReplace("tie", "ㄊㄧㄝ")
|
||||
strProcessed.selfReplace("tou", "ㄊㄡ")
|
||||
strProcessed.selfReplace("tui", "ㄊㄨㄟ")
|
||||
strProcessed.selfReplace("tun", "ㄊㄨㄣ")
|
||||
strProcessed.selfReplace("tuo", "ㄊㄨㄛ")
|
||||
strProcessed.selfReplace("wai", "ㄨㄞ")
|
||||
strProcessed.selfReplace("wan", "ㄨㄢ")
|
||||
strProcessed.selfReplace("wei", "ㄨㄟ")
|
||||
strProcessed.selfReplace("wen", "ㄨㄣ")
|
||||
strProcessed.selfReplace("xia", "ㄒㄧㄚ")
|
||||
strProcessed.selfReplace("xie", "ㄒㄧㄝ")
|
||||
strProcessed.selfReplace("xin", "ㄒㄧㄣ")
|
||||
strProcessed.selfReplace("xiu", "ㄒㄧㄡ")
|
||||
strProcessed.selfReplace("xue", "ㄒㄩㄝ")
|
||||
strProcessed.selfReplace("xun", "ㄒㄩㄣ")
|
||||
strProcessed.selfReplace("yai", "ㄧㄞ")
|
||||
strProcessed.selfReplace("yan", "ㄧㄢ")
|
||||
strProcessed.selfReplace("yao", "ㄧㄠ")
|
||||
strProcessed.selfReplace("yin", "ㄧㄣ")
|
||||
strProcessed.selfReplace("you", "ㄧㄡ")
|
||||
strProcessed.selfReplace("yue", "ㄩㄝ")
|
||||
strProcessed.selfReplace("yun", "ㄩㄣ")
|
||||
strProcessed.selfReplace("zai", "ㄗㄞ")
|
||||
strProcessed.selfReplace("zan", "ㄗㄢ")
|
||||
strProcessed.selfReplace("zao", "ㄗㄠ")
|
||||
strProcessed.selfReplace("zei", "ㄗㄟ")
|
||||
strProcessed.selfReplace("zen", "ㄗㄣ")
|
||||
strProcessed.selfReplace("zha", "ㄓㄚ")
|
||||
strProcessed.selfReplace("zhe", "ㄓㄜ")
|
||||
strProcessed.selfReplace("zhi", "ㄓ")
|
||||
strProcessed.selfReplace("zhu", "ㄓㄨ")
|
||||
strProcessed.selfReplace("zou", "ㄗㄡ")
|
||||
strProcessed.selfReplace("zui", "ㄗㄨㄟ")
|
||||
strProcessed.selfReplace("zun", "ㄗㄨㄣ")
|
||||
strProcessed.selfReplace("zuo", "ㄗㄨㄛ")
|
||||
strProcessed.selfReplace("ai", "ㄞ")
|
||||
strProcessed.selfReplace("an", "ㄢ")
|
||||
strProcessed.selfReplace("ao", "ㄠ")
|
||||
strProcessed.selfReplace("ba", "ㄅㄚ")
|
||||
strProcessed.selfReplace("bi", "ㄅㄧ")
|
||||
strProcessed.selfReplace("bo", "ㄅㄛ")
|
||||
strProcessed.selfReplace("bu", "ㄅㄨ")
|
||||
strProcessed.selfReplace("ca", "ㄘㄚ")
|
||||
strProcessed.selfReplace("ce", "ㄘㄜ")
|
||||
strProcessed.selfReplace("ci", "ㄘ")
|
||||
strProcessed.selfReplace("cu", "ㄘㄨ")
|
||||
strProcessed.selfReplace("da", "ㄉㄚ")
|
||||
strProcessed.selfReplace("de", "ㄉㄜ")
|
||||
strProcessed.selfReplace("di", "ㄉㄧ")
|
||||
strProcessed.selfReplace("du", "ㄉㄨ")
|
||||
strProcessed.selfReplace("eh", "ㄝ")
|
||||
strProcessed.selfReplace("ei", "ㄟ")
|
||||
strProcessed.selfReplace("en", "ㄣ")
|
||||
strProcessed.selfReplace("er", "ㄦ")
|
||||
strProcessed.selfReplace("fa", "ㄈㄚ")
|
||||
strProcessed.selfReplace("fo", "ㄈㄛ")
|
||||
strProcessed.selfReplace("fu", "ㄈㄨ")
|
||||
strProcessed.selfReplace("ga", "ㄍㄚ")
|
||||
strProcessed.selfReplace("ge", "ㄍㄜ")
|
||||
strProcessed.selfReplace("gi", "ㄍㄧ")
|
||||
strProcessed.selfReplace("gu", "ㄍㄨ")
|
||||
strProcessed.selfReplace("ha", "ㄏㄚ")
|
||||
strProcessed.selfReplace("he", "ㄏㄜ")
|
||||
strProcessed.selfReplace("hu", "ㄏㄨ")
|
||||
strProcessed.selfReplace("ji", "ㄐㄧ")
|
||||
strProcessed.selfReplace("ju", "ㄐㄩ")
|
||||
strProcessed.selfReplace("ka", "ㄎㄚ")
|
||||
strProcessed.selfReplace("ke", "ㄎㄜ")
|
||||
strProcessed.selfReplace("ku", "ㄎㄨ")
|
||||
strProcessed.selfReplace("la", "ㄌㄚ")
|
||||
strProcessed.selfReplace("le", "ㄌㄜ")
|
||||
strProcessed.selfReplace("li", "ㄌㄧ")
|
||||
strProcessed.selfReplace("lo", "ㄌㄛ")
|
||||
strProcessed.selfReplace("lu", "ㄌㄨ")
|
||||
strProcessed.selfReplace("lv", "ㄌㄩ")
|
||||
strProcessed.selfReplace("ma", "ㄇㄚ")
|
||||
strProcessed.selfReplace("me", "ㄇㄜ")
|
||||
strProcessed.selfReplace("mi", "ㄇㄧ")
|
||||
strProcessed.selfReplace("mo", "ㄇㄛ")
|
||||
strProcessed.selfReplace("mu", "ㄇㄨ")
|
||||
strProcessed.selfReplace("na", "ㄋㄚ")
|
||||
strProcessed.selfReplace("ne", "ㄋㄜ")
|
||||
strProcessed.selfReplace("ni", "ㄋㄧ")
|
||||
strProcessed.selfReplace("nu", "ㄋㄨ")
|
||||
strProcessed.selfReplace("nv", "ㄋㄩ")
|
||||
strProcessed.selfReplace("ou", "ㄡ")
|
||||
strProcessed.selfReplace("pa", "ㄆㄚ")
|
||||
strProcessed.selfReplace("pi", "ㄆㄧ")
|
||||
strProcessed.selfReplace("po", "ㄆㄛ")
|
||||
strProcessed.selfReplace("pu", "ㄆㄨ")
|
||||
strProcessed.selfReplace("qi", "ㄑㄧ")
|
||||
strProcessed.selfReplace("qu", "ㄑㄩ")
|
||||
strProcessed.selfReplace("re", "ㄖㄜ")
|
||||
strProcessed.selfReplace("ri", "ㄖ")
|
||||
strProcessed.selfReplace("ru", "ㄖㄨ")
|
||||
strProcessed.selfReplace("sa", "ㄙㄚ")
|
||||
strProcessed.selfReplace("se", "ㄙㄜ")
|
||||
strProcessed.selfReplace("si", "ㄙ")
|
||||
strProcessed.selfReplace("su", "ㄙㄨ")
|
||||
strProcessed.selfReplace("ta", "ㄊㄚ")
|
||||
strProcessed.selfReplace("te", "ㄊㄜ")
|
||||
strProcessed.selfReplace("ti", "ㄊㄧ")
|
||||
strProcessed.selfReplace("tu", "ㄊㄨ")
|
||||
strProcessed.selfReplace("wa", "ㄨㄚ")
|
||||
strProcessed.selfReplace("wo", "ㄨㄛ")
|
||||
strProcessed.selfReplace("wu", "ㄨ")
|
||||
strProcessed.selfReplace("xi", "ㄒㄧ")
|
||||
strProcessed.selfReplace("xu", "ㄒㄩ")
|
||||
strProcessed.selfReplace("ya", "ㄧㄚ")
|
||||
strProcessed.selfReplace("ye", "ㄧㄝ")
|
||||
strProcessed.selfReplace("yi", "ㄧ")
|
||||
strProcessed.selfReplace("yo", "ㄧㄛ")
|
||||
strProcessed.selfReplace("yu", "ㄩ")
|
||||
strProcessed.selfReplace("za", "ㄗㄚ")
|
||||
strProcessed.selfReplace("ze", "ㄗㄜ")
|
||||
strProcessed.selfReplace("zi", "ㄗ")
|
||||
strProcessed.selfReplace("zu", "ㄗㄨ")
|
||||
strProcessed.selfReplace("a", "ㄚ")
|
||||
strProcessed.selfReplace("e", "ㄜ")
|
||||
strProcessed.selfReplace("o", "ㄛ")
|
||||
strProcessed.selfReplace("q", "ㄑ")
|
||||
strProcessed.selfReplace("2", "ˊ")
|
||||
strProcessed.selfReplace("3", "ˇ")
|
||||
strProcessed.selfReplace("4", "ˋ")
|
||||
strProcessed.selfReplace("5", "˙")
|
||||
strProcessed.selfReplace("1", "")
|
||||
}
|
||||
|
||||
// Step 3: Add Formatted Pragma, the Sorted Header:
|
||||
let hdrFormatted = "# 𝙵𝙾𝚁𝙼𝙰𝚃 𝚘𝚛𝚐.𝚊𝚝𝚎𝚕𝚒𝚎𝚛𝙸𝚗𝚖𝚞.𝚟𝚌𝚑𝚎𝚠𝚒𝚗𝚐.𝚞𝚜𝚎𝚛𝙻𝚊𝚗𝚐𝚞𝚊𝚐𝚎𝙼𝚘𝚍𝚎𝚕𝙳𝚊𝚝𝚊.𝚏𝚘𝚛𝚖𝚊𝚝𝚝𝚎𝚍\n"
|
||||
strProcessed = hdrFormatted + strProcessed // Add Sorted Header
|
||||
|
|
|
@ -726,7 +726,7 @@
|
|||
<key>USE_HFS+_COMPRESSION</key>
|
||||
<false/>
|
||||
<key>VERSION</key>
|
||||
<string>1.8.0</string>
|
||||
<string>1.8.1</string>
|
||||
</dict>
|
||||
<key>TYPE</key>
|
||||
<integer>0</integer>
|
||||
|
|
|
@ -109,6 +109,12 @@
|
|||
5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB720283B4AEA0078EB25 /* data-cht.plist */; };
|
||||
5BEDB724283B4C250078EB25 /* data-symbols.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */; };
|
||||
5BEDB725283B4C250078EB25 /* data-chs.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71C283B4AEA0078EB25 /* data-chs.plist */; };
|
||||
5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */; };
|
||||
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2328840E6200DBD48E /* template-exclusions.txt */; };
|
||||
5BF9DA2928840E6200DBD48E /* template-associatedPhrases-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */; };
|
||||
5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2528840E6200DBD48E /* template-replacements.txt */; };
|
||||
5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2628840E6200DBD48E /* template-userphrases.txt */; };
|
||||
5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */; };
|
||||
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6A187E2816004C5900466B2E /* MainMenu.xib */; };
|
||||
6A225A1F23679F2600F685C6 /* NotarizedArchives in Resources */ = {isa = PBXBuildFile; fileRef = 6A225A1E23679F2600F685C6 /* NotarizedArchives */; };
|
||||
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; };
|
||||
|
@ -306,6 +312,12 @@
|
|||
5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-symbols.plist"; path = "Data/data-symbols.plist"; sourceTree = "<group>"; };
|
||||
5BEDB71F283B4AEA0078EB25 /* data-zhuyinwen.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-zhuyinwen.plist"; path = "Data/data-zhuyinwen.plist"; sourceTree = "<group>"; };
|
||||
5BEDB720283B4AEA0078EB25 /* data-cht.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = "data-cht.plist"; path = "Data/data-cht.plist"; sourceTree = "<group>"; };
|
||||
5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-usersymbolphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
|
||||
5BF9DA2328840E6200DBD48E /* template-exclusions.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-exclusions.txt"; sourceTree = "<group>"; usesTabs = 0; };
|
||||
5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-chs.txt"; path = "../Data/components/chs/template-associatedPhrases-chs.txt"; sourceTree = "<group>"; usesTabs = 0; };
|
||||
5BF9DA2528840E6200DBD48E /* template-replacements.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-replacements.txt"; sourceTree = "<group>"; usesTabs = 0; };
|
||||
5BF9DA2628840E6200DBD48E /* template-userphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-userphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
|
||||
5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-cht.txt"; path = "../Data/components/cht/template-associatedPhrases-cht.txt"; sourceTree = "<group>"; };
|
||||
5BFDF48C27B51867009523B6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = "<group>"; };
|
||||
6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewing.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6A0D4EF515FC0DA600ABF4B3 /* IME-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "IME-Info.plist"; sourceTree = "<group>"; };
|
||||
|
@ -502,6 +514,12 @@
|
|||
5B62A33027AE78E500A19448 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5BF9DA2428840E6200DBD48E /* template-associatedPhrases-chs.txt */,
|
||||
5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */,
|
||||
5BF9DA2328840E6200DBD48E /* template-exclusions.txt */,
|
||||
5BF9DA2528840E6200DBD48E /* template-replacements.txt */,
|
||||
5BF9DA2628840E6200DBD48E /* template-userphrases.txt */,
|
||||
5BF9DA2228840E6200DBD48E /* template-usersymbolphrases.txt */,
|
||||
6A0D4EEE15FC0DA600ABF4B3 /* Images */,
|
||||
5BBBB76E27AED70B0023B93A /* MenuIcons */,
|
||||
5BBBB75C27AED54C0023B93A /* SoundFiles */,
|
||||
|
@ -860,9 +878,9 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6A0D4EC015FC0D2E00ABF4B3 /* Build configuration list for PBXNativeTarget "vChewing" */;
|
||||
buildPhases = (
|
||||
5B9A5A00285184BB001FFCAF /* ShellScript */,
|
||||
6A0D4E9E15FC0D2D00ABF4B3 /* Sources */,
|
||||
6A0D4E9F15FC0D2D00ABF4B3 /* Frameworks */,
|
||||
5B9A5A00285184BB001FFCAF /* ShellScript */,
|
||||
6A0D4EA015FC0D2D00ABF4B3 /* Resources */,
|
||||
5BDC5CBE27C28E8B00E1CCE2 /* Embed Foundation Extensions */,
|
||||
);
|
||||
|
@ -984,6 +1002,7 @@
|
|||
5B84579E2871AD2200C93B01 /* convdict.plist in Resources */,
|
||||
5BBBB77427AED70B0023B93A /* MenuIcon-SCVIM@2x.png in Resources */,
|
||||
D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */,
|
||||
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */,
|
||||
5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */,
|
||||
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */,
|
||||
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */,
|
||||
|
@ -991,12 +1010,17 @@
|
|||
5BBBB76B27AED5DB0023B93A /* frmNonModalAlertWindow.xib in Resources */,
|
||||
5BEDB723283B4C250078EB25 /* data-cht.plist in Resources */,
|
||||
5BEDB721283B4C250078EB25 /* data-cns.plist in Resources */,
|
||||
5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */,
|
||||
5BEDB725283B4C250078EB25 /* data-chs.plist in Resources */,
|
||||
5BF9DA2928840E6200DBD48E /* template-associatedPhrases-chs.txt in Resources */,
|
||||
5BBBB76D27AED5DB0023B93A /* frmAboutWindow.xib in Resources */,
|
||||
5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */,
|
||||
5BBBB77527AED70B0023B93A /* MenuIcon-SCVIM.png in Resources */,
|
||||
5BEDB722283B4C250078EB25 /* data-zhuyinwen.plist in Resources */,
|
||||
5BF9DA2728840E6200DBD48E /* template-usersymbolphrases.txt in Resources */,
|
||||
5BEDB724283B4C250078EB25 /* data-symbols.plist in Resources */,
|
||||
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */,
|
||||
5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */,
|
||||
5BBBB77327AED70B0023B93A /* MenuIcon-TCVIM@2x.png in Resources */,
|
||||
5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */,
|
||||
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */,
|
||||
|
@ -1365,7 +1389,7 @@
|
|||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
|
@ -1375,7 +1399,7 @@
|
|||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
|
||||
|
@ -1404,13 +1428,13 @@
|
|||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
|
||||
|
@ -1441,7 +1465,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
|
@ -1462,7 +1486,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
|
||||
|
@ -1491,7 +1515,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
|
@ -1508,7 +1532,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
|
||||
|
@ -1618,7 +1642,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1649,7 +1673,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1676,7 +1700,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
|
@ -1701,7 +1725,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1723,7 +1747,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
@ -1744,7 +1768,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1766,7 +1790,7 @@
|
|||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1980;
|
||||
CURRENT_PROJECT_VERSION = 1981;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
@ -1781,7 +1805,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.8.0;
|
||||
MARKETING_VERSION = 1.8.1;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
|