添加联想词库

This commit is contained in:
2026-03-04 14:15:45 +08:00
parent b1f1ddec7e
commit f9da0c40e5
11 changed files with 195433 additions and 130 deletions

View File

@@ -406,6 +406,7 @@ static NSString *KBFormatMB(uint64_t bytes) {
case KBSuggestionEngineTypeBopomofo: case KBSuggestionEngineTypeBopomofo:
return [self kb_bopomofoSuggestionCharacterSet]; return [self kb_bopomofoSuggestionCharacterSet];
case KBSuggestionEngineTypeLatin: case KBSuggestionEngineTypeLatin:
case KBSuggestionEngineTypeEnglish:
case KBSuggestionEngineTypePortuguese: case KBSuggestionEngineTypePortuguese:
case KBSuggestionEngineTypeIndonesian: case KBSuggestionEngineTypeIndonesian:
case KBSuggestionEngineTypePinyinSimplified: case KBSuggestionEngineTypePinyinSimplified:

View File

@@ -95,6 +95,7 @@
case KBSuggestionEngineTypeBopomofo: case KBSuggestionEngineTypeBopomofo:
return [self kb_bopomofoSuggestionCharacterSet]; return [self kb_bopomofoSuggestionCharacterSet];
case KBSuggestionEngineTypeLatin: case KBSuggestionEngineTypeLatin:
case KBSuggestionEngineTypeEnglish:
case KBSuggestionEngineTypePortuguese: case KBSuggestionEngineTypePortuguese:
case KBSuggestionEngineTypeIndonesian: case KBSuggestionEngineTypeIndonesian:
case KBSuggestionEngineTypePinyinSimplified: case KBSuggestionEngineTypePinyinSimplified:

View File

@@ -8,7 +8,8 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, KBSuggestionEngineType) { typedef NS_ENUM(NSInteger, KBSuggestionEngineType) {
KBSuggestionEngineTypeLatin = 0, // 拉丁字母(英语 KBSuggestionEngineTypeLatin = 0, // 拉丁字母(兼容旧值
KBSuggestionEngineTypeEnglish, // 英语
KBSuggestionEngineTypeSpanish, // 西班牙语 KBSuggestionEngineTypeSpanish, // 西班牙语
KBSuggestionEngineTypePortuguese, // 葡萄牙语 KBSuggestionEngineTypePortuguese, // 葡萄牙语
KBSuggestionEngineTypeIndonesian, // 印度尼西亚语 KBSuggestionEngineTypeIndonesian, // 印度尼西亚语

View File

@@ -15,6 +15,7 @@
@property (nonatomic, strong) NSDictionary<NSString *, NSArray<NSString *> *> *pinyinToTraditionalMap; @property (nonatomic, strong) NSDictionary<NSString *, NSArray<NSString *> *> *pinyinToTraditionalMap;
@property (nonatomic, strong) NSDictionary<NSString *, NSArray<NSString *> *> *bopomofoToChineseMap; @property (nonatomic, strong) NSDictionary<NSString *, NSArray<NSString *> *> *bopomofoToChineseMap;
@property (nonatomic, copy) NSArray<NSString *> *spanishWords; @property (nonatomic, copy) NSArray<NSString *> *spanishWords;
@property (nonatomic, copy) NSArray<NSString *> *englishWords;
@property (nonatomic, copy) NSArray<NSString *> *portugueseWords; @property (nonatomic, copy) NSArray<NSString *> *portugueseWords;
@property (nonatomic, copy) NSArray<NSString *> *indonesianWords; @property (nonatomic, copy) NSArray<NSString *> *indonesianWords;
@end @end
@@ -42,6 +43,7 @@
_pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap]; _pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap];
_bopomofoToChineseMap = [self kb_loadBopomofoToChineseMap]; _bopomofoToChineseMap = [self kb_loadBopomofoToChineseMap];
_spanishWords = [self kb_loadSpanishWords]; _spanishWords = [self kb_loadSpanishWords];
_englishWords = [self kb_loadEnglishWords];
_portugueseWords = [self kb_loadPortugueseWords]; _portugueseWords = [self kb_loadPortugueseWords];
_indonesianWords = [self kb_loadIndonesianWords]; _indonesianWords = [self kb_loadIndonesianWords];
} }
@@ -52,6 +54,8 @@
if (prefix.length == 0 || limit == 0) { return @[]; } if (prefix.length == 0 || limit == 0) { return @[]; }
switch (self.engineType) { switch (self.engineType) {
case KBSuggestionEngineTypeEnglish:
return [self kb_englishSuggestionsForPrefix:prefix limit:limit];
case KBSuggestionEngineTypeSpanish: case KBSuggestionEngineTypeSpanish:
return [self kb_spanishSuggestionsForPrefix:prefix limit:limit]; return [self kb_spanishSuggestionsForPrefix:prefix limit:limit];
case KBSuggestionEngineTypePortuguese: case KBSuggestionEngineTypePortuguese:
@@ -171,6 +175,8 @@
self.engineType = KBSuggestionEngineTypeLatin; self.engineType = KBSuggestionEngineTypeLatin;
} else if ([engineTypeString isEqualToString:@"spanish"]) { } else if ([engineTypeString isEqualToString:@"spanish"]) {
self.engineType = KBSuggestionEngineTypeSpanish; self.engineType = KBSuggestionEngineTypeSpanish;
} else if ([engineTypeString isEqualToString:@"english"]) {
self.engineType = KBSuggestionEngineTypeEnglish;
} else if ([engineTypeString isEqualToString:@"portuguese"]) { } else if ([engineTypeString isEqualToString:@"portuguese"]) {
self.engineType = KBSuggestionEngineTypePortuguese; self.engineType = KBSuggestionEngineTypePortuguese;
} else if ([engineTypeString isEqualToString:@"indonesian"]) { } else if ([engineTypeString isEqualToString:@"indonesian"]) {
@@ -187,6 +193,55 @@
NSLog(@"[KBSuggestionEngine] Engine type set to: %@", engineTypeString); NSLog(@"[KBSuggestionEngine] Engine type set to: %@", engineTypeString);
} }
#pragma mark - English Suggestions
- (NSArray<NSString *> *)kb_englishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.englishWords
prefix:prefix
limit:limit];
if (matches.count == 0) {
return [self kb_latinSuggestionsForPrefix:prefix limit:limit];
}
return matches;
}
- (NSArray<NSString *> *)kb_loadEnglishWords {
NSString *path = [[NSBundle mainBundle] pathForResource:@"english_words" ofType:@"json"];
if (!path) {
NSLog(@"[KBSuggestionEngine] english_words.json not found, using default words");
return [self.class kb_defaultWords];
}
NSData *data = [NSData dataWithContentsOfFile:path];
if (!data) {
NSLog(@"[KBSuggestionEngine] Failed to read english_words.json");
return [self.class kb_defaultWords];
}
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error || ![json isKindOfClass:NSDictionary.class]) {
NSLog(@"[KBSuggestionEngine] Failed to parse english_words.json: %@", error);
return [self.class kb_defaultWords];
}
NSArray *wordsArray = json[@"words"];
if (![wordsArray isKindOfClass:NSArray.class]) {
NSLog(@"[KBSuggestionEngine] Invalid words array in english_words.json");
return [self.class kb_defaultWords];
}
NSMutableArray<NSString *> *result = [NSMutableArray array];
for (id item in wordsArray) {
if ([item isKindOfClass:NSString.class]) {
[result addObject:item];
}
}
NSLog(@"[KBSuggestionEngine] Loaded %lu English words", (unsigned long)result.count);
return result.count > 0 ? [result copy] : [self.class kb_defaultWords];
}
#pragma mark - Latin Suggestions #pragma mark - Latin Suggestions
- (NSArray<NSString *> *)kb_latinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit { - (NSArray<NSString *> *)kb_latinSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -113,7 +113,7 @@
@"code": @"en", @"code": @"en",
@"name": @"English", @"name": @"English",
@"defaultSkinZip": @"normal_them.zip", @"defaultSkinZip": @"normal_them.zip",
@"layouts": @[@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"en_US_qwerty", @"layoutJsonId": @"letters", @"suggestionEngine": @"latin"}] @"layouts": @[@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"en_US_qwerty", @"layoutJsonId": @"letters", @"suggestionEngine": @"english"}]
}, },
@{ @{
@"code": @"es", @"code": @"es",

View File

@@ -11,7 +11,7 @@
"title": "QWERTY", "title": "QWERTY",
"profileId": "en_US_qwerty", "profileId": "en_US_qwerty",
"layoutJsonId": "letters", "layoutJsonId": "letters",
"suggestionEngine": "latin" "suggestionEngine": "english"
} }
] ]
}, },

