思路
主要就是利用runtime hook系统的方法,宏定义为NSLocalizedString(key, comment),方法为[NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil],设置语言的时候传入正确的语言代码并找到相应的bundle,进而得到想要的字符串。当然已经显示的页面还要自己处理页面的刷新,比如更新rootViewController。
#import <Foundation/Foundation.h>
@interface NSBundle (Language)
+ (void)setLangage:(NSString *)language;//zh-Hans,en,zh-Hant...
@end
#import "NSBundle+Language.h"
#import <objc/runtime.h>
static NSString *languageKey = @"chosenLanguage";
@implementation NSBundle (Language)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(localizedStringForKey:value:table:);
SEL swizzledSelector = @selector(yx_localizedStringForKey:value:table:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (NSString *)yx_localizedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName {
NSString *chosenLanguage = [[NSUserDefaults standardUserDefaults] objectForKey:languageKey];
chosenLanguage = chosenLanguage ? chosenLanguage: @"Base";
NSBundle *chosenBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:chosenLanguage ofType:@"lproj"]];
chosenBundle = chosenBundle ? chosenBundle: NSBundle.mainBundle;
NSString *result = [chosenBundle yx_localizedStringForKey:key value:value table:tableName];
return result;
}
+ (void)setLangage:(NSString *)language {
[[NSUserDefaults standardUserDefaults] setObject:language forKey:languageKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
@end