美文网首页iOS 的那些事儿
iOS App内语言切换(国际化)

iOS App内语言切换(国际化)

作者: MQ_Twist | 来源:发表于2020-08-21 14:02 被阅读0次

    精准与否,就是屠宰和手术的区别。 —— 卡蜜尔

    前言

    App国际化老生常谈,App内语言切换这个相关文章已经很多,可惜我没有,难受,想拥有。国际化的前期配置,文件创建这里不再赘述,请看之前的一篇文章 —— iOS语言国际化(本地化)

    切入正题

    iOS里面语言能够跟着系统语言显示,主要依赖系统的一个宏NSLocalizedString

    #define NSLocalizedString(key, comment) \
            [NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
    

    其中key就是国际化文字,comment可以为nil,有的话就是对key的描述。
    那么系统到底是怎么选择相关的文字进行显示的呢?从宏可以看到一些端倪,主要是localizedStringForKey:value:table:这个方法,且查找路径是在mainBundle里面。这时查看配置好的工程会发现会有对应的语言的.iproj文件夹,里面就是对应的国际化语言文件。

    .iproj文件夹
    系统就是根据当前语言找到对应的.iproj文件夹,然后找到相应的文件返回对应的文字。

    那么接下来就好弄了,要三步走。

    • 1、保存用户App内设置语言的状态。

    .h

    @interface MQLanguageConfig : NSObject
    
    /**
     用户自定义使用的语言,当传nil时,等同于resetSystemLanguage
     */
    @property (class, nonatomic, strong, nullable) NSString *userLanguage;
    /**
     重置系统语言
     */
    + (void)resetSystemLanguage;
    
    @end
    

    .m

    static NSString *const MQUserLanguageKey = @"MQUserLanguageKey";
    #define STANDARD_USER_DEFAULT  [NSUserDefaults standardUserDefaults]
    
    @implementation MQLanguageConfig
    
    + (void)setUserLanguage:(NSString *)userLanguage {
        //跟随手机系统
        if (userLanguage.length == 0) {
            [self resetSystemLanguage];
            return;
        }
        //用户自定义
        [STANDARD_USER_DEFAULT setValue:userLanguage forKey:MQUserLanguageKey];
        [STANDARD_USER_DEFAULT setValue:@[userLanguage] forKey:@"AppleLanguages"];
        [STANDARD_USER_DEFAULT synchronize];
    }
    
    + (NSString *)userLanguage {
        return [STANDARD_USER_DEFAULT valueForKey:MQUserLanguageKey];
    }
    
    //** 重置系统语言 */
    + (void)resetSystemLanguage {
        [STANDARD_USER_DEFAULT removeObjectForKey:MQUserLanguageKey];
        [STANDARD_USER_DEFAULT setValue:nil forKey:@"AppleLanguages"];
        [STANDARD_USER_DEFAULT synchronize];
    }
    
    @end
    
    
    • 2、创建分类,用runtime来操作localizedStringForKey:value:table:

    .h

    @interface NSBundle (Language)
    
    + (BOOL)isChineseLanguage;
    + (NSString *)currentLanguage;
    
    @end
    

    .m

    #import "MQLanguageConfig.h"
    #import <objc/runtime.h>
    
    @implementation NSBundle (Language)
    
    + (void)load {
        NSLog(@">>>currentLanguage:%@", [self currentLanguage]);
        Method ori = class_getInstanceMethod(self, @selector(localizedStringForKey:value:table:));
        Method cur = class_getInstanceMethod(self, @selector(mq_localizedStringForKey:value:table:));
        method_exchangeImplementations(ori, cur);
    }
    
    
    - (NSString *)mq_localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
        NSString *path = [[NSBundle mainBundle] pathForResource:[NSBundle currentLanguage] ofType:@"lproj"];
        if (path.length > 0) {
            NSBundle *bundle = [NSBundle bundleWithPath:path];
            return [bundle mq_localizedStringForKey:key value:value table:tableName];
        }
        return [self mq_localizedStringForKey:key value:value table:tableName];
    }
    
    + (BOOL)isChineseLanguage {
        NSString *currentLanguage = [self currentLanguage];
        return [currentLanguage hasPrefix:@"zh-Hans"];
    }
    
    + (NSString *)currentLanguage {
        return [MQLanguageConfig userLanguage] ? : [NSLocale preferredLanguages].firstObject;
    }
    
    @end
    
    • 3、刷新UI
      tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath中核心代码:
    //保存当前语言
    MQLanguageConfig.userLanguage = model.language;
    //创建新的UITabbarController
    MQTabbarController *tabbar = [MQTabbarController new];
    //找到对应的nav
    tabbar.selectedIndex = 2;
    UINavigationController *nav = tabbar.selectedViewController;
    NSMutableArray *navVCs = nav.viewControllers.mutableCopy;
    //添加指定vc到nav栈中
    SettingViewController *vc = [SettingViewController new];
    vc.hidesBottomBarWhenPushed = YES;
    [navVCs addObject:vc];
    //主线程刷新UI
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIApplication sharedApplication].delegate.window.rootViewController = tabbar;
        nav.viewControllers = navVCs;
        NSLog(@"当前语言 %@", [NSBundle currentLanguage]);
    });
    

    效果如下:

    App内国际化
    Demo传送门

    结语

    拥有了,舒服~

    相关文章

      网友评论

        本文标题:iOS App内语言切换(国际化)

        本文链接:https://www.haomeiwen.com/subject/faxujktx.html