This commit is contained in:
2026-03-04 13:44:56 +08:00
parent f30b1d7640
commit b1f1ddec7e
9 changed files with 331 additions and 60 deletions

View File

@@ -369,13 +369,7 @@ static NSString *KBFormatMB(uint64_t bytes) {
if (context.length == 0) {
return @"";
}
static NSCharacterSet *letters = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
letters = [NSCharacterSet
characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
});
NSCharacterSet *letters = [self kb_allowedSuggestionCharacterSet];
NSInteger idx = (NSInteger)context.length - 1;
while (idx >= 0) {
@@ -396,13 +390,7 @@ static NSString *KBFormatMB(uint64_t bytes) {
if (text.length == 0) {
return NO;
}
static NSCharacterSet *letters = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
letters = [NSCharacterSet
characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
});
NSCharacterSet *letters = [self kb_allowedSuggestionCharacterSet];
for (NSUInteger i = 0; i < text.length; i++) {
if (![letters characterIsMember:[text characterAtIndex:i]]) {
return NO;
@@ -411,6 +399,61 @@ static NSString *KBFormatMB(uint64_t bytes) {
return YES;
}
- (NSCharacterSet *)kb_allowedSuggestionCharacterSet {
switch (self.suggestionEngine.engineType) {
case KBSuggestionEngineTypeSpanish:
return [self kb_spanishSuggestionCharacterSet];
case KBSuggestionEngineTypeBopomofo:
return [self kb_bopomofoSuggestionCharacterSet];
case KBSuggestionEngineTypeLatin:
case KBSuggestionEngineTypePortuguese:
case KBSuggestionEngineTypeIndonesian:
case KBSuggestionEngineTypePinyinSimplified:
case KBSuggestionEngineTypePinyinTraditional:
default:
return [self kb_latinSuggestionCharacterSet];
}
}
- (NSCharacterSet *)kb_latinSuggestionCharacterSet {
static NSCharacterSet *set = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSCharacterSet characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
"áÁàÀâÂãÃäÄåÅæÆçÇ"
"éÉèÈêÊëË"
"íÍìÌîÎïÏ"
"ñÑ"
"óÓòÒôÔõÕöÖøØ"
"úÚùÙûÛüÜ"
"ýÝÿ"];
});
return set;
}
- (NSCharacterSet *)kb_spanishSuggestionCharacterSet {
static NSCharacterSet *set = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSCharacterSet characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
"áÁéÉíÍóÓúÚñÑüÜ"];
});
return set;
}
- (NSCharacterSet *)kb_bopomofoSuggestionCharacterSet {
static NSCharacterSet *set = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSCharacterSet characterSetWithCharactersInString:
@"ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄧㄨㄩㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ"
"˙ˊˇˋ"];
});
return set;
}
- (void)kb_updateSuggestionsForCurrentWord {
NSString *prefix = self.currentWord ?: @"";
if (prefix.length == 0) {

View File

@@ -58,13 +58,7 @@
if (context.length == 0) {
return @"";
}
static NSCharacterSet *letters = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
letters = [NSCharacterSet
characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
});
NSCharacterSet *letters = [self kb_allowedSuggestionCharacterSet];
NSInteger idx = (NSInteger)context.length - 1;
while (idx >= 0) {
@@ -85,13 +79,7 @@
if (text.length == 0) {
return NO;
}
static NSCharacterSet *letters = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
letters = [NSCharacterSet
characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];
});
NSCharacterSet *letters = [self kb_allowedSuggestionCharacterSet];
for (NSUInteger i = 0; i < text.length; i++) {
if (![letters characterIsMember:[text characterAtIndex:i]]) {
return NO;
@@ -100,6 +88,61 @@
return YES;
}
- (NSCharacterSet *)kb_allowedSuggestionCharacterSet {
switch (self.suggestionEngine.engineType) {
case KBSuggestionEngineTypeSpanish:
return [self kb_spanishSuggestionCharacterSet];
case KBSuggestionEngineTypeBopomofo:
return [self kb_bopomofoSuggestionCharacterSet];
case KBSuggestionEngineTypeLatin:
case KBSuggestionEngineTypePortuguese:
case KBSuggestionEngineTypeIndonesian:
case KBSuggestionEngineTypePinyinSimplified:
case KBSuggestionEngineTypePinyinTraditional:
default:
return [self kb_latinSuggestionCharacterSet];
}
}
- (NSCharacterSet *)kb_latinSuggestionCharacterSet {
static NSCharacterSet *set = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSCharacterSet characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
"áÁàÀâÂãÃäÄåÅæÆçÇ"
"éÉèÈêÊëË"
"íÍìÌîÎïÏ"
"ñÑ"
"óÓòÒôÔõÕöÖøØ"
"úÚùÙûÛüÜ"
"ýÝÿ"];
});
return set;
}
- (NSCharacterSet *)kb_spanishSuggestionCharacterSet {
static NSCharacterSet *set = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSCharacterSet characterSetWithCharactersInString:
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
"áÁéÉíÍóÓúÚñÑüÜ"];
});
return set;
}
- (NSCharacterSet *)kb_bopomofoSuggestionCharacterSet {
static NSCharacterSet *set = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
set = [NSCharacterSet characterSetWithCharactersInString:
@"ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄧㄨㄩㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦ"
"˙ˊˇˋ"];
});
return set;
}
- (void)kb_updateSuggestionsForCurrentWord {
NSString *prefix = self.currentWord ?: @"";
if (prefix.length == 0) {
@@ -175,4 +218,3 @@
}
@end

View File

@@ -8,8 +8,10 @@
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, KBSuggestionEngineType) {
KBSuggestionEngineTypeLatin = 0, // 拉丁字母(英语、葡萄牙语、印尼语
KBSuggestionEngineTypeLatin = 0, // 拉丁字母(英语)
KBSuggestionEngineTypeSpanish, // 西班牙语
KBSuggestionEngineTypePortuguese, // 葡萄牙语
KBSuggestionEngineTypeIndonesian, // 印度尼西亚语
KBSuggestionEngineTypePinyinSimplified, // 简体拼音
KBSuggestionEngineTypePinyinTraditional, // 繁体拼音
KBSuggestionEngineTypeBopomofo // 注音(繁体)

View File

@@ -15,6 +15,8 @@
@property (nonatomic, strong) NSDictionary<NSString *, NSArray<NSString *> *> *pinyinToTraditionalMap;
@property (nonatomic, strong) NSDictionary<NSString *, NSArray<NSString *> *> *bopomofoToChineseMap;
@property (nonatomic, copy) NSArray<NSString *> *spanishWords;
@property (nonatomic, copy) NSArray<NSString *> *portugueseWords;
@property (nonatomic, copy) NSArray<NSString *> *indonesianWords;
@end
@implementation KBSuggestionEngine
@@ -40,6 +42,8 @@
_pinyinToTraditionalMap = [self kb_loadPinyinToTraditionalMap];
_bopomofoToChineseMap = [self kb_loadBopomofoToChineseMap];
_spanishWords = [self kb_loadSpanishWords];
_portugueseWords = [self kb_loadPortugueseWords];
_indonesianWords = [self kb_loadIndonesianWords];
}
return self;
}
@@ -50,6 +54,10 @@
switch (self.engineType) {
case KBSuggestionEngineTypeSpanish:
return [self kb_spanishSuggestionsForPrefix:prefix limit:limit];
case KBSuggestionEngineTypePortuguese:
return [self kb_portugueseSuggestionsForPrefix:prefix limit:limit];
case KBSuggestionEngineTypeIndonesian:
return [self kb_indonesianSuggestionsForPrefix:prefix limit:limit];
case KBSuggestionEngineTypePinyinTraditional:
return [self kb_traditionalPinyinSuggestionsForPrefix:prefix limit:limit];
case KBSuggestionEngineTypePinyinSimplified:
@@ -163,6 +171,10 @@
self.engineType = KBSuggestionEngineTypeLatin;
} else if ([engineTypeString isEqualToString:@"spanish"]) {
self.engineType = KBSuggestionEngineTypeSpanish;
} else if ([engineTypeString isEqualToString:@"portuguese"]) {
self.engineType = KBSuggestionEngineTypePortuguese;
} else if ([engineTypeString isEqualToString:@"indonesian"]) {
self.engineType = KBSuggestionEngineTypeIndonesian;
} else if ([engineTypeString isEqualToString:@"pinyin_traditional"]) {
self.engineType = KBSuggestionEngineTypePinyinTraditional;
} else if ([engineTypeString isEqualToString:@"pinyin_simplified"]) {
@@ -539,35 +551,13 @@
#pragma mark - Spanish Suggestions
- (NSArray<NSString *> *)kb_spanishSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
NSString *lower = prefix.lowercaseString;
NSMutableArray<NSString *> *matches = [NSMutableArray array];
for (NSString *word in self.spanishWords) {
if ([word hasPrefix:lower]) {
[matches addObject:word];
if (matches.count >= limit * 2) {
break;
}
}
}
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.spanishWords
prefix:prefix
limit:limit];
if (matches.count == 0) {
return [self kb_latinSuggestionsForPrefix:prefix limit:limit];
}
[matches sortUsingComparator:^NSComparisonResult(NSString *a, NSString *b) {
NSInteger ca = self.selectionCounts[a].integerValue;
NSInteger cb = self.selectionCounts[b].integerValue;
if (ca != cb) {
return (cb > ca) ? NSOrderedAscending : NSOrderedDescending;
}
return [a compare:b];
}];
if (matches.count > limit) {
return [matches subarrayWithRange:NSMakeRange(0, limit)];
}
return matches.copy;
return matches;
}
- (NSArray<NSString *> *)kb_loadSpanishWords {
@@ -607,4 +597,136 @@
return result.count > 0 ? [result copy] : [self.class kb_defaultWords];
}
#pragma mark - Portuguese Suggestions
- (NSArray<NSString *> *)kb_portugueseSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.portugueseWords
prefix:prefix
limit:limit];
if (matches.count == 0) {
return [self kb_latinSuggestionsForPrefix:prefix limit:limit];
}
return matches;
}
- (NSArray<NSString *> *)kb_loadPortugueseWords {
NSString *path = [[NSBundle mainBundle] pathForResource:@"portuguese_words" ofType:@"json"];
if (!path) {
NSLog(@"[KBSuggestionEngine] portuguese_words.json not found, using default words");
return [self.class kb_defaultWords];
}
NSData *data = [NSData dataWithContentsOfFile:path];
if (!data) {
NSLog(@"[KBSuggestionEngine] Failed to read portuguese_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 portuguese_words.json: %@", error);
return [self.class kb_defaultWords];
}
NSArray *wordsArray = json[@"words"];
if (![wordsArray isKindOfClass:NSArray.class]) {
NSLog(@"[KBSuggestionEngine] Invalid words array in portuguese_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 Portuguese words", (unsigned long)result.count);
return result.count > 0 ? [result copy] : [self.class kb_defaultWords];
}
#pragma mark - Indonesian Suggestions
- (NSArray<NSString *> *)kb_indonesianSuggestionsForPrefix:(NSString *)prefix limit:(NSUInteger)limit {
NSArray<NSString *> *matches = [self kb_suggestionsFromWordList:self.indonesianWords
prefix:prefix
limit:limit];
if (matches.count == 0) {
return [self kb_latinSuggestionsForPrefix:prefix limit:limit];
}
return matches;
}
- (NSArray<NSString *> *)kb_loadIndonesianWords {
NSString *path = [[NSBundle mainBundle] pathForResource:@"indonesian_words" ofType:@"json"];
if (!path) {
NSLog(@"[KBSuggestionEngine] indonesian_words.json not found, using default words");
return [self.class kb_defaultWords];
}
NSData *data = [NSData dataWithContentsOfFile:path];
if (!data) {
NSLog(@"[KBSuggestionEngine] Failed to read indonesian_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 indonesian_words.json: %@", error);
return [self.class kb_defaultWords];
}
NSArray *wordsArray = json[@"words"];
if (![wordsArray isKindOfClass:NSArray.class]) {
NSLog(@"[KBSuggestionEngine] Invalid words array in indonesian_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 Indonesian words", (unsigned long)result.count);
return result.count > 0 ? [result copy] : [self.class kb_defaultWords];
}
#pragma mark - Word List Helpers
- (NSArray<NSString *> *)kb_suggestionsFromWordList:(NSArray<NSString *> *)words
prefix:(NSString *)prefix
limit:(NSUInteger)limit {
NSString *lower = prefix.lowercaseString;
NSMutableArray<NSString *> *matches = [NSMutableArray array];
for (NSString *word in words) {
if ([word hasPrefix:lower]) {
[matches addObject:word];
if (matches.count >= limit * 2) {
break;
}
}
}
if (matches.count == 0) { return @[]; }
[matches sortUsingComparator:^NSComparisonResult(NSString *a, NSString *b) {
NSInteger ca = self.selectionCounts[a].integerValue;
NSInteger cb = self.selectionCounts[b].integerValue;
if (ca != cb) {
return (cb > ca) ? NSOrderedAscending : NSOrderedDescending;
}
return [a compare:b];
}];
if (matches.count > limit) {
return [matches subarrayWithRange:NSMakeRange(0, limit)];
}
return matches.copy;
}
@end

View File

@@ -0,0 +1,22 @@
{
"__comment": "印度尼西亚语常用词库",
"words": [
"halo", "terima", "kasih", "tolong", "ya", "tidak", "mungkin", "baik",
"bagus", "selamat", "pagi", "siang", "sore", "malam", "hari", "ini",
"itu", "saya", "kamu", "dia", "kita", "kami", "mereka", "anda",
"aku", "mu", "nya", "rumah", "kerja", "uang", "waktu", "tahun",
"bulan", "minggu", "jam", "menit", "detik", "hidup", "cinta", "teman",
"keluarga", "ayah", "ibu", "anak", "air", "makan", "minum", "kopi",
"teh", "nasi", "ikan", "daging", "buah", "sayur", "kota", "negara",
"indonesia", "sekolah", "universitas", "mobil", "bus", "kereta", "jalan",
"pantai", "matahari", "bulan", "hujan", "angin", "api", "tanah",
"langit", "laut", "gunung", "sungai", "besar", "kecil", "baru", "lama",
"muda", "cepat", "lambat", "kuat", "lemah", "mudah", "sulit", "panas",
"dingin", "dekat", "jauh", "kanan", "kiri", "di", "ke", "dari", "untuk",
"dengan", "tanpa", "antara", "karena", "jadi", "juga", "sini", "situ",
"sekarang", "kemarin", "besok", "selalu", "tidak", "pernah", "sudah",
"belum", "mau", "bisa", "harus", "perlu", "ingin", "tahu", "lihat",
"dengar", "bicara", "datang", "pergi", "buat", "beli", "jual", "bayar",
"tinggal", "lari", "kerja", "belajar", "membaca", "menulis"
]
}

View File

@@ -0,0 +1,32 @@
{
"__comment": "葡萄牙语常用词库",
"words": [
"olá", "ola", "obrigado", "obrigada", "favor", "por", "sim", "não",
"nao", "talvez", "tudo", "bem", "bom", "boa", "dia", "noite",
"tarde", "amanhã", "amanha", "hoje", "ontem", "agora", "depois",
"antes", "sempre", "nunca", "já", "ja", "ainda", "aqui", "ali",
"lá", "la", "onde", "quando", "porquê", "porque", "como", "quanto",
"quem", "qual", "quais", "eu", "tu", "ele", "ela", "nós", "nos",
"vós", "vos", "vocês", "voces", "você", "voce", "me", "te", "se",
"meu", "minha", "seu", "sua", "nosso", "nossa", "casa", "trabalho",
"dinheiro", "tempo", "ano", "mês", "mes", "semana", "hora",
"minuto", "segundo", "vida", "amor", "amigo", "amiga", "pai", "mãe",
"mae", "filho", "filha", "irmão", "irmao", "irmã", "irma", "família",
"familia", "água", "agua", "comida", "café", "cafe", "chá", "cha",
"leite", "pão", "pao", "carne", "peixe", "fruta", "verdura", "arroz",
"feijão", "feijao", "cidade", "país", "pais", "brasil", "portugal",
"escola", "universidade", "carro", "ônibus", "onibus", "metrô",
"metro", "rua", "avenida", "praia", "sol", "lua", "chuva", "vento",
"fogo", "terra", "céu", "ceu", "mar", "montanha", "rio", "bonito",
"feio", "grande", "pequeno", "novo", "velho", "jovem", "rápido",
"rapido", "lento", "forte", "fraco", "fácil", "facil", "difícil",
"dificil", "quente", "frio", "perto", "longe", "direita", "esquerda",
"em", "de", "para", "com", "sem", "sobre", "entre", "então", "entao",
"também", "tambem", "isso", "aquilo", "essa", "esse", "esta", "este",
"estou", "está", "esta", "são", "sao", "ser", "estar", "ter", "fazer",
"ir", "vir", "ver", "poder", "querer", "saber", "dizer", "gostar",
"precisar", "usar", "comprar", "vender", "pagar", "chamar", "chegar",
"sair", "entrar", "voltar", "andar", "correr", "morar", "viver",
"morrer", "nascer"
]
}

View File

@@ -125,7 +125,7 @@
@"code": @"pt",
@"name": @"Português",
@"defaultSkinZip": @"葡萄牙初始皮肤.zip",
@"layouts": @[@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"pt_PT_qwerty", @"layoutJsonId": @"letters_pt", @"suggestionEngine": @"latin"}]
@"layouts": @[@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"pt_PT_qwerty", @"layoutJsonId": @"letters_pt", @"suggestionEngine": @"portuguese"}]
},
@{
@"code": @"zh-Hant-Pinyin",
@@ -143,7 +143,7 @@
@"code": @"id",
@"name": @"Bahasa Indonesia",
@"defaultSkinZip": @"印度尼西亚初始皮肤.zip",
@"layouts": @[@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"id_ID_qwerty", @"layoutJsonId": @"letters_id", @"suggestionEngine": @"latin"}]
@"layouts": @[@{@"variant": @"qwerty", @"title": @"QWERTY", @"profileId": @"id_ID_qwerty", @"layoutJsonId": @"letters_id", @"suggestionEngine": @"indonesian"}]
}
];
return [self parseProfilesFromJSONArray:fallback];