View File

@@ -45,6 +45,7 @@
043213B12F556DF80065C888 /* KBSkinIconMap_es.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AB2F556DF80065C888 /* KBSkinIconMap_es.strings */; }; 043213B12F556DF80065C888 /* KBSkinIconMap_es.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AB2F556DF80065C888 /* KBSkinIconMap_es.strings */; };
043213B22F556DF80065C888 /* KBSkinIconMap_zh_hant.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */; }; 043213B22F556DF80065C888 /* KBSkinIconMap_zh_hant.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */; };
043213B62F5582710065C888 /* spanish_words.json in Resources */ = {isa = PBXBuildFile; fileRef = 043213B52F5582710065C888 /* spanish_words.json */; }; 043213B62F5582710065C888 /* spanish_words.json in Resources */ = {isa = PBXBuildFile; fileRef = 043213B52F5582710065C888 /* spanish_words.json */; };
B7F1A1E52F90000100000001 /* english_words.json in Resources */ = {isa = PBXBuildFile; fileRef = B7F1A1E62F90000100000001 /* english_words.json */; };
B7F1A1E12F90000100000001 /* portuguese_words.json in Resources */ = {isa = PBXBuildFile; fileRef = B7F1A1E32F90000100000001 /* portuguese_words.json */; }; B7F1A1E12F90000100000001 /* portuguese_words.json in Resources */ = {isa = PBXBuildFile; fileRef = B7F1A1E32F90000100000001 /* portuguese_words.json */; };
B7F1A1E22F90000100000001 /* indonesian_words.json in Resources */ = {isa = PBXBuildFile; fileRef = B7F1A1E42F90000100000001 /* indonesian_words.json */; }; B7F1A1E22F90000100000001 /* indonesian_words.json in Resources */ = {isa = PBXBuildFile; fileRef = B7F1A1E42F90000100000001 /* indonesian_words.json */; };
043213BD2F56A3920065C888 /* 西班牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */; }; 043213BD2F56A3920065C888 /* 西班牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */; };
@@ -419,6 +420,7 @@
043213B52F5582710065C888 /* spanish_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = spanish_words.json; sourceTree = "<group>"; }; 043213B52F5582710065C888 /* spanish_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = spanish_words.json; sourceTree = "<group>"; };
B7F1A1E32F90000100000001 /* portuguese_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = portuguese_words.json; sourceTree = "<group>"; }; B7F1A1E32F90000100000001 /* portuguese_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = portuguese_words.json; sourceTree = "<group>"; };
B7F1A1E42F90000100000001 /* indonesian_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = indonesian_words.json; sourceTree = "<group>"; }; B7F1A1E42F90000100000001 /* indonesian_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = indonesian_words.json; sourceTree = "<group>"; };
B7F1A1E62F90000100000001 /* english_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = english_words.json; sourceTree = "<group>"; };
043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "葡萄牙初始皮肤.zip"; sourceTree = "<group>"; }; 043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "葡萄牙初始皮肤.zip"; sourceTree = "<group>"; };
043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "西班牙初始皮肤.zip"; sourceTree = "<group>"; }; 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "西班牙初始皮肤.zip"; sourceTree = "<group>"; };
043213BF2F56C9330065C888 /* 印度尼西亚初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "印度尼西亚初始皮肤.zip"; sourceTree = "<group>"; }; 043213BF2F56C9330065C888 /* 印度尼西亚初始皮肤.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = "印度尼西亚初始皮肤.zip"; sourceTree = "<group>"; };
@@ -982,6 +984,7 @@
043213AD2F556DF80065C888 /* KBSkinIconMap_pt.strings */, 043213AD2F556DF80065C888 /* KBSkinIconMap_pt.strings */,
043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */, 043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */,
043213B52F5582710065C888 /* spanish_words.json */, 043213B52F5582710065C888 /* spanish_words.json */,
B7F1A1E62F90000100000001 /* english_words.json */,
B7F1A1E32F90000100000001 /* portuguese_words.json */, B7F1A1E32F90000100000001 /* portuguese_words.json */,
B7F1A1E42F90000100000001 /* indonesian_words.json */, B7F1A1E42F90000100000001 /* indonesian_words.json */,
043213A22F5528140065C888 /* pinyin_to_traditional.json */, 043213A22F5528140065C888 /* pinyin_to_traditional.json */,
@@ -2381,6 +2384,7 @@
043213AA2F5566EF0065C888 /* kb_input_profiles.json in Resources */, 043213AA2F5566EF0065C888 /* kb_input_profiles.json in Resources */,
04286A0B2ECD88B400CE730C /* KeyboardAssets.xcassets in Resources */, 04286A0B2ECD88B400CE730C /* KeyboardAssets.xcassets in Resources */,
043213B62F5582710065C888 /* spanish_words.json in Resources */, 043213B62F5582710065C888 /* spanish_words.json in Resources */,
B7F1A1E52F90000100000001 /* english_words.json in Resources */,
B7F1A1E12F90000100000001 /* portuguese_words.json in Resources */, B7F1A1E12F90000100000001 /* portuguese_words.json in Resources */,
B7F1A1E22F90000100000001 /* indonesian_words.json in Resources */, B7F1A1E22F90000100000001 /* indonesian_words.json in Resources */,
043213A62F5561FD0065C888 /* kb_keyboard_layouts_i18n.json in Resources */, 043213A62F5561FD0065C888 /* kb_keyboard_layouts_i18n.json in Resources */,