语言逻辑处理
我的项目里有5个国家的语言,如果用户在app里手动切换了国家语言,只要不卸载app,用户在手机设置切换语言,app的语言不要变;如果app被删 除,重新安装,app语言要跟随手机设置的语言(如果语言对不上,app就显示英语) 用户没有在app里手动设置过国家语言,用户在手机设置界面切换国家,app要跟随手机设置的语言(如果语言对不上,app就显示英语)。
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#import "KBKeyBoardMainView.h"
|
||||
#import "KBKeyboardSubscriptionView.h"
|
||||
#import "KBLocalizationManager.h"
|
||||
#import "KBSettingView.h"
|
||||
#import "KBSkinManager.h"
|
||||
#import "KBSkinInstallBridge.h"
|
||||
#import "KBSuggestionEngine.h"
|
||||
@@ -96,6 +97,19 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
||||
}
|
||||
[self kb_applyTheme];
|
||||
}];
|
||||
|
||||
// 语言变化时,重建键盘 UI(保证“App 语言=键盘语言”,并支持 App 内切换语言后键盘即时刷新)
|
||||
self.kb_localizationObserverToken = [[NSNotificationCenter defaultCenter]
|
||||
addObserverForName:KBLocalizationDidChangeNotification
|
||||
object:nil
|
||||
queue:[NSOperationQueue mainQueue]
|
||||
usingBlock:^(__unused NSNotification *_Nonnull note) {
|
||||
__strong typeof(weakSelf) self = weakSelf;
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
[self kb_reloadUIForLocalizationChange];
|
||||
}];
|
||||
[self kb_applyTheme];
|
||||
[self kb_registerDarwinSkinInstallObserver];
|
||||
[self kb_consumePendingShopSkin];
|
||||
@@ -239,6 +253,11 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
||||
removeObserver:self.kb_skinObserverToken];
|
||||
self.kb_skinObserverToken = nil;
|
||||
}
|
||||
if (self.kb_localizationObserverToken) {
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:self.kb_localizationObserverToken];
|
||||
self.kb_localizationObserverToken = nil;
|
||||
}
|
||||
[self kb_stopObservingAppGroupChanges];
|
||||
[self kb_unregisterDarwinSkinInstallObserver];
|
||||
#if DEBUG
|
||||
@@ -250,6 +269,57 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Localization
|
||||
|
||||
- (void)kb_reloadUIForLocalizationChange {
|
||||
if (![NSThread isMainThread]) {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[weakSelf kb_reloadUIForLocalizationChange];
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 记录当前面板状态,重建后尽量恢复。
|
||||
KBKeyboardPanelMode targetMode = self.kb_panelMode;
|
||||
// 强制下次布局刷新:即使 profileId 未变,也需要让新建的主视图应用一次当前 profile。
|
||||
_kb_lastLoadedProfileId = nil;
|
||||
|
||||
// 主键盘/面板里有大量静态文案(init 时设置),语言变化后需要重建才能刷新。
|
||||
if (_keyBoardMainView) {
|
||||
[_keyBoardMainView removeFromSuperview];
|
||||
_keyBoardMainView = nil;
|
||||
}
|
||||
self.keyBoardMainHeightConstraint = nil;
|
||||
|
||||
if (_functionView) {
|
||||
[_functionView removeFromSuperview];
|
||||
_functionView = nil;
|
||||
}
|
||||
if (_settingView) {
|
||||
[_settingView removeFromSuperview];
|
||||
_settingView = nil;
|
||||
}
|
||||
if (_subscriptionView) {
|
||||
[_subscriptionView removeFromSuperview];
|
||||
_subscriptionView = nil;
|
||||
}
|
||||
if (_chatPanelView) {
|
||||
[_chatPanelView removeFromSuperview];
|
||||
_chatPanelView = nil;
|
||||
}
|
||||
self.chatPanelVisible = NO;
|
||||
self.chatPanelHeightConstraint = nil;
|
||||
|
||||
// 强制触发面板刷新:先回到 Main,再切回目标面板(避免 kb_setPanelMode 直接 return)。
|
||||
self.kb_panelMode = KBKeyboardPanelModeMain;
|
||||
[self kb_setPanelMode:targetMode animated:NO];
|
||||
// 语言变化后,键盘布局/profile 也可能需要同步更新(未手动选择键盘配置时会随 App 语言变化)
|
||||
[self kb_checkAndApplyLayoutIfNeeded];
|
||||
[KBHUD setContainerView:self.view];
|
||||
[self kb_applyTheme];
|
||||
}
|
||||
|
||||
#pragma mark - Layout Switching
|
||||
|
||||
- (void)kb_checkAndApplyLayoutIfNeeded {
|
||||
|
||||
@@ -68,6 +68,7 @@ typedef NS_ENUM(NSInteger, KBKeyboardPanelMode) {
|
||||
NSString *_chatPanelBaselineText;
|
||||
id _kb_fullAccessObserverToken;
|
||||
id _kb_skinObserverToken;
|
||||
id _kb_localizationObserverToken;
|
||||
KBKeyboardPanelMode _kb_panelMode;
|
||||
}
|
||||
|
||||
@@ -104,6 +105,7 @@ typedef NS_ENUM(NSInteger, KBKeyboardPanelMode) {
|
||||
@property(nonatomic, copy) NSString *chatPanelBaselineText; // 打开聊天面板时宿主输入框已有的文本
|
||||
@property(nonatomic, strong, nullable) id kb_fullAccessObserverToken;
|
||||
@property(nonatomic, strong, nullable) id kb_skinObserverToken;
|
||||
@property(nonatomic, strong, nullable) id kb_localizationObserverToken;
|
||||
@property(nonatomic, assign) KBKeyboardPanelMode kb_panelMode;
|
||||
@property(nonatomic, strong, nullable) id kb_appGroupObserverToken;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#import "KBKeyboardLayoutResolver.h"
|
||||
#import "KBInputProfileManager.h"
|
||||
#import "KBConfig.h"
|
||||
#import "KBLocalizationManager.h"
|
||||
|
||||
@implementation KBKeyboardLayoutResolver
|
||||
|
||||
@@ -18,6 +19,30 @@
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// 未手动选择键盘输入配置时,根据当前 App 语言推导默认键盘语言码(对应 kb_input_profiles.json 的 code)。
|
||||
- (NSString *)kb_defaultKeyboardLanguageCodeForAppLanguageCode:(NSString *)appLanguageCode {
|
||||
NSString *lc = (appLanguageCode ?: @"").lowercaseString;
|
||||
if ([lc hasPrefix:@"es"]) { return @"es"; }
|
||||
if ([lc hasPrefix:@"pt"]) { return @"pt"; }
|
||||
if ([lc hasPrefix:@"id"]) { return @"id"; }
|
||||
if ([lc hasPrefix:@"zh-hant"]) { return @"zh-Hant-Pinyin"; }
|
||||
return @"en";
|
||||
}
|
||||
|
||||
- (BOOL)kb_didUserSelectKeyboardProfileInAppGroup:(NSUserDefaults *)appGroup {
|
||||
return [appGroup boolForKey:AppGroup_DidUserSelectKeyboardProfile];
|
||||
}
|
||||
|
||||
- (nullable KBInputProfileLayout *)kb_defaultLayoutForCurrentAppLanguage {
|
||||
NSString *appLang = [KBLocalizationManager shared].currentLanguageCode ?: KBLanguageCodeEnglish;
|
||||
NSString *kbLang = [self kb_defaultKeyboardLanguageCodeForAppLanguageCode:appLang];
|
||||
KBInputProfile *profile = [[KBInputProfileManager sharedManager] profileForLanguageCode:kbLang];
|
||||
if (!profile) {
|
||||
profile = [[KBInputProfileManager sharedManager] profileForLanguageCode:@"en"];
|
||||
}
|
||||
return profile.layouts.firstObject;
|
||||
}
|
||||
|
||||
- (NSString *)layoutJsonIdForProfileId:(NSString *)profileId {
|
||||
if (profileId.length == 0) {
|
||||
return @"letters";
|
||||
@@ -51,19 +76,31 @@
|
||||
- (nullable NSString *)currentProfileId {
|
||||
NSUserDefaults *appGroup = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
NSString *profileId = [appGroup stringForKey:AppGroup_SelectedKeyboardProfileId];
|
||||
return profileId;
|
||||
if ([self kb_didUserSelectKeyboardProfileInAppGroup:appGroup]) {
|
||||
return profileId;
|
||||
}
|
||||
KBInputProfileLayout *layout = [self kb_defaultLayoutForCurrentAppLanguage];
|
||||
return layout.profileId.length > 0 ? layout.profileId : profileId;
|
||||
}
|
||||
|
||||
- (nullable NSString *)currentLanguageCode {
|
||||
NSUserDefaults *appGroup = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
NSString *languageCode = [appGroup stringForKey:AppGroup_SelectedKeyboardLanguageCode];
|
||||
return languageCode;
|
||||
if ([self kb_didUserSelectKeyboardProfileInAppGroup:appGroup]) {
|
||||
return languageCode;
|
||||
}
|
||||
NSString *appLang = [KBLocalizationManager shared].currentLanguageCode ?: KBLanguageCodeEnglish;
|
||||
return [self kb_defaultKeyboardLanguageCodeForAppLanguageCode:appLang];
|
||||
}
|
||||
|
||||
- (nullable NSString *)currentLayoutVariant {
|
||||
NSUserDefaults *appGroup = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||
NSString *layoutVariant = [appGroup stringForKey:AppGroup_SelectedKeyboardLayoutVariant];
|
||||
return layoutVariant;
|
||||
if ([self kb_didUserSelectKeyboardProfileInAppGroup:appGroup]) {
|
||||
return layoutVariant;
|
||||
}
|
||||
KBInputProfileLayout *layout = [self kb_defaultLayoutForCurrentAppLanguage];
|
||||
return layout.variant.length > 0 ? layout.variant : layoutVariant;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -843,7 +843,7 @@
|
||||
"align": "left",
|
||||
"insetLeft": 4,
|
||||
"insetRight": 4,
|
||||
"gap": 5,
|
||||
"gap": 6,
|
||||
"items": [
|
||||
"letter:ㄅ", "letter:ㄉ", "letter:ˇ", "letter:ˋ", "letter:ㄓ",
|
||||
"letter:ˊ", "letter:˙", "letter:ㄚ", "letter:ㄞ", "letter:ㄢ", "letter:ㄦ"
|
||||
|
||||
Reference in New Issue
Block a user