上篇文章中提到我们目前的工程用pod进行了模块化管理,当项目被拆分之后,资源文件、语言文件当然也要被拆分。
因为一开始以为和图片资源一样,不用特殊处理,最终会合并为一个car文件。拆分的时候就直接在每个模块下面建立一个语言文件,命名为:Localizable.strings。拆好一个模块之后,run起来发现大量的翻译丢失了,仔细检查之后发现,工程中的string文件并没有像想象中的那样合并起来,而是只打包了一份string文件进来,那这个问题就尴尬了,因为之前都是用的
NSLocalizedString(@"login_fail",@"登录失败");
这样的方式来进行翻译的,没有指定string的文件名,如果要改数量就比较巨大了。是时候祭出 Method swizzing,解决这一难题了。
首先第一步:检查NSLocalizedString这个宏定义对应的方法
[NSBundle.mainBundle localizedStringForKey:(key) value:@"" table:nil]
在哪些地方使用,交换之后会不会影响第三方库的语言问题。检查后发现项目中所使用的第三方库都是用bundle打包了自己的资源文件,不会用这个方法进行加载语言文件。 Method swizzing 是可以放心的用了。
第二步,将刚刚拆出来的文件重新命名,重新编译之后,解压发现.app中确实有了两个string文件。这一步也成功了
第三步,进行方法交换。上代码:
#import "NSBundle+ZATool.h"
#import <objc/runtime.h>
@implementation NSBundle (ZATool)
+(void)load
{
//需要交换的系统方法,类方法和对象方法使用的方法不同
Method fromMethod = class_getInstanceMethod([self class], @selector(localizedStringForKey:value:table:));
//需要交换的自己写的方法
Method toMethod = class_getInstanceMethod([self class], @selector(ZALocalizedStringForKey:value:table:));
//方法交换
method_exchangeImplementations(fromMethod, toMethod);
}
#pragma mark - 多语言方法实现
-(NSString *)ZALocalizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
//语言文件数组
NSArray *array=@[@"CommonLocalizable",@"Localizable"];
if (!tableName || [array containsObject:tableName]) {
if (!tableName) {
tableName=@"CommonLocalizable";
}
//注意:方法交换是相互交换的,这里相当于是调的系统的翻译方法
NSString *string= [self ZALocalizedStringForKey:key value:value table:tableName];
if ([string isEqualToString:key]) {
//当取不到翻译字符串的时候,递归调用从下一个翻译文件中查找
NSInteger tag=[array indexOfObject:tableName];
if (tag!=array.count-1) {
tableName=array[tag+1];
//注意:方法交换是相互交换的,这里相当于是调的我们自己的翻译方法
string= [self localizedStringForKey:key value:value table:tableName];
}
}else{
}
return string;
}else
{
return [self ZALocalizedStringForKey:key value:value table:tableName];
}
}