diff --git a/Source/AppDelegate.swift b/Source/AppDelegate.swift
index f93bf8b2..f8d348fb 100644
--- a/Source/AppDelegate.swift
+++ b/Source/AppDelegate.swift
@@ -51,6 +51,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NonModalAlertWindowControlle
private var updateNextStepURL: URL?
func applicationDidFinishLaunching(_ notification: Notification) {
+ LanguageModelManager.setupDataModelValueConverter()
LanguageModelManager.loadDataModels()
LanguageModelManager.loadUserPhrases()
LanguageModelManager.loadUserPhraseReplacement()
diff --git a/Source/Base.lproj/preferences.xib b/Source/Base.lproj/preferences.xib
index 451d8d39..25ee9a38 100644
--- a/Source/Base.lproj/preferences.xib
+++ b/Source/Base.lproj/preferences.xib
@@ -19,14 +19,14 @@
-
+
-
+
-
+
@@ -35,7 +35,7 @@
-
+
@@ -47,7 +47,7 @@
-
+
@@ -56,7 +56,7 @@
-
+
@@ -84,7 +84,7 @@
-
+
@@ -93,7 +93,7 @@
-
+
@@ -114,7 +114,7 @@
-
+
@@ -134,7 +134,7 @@
-
+
@@ -143,7 +143,7 @@
-
+
@@ -152,7 +152,7 @@
-
+
@@ -161,7 +161,7 @@
-
+
@@ -187,7 +187,7 @@
-
+
@@ -212,8 +212,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -239,7 +274,7 @@
-
+
@@ -261,12 +296,8 @@
-
-
-
-
+
+
+
+
-
+
diff --git a/Source/Engine/McBopomofoLM.cpp b/Source/Engine/McBopomofoLM.cpp
index 3fba9fc9..1e235447 100644
--- a/Source/Engine/McBopomofoLM.cpp
+++ b/Source/Engine/McBopomofoLM.cpp
@@ -121,20 +121,46 @@ bool McBopomofoLM::phraseReplacementEnabled()
return m_phraseReplacementEnabled;
}
+void McBopomofoLM::setExternalConverterEnabled(bool enabled)
+{
+ m_externalConverterEnabled = enabled;
+}
+
+bool McBopomofoLM::externalConverterEnabled()
+{
+ return m_externalConverterEnabled;
+}
+
+void McBopomofoLM::setExternalConvrter(std::function externalConverter)
+{
+ m_externalConverter = externalConverter;
+}
+
const vector McBopomofoLM::filterAndTransformUnigrams(vector unigrams, const unordered_set& excludedValues, unordered_set& insertedValues)
{
vector results;
for (auto&& unigram : unigrams) {
- string value = unigram.keyValue.value;
+ // excludedValues filters out the unigrams with the original value.
+ // insertedValues filters out the ones with the converted value
+ string originalValue = unigram.keyValue.value;
+ if (excludedValues.find(originalValue) != excludedValues.end()) {
+ continue;
+ }
+
+ string value = originalValue;
if (m_phraseReplacementEnabled) {
string replacement = m_phraseReplacement.valueForKey(value);
if (replacement != "") {
value = replacement;
- unigram.keyValue.value = value;
}
}
- if (excludedValues.find(value) == excludedValues.end() && insertedValues.find(value) == insertedValues.end()) {
+ if (m_externalConverterEnabled && m_externalConverter) {
+ string replacement = m_externalConverter(value);
+ value = replacement;
+ }
+ unigram.keyValue.value = value;
+ if (insertedValues.find(value) == insertedValues.end()) {
results.push_back(unigram);
insertedValues.insert(value);
}
diff --git a/Source/Engine/McBopomofoLM.h b/Source/Engine/McBopomofoLM.h
index 00dbc360..63ae7361 100644
--- a/Source/Engine/McBopomofoLM.h
+++ b/Source/Engine/McBopomofoLM.h
@@ -50,6 +50,10 @@ public:
void setPhraseReplacementEnabled(bool enabled);
bool phraseReplacementEnabled();
+ void setExternalConverterEnabled(bool enabled);
+ bool externalConverterEnabled();
+ void setExternalConvrter(std::function externalConverter);
+
protected:
const vector filterAndTransformUnigrams(vector unigrams,
const std::unordered_set& excludedValues,
@@ -60,6 +64,8 @@ protected:
UserPhrasesLM m_excludedPhrases;
PhraseReplacementMap m_phraseReplacement;
bool m_phraseReplacementEnabled;
+ bool m_externalConverterEnabled;
+ std::function m_externalConverter;
};
};
diff --git a/Source/InputMethodController.mm b/Source/InputMethodController.mm
index 762e7665..16963ebc 100644
--- a/Source/InputMethodController.mm
+++ b/Source/InputMethodController.mm
@@ -243,6 +243,8 @@ static double FindHighestScore(const vector& nodes, double epsilon)
Preferences.keyboardLayout = KeyboardLayoutStandard;
}
+ _languageModel->setExternalConverterEnabled(Preferences.chineseConversionStyle == 1);
+
[(AppDelegate *)[NSApp delegate] checkForUpdate];
}
@@ -275,12 +277,14 @@ static double FindHighestScore(const vector& nodes, double epsilon)
if ([value isKindOfClass:[NSString class]] && [value isEqual:kPlainBopomofoModeIdentifier]) {
newInputMode = kPlainBopomofoModeIdentifier;
newLanguageModel = [LanguageModelManager languageModelPlainBopomofo];
+ newLanguageModel->setPhraseReplacementEnabled(false);
}
else {
newInputMode = kBopomofoModeIdentifier;
newLanguageModel = [LanguageModelManager languageModelMcBopomofo];
newLanguageModel->setPhraseReplacementEnabled(Preferences.phraseReplacementEnabled);
}
+ newLanguageModel->setExternalConverterEnabled(Preferences.chineseConversionStyle == 1);
// Only apply the changes if the value is changed
if (![_inputMode isEqualToString:newInputMode]) {
@@ -312,8 +316,16 @@ static double FindHighestScore(const vector& nodes, double epsilon)
#pragma mark - IMKServerInput protocol methods
-- (NSString *)_convertToSimplifiedChinese:(NSString *)text
+- (NSString *)_convertToSimplifiedChineseIfRequired:(NSString *)text
{
+ if (!Preferences.chineseConversionEnabled) {
+ return text;
+ }
+
+ if (Preferences.chineseConversionStyle == 1) {
+ return text;
+ }
+
if (Preferences.chineneConversionEngine == 1) {
return [VXHanConvert convertToSimplifiedFrom:text];
}
@@ -333,11 +345,7 @@ static double FindHighestScore(const vector& nodes, double epsilon)
}
// Chinese conversion.
- NSString *buffer = _composingBuffer;
-
- if (Preferences.chineseConversionEnabled) {
- buffer = [self _convertToSimplifiedChinese:_composingBuffer];
- }
+ NSString *buffer = [self _convertToSimplifiedChineseIfRequired:_composingBuffer];
// commit the text, clear the state
[client insertText:buffer replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
@@ -483,10 +491,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
NodeAnchor &anchor = _walkedNodes[0];
NSString *popedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()];
// Chinese conversion.
- BOOL chineseConversionEnabled = Preferences.chineseConversionEnabled;
- if (chineseConversionEnabled) {
- popedText = [self _convertToSimplifiedChinese:popedText];
- }
+ popedText = [self _convertToSimplifiedChineseIfRequired:popedText];
[client insertText:popedText replacementRange:NSMakeRange(NSNotFound, NSNotFound)];
_builder->removeHeadReadings(anchor.spanningLength);
}
diff --git a/Source/LanguageModelManager.h b/Source/LanguageModelManager.h
index 6a82c47a..ce28eaf5 100644
--- a/Source/LanguageModelManager.h
+++ b/Source/LanguageModelManager.h
@@ -9,6 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)loadDataModels;
+ (void)loadUserPhrases;
+ (void)loadUserPhraseReplacement;
++ (void)setupDataModelValueConverter;
+ (BOOL)checkIfUserLanguageModelFilesExist;
+ (BOOL)writeUserPhrase:(NSString *)userPhrase;
diff --git a/Source/LanguageModelManager.mm b/Source/LanguageModelManager.mm
index 189e2eb6..37fa2897 100644
--- a/Source/LanguageModelManager.mm
+++ b/Source/LanguageModelManager.mm
@@ -4,6 +4,10 @@
#import
#import "OVStringHelper.h"
#import "OVUTF8Helper.h"
+#import "McBopomofo-Swift.h"
+
+@import VXHanConvert;
+@import OpenCCBridge;
using namespace std;
using namespace Formosa::Gramambular;
@@ -43,6 +47,31 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, McBopomo
gLanguageModelMcBopomofo.loadPhraseReplacementMap([[self phraseReplacementDataPathMcBopomofo] UTF8String]);
}
++ (void)setupDataModelValueConverter
+{
+ auto converter = [] (string input) {
+ if (!Preferences.chineseConversionEnabled) {
+ return input;
+ }
+
+ if (Preferences.chineseConversionStyle == 0) {
+ return input;
+ }
+
+ NSString *text = [NSString stringWithUTF8String:input.c_str()];
+ if (Preferences.chineneConversionEngine == 1) {
+ text = [VXHanConvert convertToSimplifiedFrom:text];
+ }
+ else {
+ text = [OpenCCBridge convertToSimplified:text];
+ }
+ return string(text.UTF8String);
+ };
+
+ gLanguageModelMcBopomofo.setExternalConvrter(converter);
+ gLanguageModelPlainBopomofo.setExternalConvrter(converter);
+}
+
+ (BOOL)checkIfUserDataFolderExists
{
NSString *folderPath = [self dataFolderPath];
diff --git a/Source/McBopomofo-Bridging-Header.h b/Source/McBopomofo-Bridging-Header.h
index 8310cc67..69a7fc4f 100644
--- a/Source/McBopomofo-Bridging-Header.h
+++ b/Source/McBopomofo-Bridging-Header.h
@@ -8,4 +8,5 @@
+ (void)loadDataModels;
+ (void)loadUserPhrases;
+ (void)loadUserPhraseReplacement;
++ (void)setupDataModelValueConverter;
@end
diff --git a/Source/Preferences.swift b/Source/Preferences.swift
index e1f2303c..61ecead0 100644
--- a/Source/Preferences.swift
+++ b/Source/Preferences.swift
@@ -50,8 +50,9 @@ private let kEscToCleanInputBufferKey = "EscToCleanInputBuffer"
private let kCandidateTextFontName = "CandidateTextFontName"
private let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
private let kCandidateKeys = "CandidateKeys"
-private let kChineseConversionEngineKey = "ChineseConversionEngine"
private let kPhraseReplacementEnabledKey = "PhraseReplacementEnabled"
+private let kChineseConversionEngineKey = "ChineseConversionEngine"
+private let kChineseConversionStyle = "ChineseConversionStyle"
private let kDefaultCandidateListTextSize: CGFloat = 16
private let kMinKeyLabelSize: CGFloat = 10
@@ -217,6 +218,20 @@ struct ComposingKeys {
}
}
+@objc enum ChineseConversionStyle: Int {
+ case output
+ case model
+
+ var name: String {
+ switch (self) {
+ case .output:
+ return "output"
+ case .model:
+ return "model"
+ }
+ }
+}
+
// MARK: -
class Preferences: NSObject {
@@ -285,13 +300,6 @@ class Preferences: NSObject {
kDefaultKeys
}
- @UserDefault(key: kChineseConversionEngineKey, defaultValue: 0)
- @objc static var chineneConversionEngine: Int
-
- @objc static var chineneConversionEngineName: String? {
- return ChineseConversionEngine(rawValue: chineneConversionEngine)?.name
- }
-
@UserDefault(key: kPhraseReplacementEnabledKey, defaultValue: false)
@objc static var phraseReplacementEnabled: Bool
@@ -300,4 +308,26 @@ class Preferences: NSObject {
return phraseReplacementEnabled;
}
+ /// The conversion engine.
+ ///
+ /// - 0: OpenCC
+ /// - 1: VXHanConvert
+ @UserDefault(key: kChineseConversionEngineKey, defaultValue: 0)
+ @objc static var chineneConversionEngine: Int
+
+ @objc static var chineneConversionEngineName: String? {
+ return ChineseConversionEngine(rawValue: chineneConversionEngine)?.name
+ }
+
+ /// The conversion style.
+ ///
+ /// - 0: convert the output
+ /// - 1: convert the phrase models.
+ @UserDefault(key: kChineseConversionStyle, defaultValue: 0)
+ @objc static var chineseConversionStyle: Int
+
+ @objc static var chineseConversionStyleName: String? {
+ return ChineseConversionStyle(rawValue: chineseConversionStyle)?.name
+ }
+
}
diff --git a/Source/zh-Hant.lproj/preferences.xib b/Source/zh-Hant.lproj/preferences.xib
index 6cd9981c..3aad70ae 100644
--- a/Source/zh-Hant.lproj/preferences.xib
+++ b/Source/zh-Hant.lproj/preferences.xib
@@ -19,14 +19,14 @@
-
+
-
+
-
+
@@ -49,7 +49,7 @@
-
+
@@ -58,7 +58,7 @@
-
+
@@ -70,7 +70,7 @@
-
+
@@ -79,7 +79,7 @@
-
+
@@ -88,7 +88,7 @@
-
+
@@ -97,7 +97,7 @@
-
+
@@ -123,7 +123,7 @@
-
+
@@ -149,7 +149,7 @@
-
+
@@ -172,7 +172,7 @@
-
+
@@ -200,7 +200,7 @@
-
+
@@ -209,7 +209,7 @@
-
+
@@ -229,16 +229,16 @@
-
+
-
+
-
+
@@ -263,12 +263,43 @@
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+