View File

@@ -39,7 +39,7 @@
"title": "QWERTY",
"profileId": "pt_PT_qwerty",
"layoutJsonId": "letters_pt",
"suggestionEngine": "latin"
"suggestionEngine": "portuguese"
}
]
},
@@ -81,7 +81,7 @@
"title": "QWERTY",
"profileId": "id_ID_qwerty",
"layoutJsonId": "letters_id",
"suggestionEngine": "latin"
"suggestionEngine": "indonesian"
}
]
}

View File

@@ -45,6 +45,8 @@
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 */; };
043213B62F5582710065C888 /* spanish_words.json in Resources */ = {isa = PBXBuildFile; fileRef = 043213B52F5582710065C888 /* spanish_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 */; };
043213BD2F56A3920065C888 /* 西班牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BC2F56A3920065C888 /* 西班牙初始皮肤.zip */; };
043213BE2F56A3920065C888 /* 葡萄牙初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.zip */; };
043213C02F56C9330065C888 /* 印度尼西亚初始皮肤.zip in Resources */ = {isa = PBXBuildFile; fileRef = 043213BF2F56C9330065C888 /* 印度尼西亚初始皮肤.zip */; };
@@ -415,6 +417,8 @@
043213AD2F556DF80065C888 /* KBSkinIconMap_pt.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = KBSkinIconMap_pt.strings; sourceTree = "<group>"; };
043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = KBSkinIconMap_zh_hant.strings; 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>"; };
B7F1A1E42F90000100000001 /* indonesian_words.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = indonesian_words.json; sourceTree = "<group>"; };
043213BB2F56A3920065C888 /* 葡萄牙初始皮肤.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>"; };
@@ -978,6 +982,8 @@
043213AD2F556DF80065C888 /* KBSkinIconMap_pt.strings */,
043213AE2F556DF80065C888 /* KBSkinIconMap_zh_hant.strings */,
043213B52F5582710065C888 /* spanish_words.json */,
B7F1A1E32F90000100000001 /* portuguese_words.json */,
B7F1A1E42F90000100000001 /* indonesian_words.json */,
043213A22F5528140065C888 /* pinyin_to_traditional.json */,
043213A12F5528140065C888 /* bopomofo_to_chinese.json */,
);
@@ -2375,6 +2381,8 @@
043213AA2F5566EF0065C888 /* kb_input_profiles.json in Resources */,
04286A0B2ECD88B400CE730C /* KeyboardAssets.xcassets in Resources */,
043213B62F5582710065C888 /* spanish_words.json in Resources */,
B7F1A1E12F90000100000001 /* portuguese_words.json in Resources */,
B7F1A1E22F90000100000001 /* indonesian_words.json in Resources */,
043213A62F5561FD0065C888 /* kb_keyboard_layouts_i18n.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;