iOS 多語言快捷設置Xib設置 前言

前言

  • 關於多語言國際化的介紹,現在越來越多的App走向國際,因此多語言/國際化就變得比較常見,我呢比較喜歡偷懶,也比較喜歡整理,因此我封裝了一套下面的工具來方便大家一起使用。

. Demo地址

關於怎麼去配置國際化的信息,我就不做多餘的贅述,這些文章就挺詳細 iOS 國際化開發3分鐘實現iOS語言本地化/國際化

簡單說明工具類

1、KJLoadLanguageViewController:簡單的切換加載控制器
2、NSBundle+KJLanguage:工具的核心,當前語言獲取和設置
3、UIButton+KJLanguage:按鈕多語言
4、UILabel+KJLanguage:文本多語言
5、UITextField+KJLanguage:TextField多語言

分別介紹每個類對應的 API & Property

一、KJLoadLanguageViewController

@interface KJLoadLanguageViewController : UIViewController
@property(nonatomic,strong)UIActivityIndicatorView *indicatorView;
@property(nonatomic,assign)CGFloat time;
@property(nonatomic,readwrite,copy)void(^loadEnd)(void);
@end

indicatorView:系統自帶加載控件
time:加載時間
loadEnd:加載結束的回調處理

二、NSBundle+KJLanguage

這個是本工具的核心,那麼我就多介紹一下,先看看 API & Property

/// 自定義strings文件,默認Localizable.strings
@property(nonatomic,strong,class)NSString *customStringsName;
/// 當前語言
@property(nonatomic,strong,readonly,class)NSString *currentLanguage;
/// 設置語言,傳nil恢復系統默認語言
+ (void)kj_setCurrentLanguage:(NSString*_Nullable)language complete:(void(^_Nullable)(void))complete;
/// 切換動畫,備註Xib設置的多語言會自動切換
+ (void)kj_switchoverLanguage:(UIViewController*(^_Nullable)(KJLoadLanguageViewController *loadvc))block complete:(void(^_Nullable)(void))complete;

customStringsName:自定義strings文件,默認Localizable.strings,這個主要是後面控件使用,如果你的strings文件名字不是Localizable而是自定義的話,那麼你就得使用NSLocalizedStringFromTable來讀取本地化字符串

if (NSBundle.customStringsName) {
    self.text = NSLocalizedStringFromTable(LocalizedKey,NSBundle.customStringsName,nil);
}else{
    self.text = NSLocalizedString(LocalizedKey, nil);
}

currentLanguage:獲取App當前語言,這個其實是存儲在NSUserDefaults當中,多說一句這個語言並不是App系統語言,而是用戶設置語言,當然第一次未設置的時候則取App系統語言

static NSString *kAppLanguageKey = @"KJ_CURRENT_LANGUAGE_KEY";
+ (NSString*)currentLanguage{
    NSString *language = [[NSUserDefaults standardUserDefaults] objectForKey:kAppLanguageKey];
    if (language == nil) {
        language = [[NSLocale preferredLanguages] firstObject];
    }
    return language;
}

kj_setCurrentLanguage:complete::設置語言,傳nil恢復系統默認語言,中文zh-Hans、英文en,其他的按這種格式就行

+ (void)kj_setCurrentLanguage:(NSString*)language complete:(void(^)(void))complete{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    if (language) {
        [userDefaults setObject:language forKey:kAppLanguageKey];
    }else{
        [userDefaults removeObjectForKey:kAppLanguageKey];
    }
    [userDefaults synchronize];
    if (complete) complete();
}

kj_switchoverLanguage:complete::我封裝的一款簡單的切換動畫,當然你覺得不好看什麼的,你可以自己選擇,KJLoadLanguageViewController控制器可以用來承載你想要的切換動畫效果

/// 切換動畫,自帶菊花加載界面
+ (void)kj_switchoverLanguage:(UIViewController*(^)(KJLoadLanguageViewController *loadvc))block complete:(void(^)(void))complete{
    if (block) {
        KJLoadLanguageViewController *__vc = [KJLoadLanguageViewController new];
        __vc.time = .5;
        __block UIViewController *vc = block(__vc);
        if (vc) {
            __vc.loadEnd = ^{
                [vc.view.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                    if ([obj isKindOfClass:[UIButton class]]) {
                        UIButton *button = (UIButton*)obj;
                        button.LocalizedKey = button.LocalizedKey;
                        button.SelectedKey = button.SelectedKey;
                        button.DisabledKey = button.DisabledKey;
                        button.HighlightedKey = button.HighlightedKey;
                    }else if ([obj isKindOfClass:[UILabel class]]) {
                        UILabel *label = (UILabel*)obj;
                        label.LocalizedKey = label.LocalizedKey;
                    }else if ([obj isKindOfClass:[UITextField class]]) {
                        UITextField *textField = (UITextField*)obj;
                        textField.LocalizedKey = textField.LocalizedKey;
                    }
                }];
                if (complete) complete();
            };
            [vc presentViewController:__vc animated:NO completion:nil];
        }
    }
}

簡單使用如下,

[NSBundle kj_switchoverLanguage:^UIViewController * _Nonnull(KJLoadLanguageViewController * _Nonnull loadvc) {
    loadvc.view.backgroundColor = [UIColor.greenColor colorWithAlphaComponent:0.3];
    return weakself;
} complete:^{
    [changebutton setTitle:NSLocalizedString(@"changeLanguage", nil) forState:UIControlStateNormal];
}];

內部處理

介紹完API,我再來說說實現吧,
國際化其實就是走該方法localizedStringForKey:value:table:

/// 國際化
- (NSString*)localizedStringForKey:(NSString*)key value:(NSString*)value table:(NSString*)tableName{
    NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:NSBundle.currentLanguage ofType:@"lproj"]];
    if (bundle) {
        return [bundle localizedStringForKey:key value:value table:tableName];
    }else{
        return [super localizedStringForKey:key value:value table:tableName];
    }
}

load方法中採用動態繼創建子類KJLanguageBundle調用國際化方法localizedStringForKey:value:table:

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 動態繼承修改[NSBundle mainBundle]對象的isa指針使其指向子類,便可以調用子類的方法
// 在運行時創建新的子類,並添加新的方法
        object_setClass([NSBundle mainBundle], [KJLanguageBundle class]);
    });
}

自定義strings文件,我採用類屬性來設置,runtime關聯實現

+ (NSString*)customStringsName{
    return objc_getAssociatedObject(self, @selector(customStringsName));
}
+ (void)setCustomStringsName:(NSString*)customStringsName{
    objc_setAssociatedObject(self, @selector(customStringsName), customStringsName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

三、UIButton+KJLanguage

暫時我提供4種Api,IBInspectable用來支持Xib快捷設置(偷懶偷的更徹底- -!)
LocalizedKey:Normal狀態下的文字
SelectedKey:選中狀態下的文字
DisabledKey:不可操作狀態下的文字
HighlightedKey:高亮狀態下的文字

- (NSString*)LocalizedKey{
    return objc_getAssociatedObject(self, @selector(LocalizedKey));;
}
- (void)setLocalizedKey:(NSString*)LocalizedKey{
    objc_setAssociatedObject(self, @selector(LocalizedKey), LocalizedKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (LocalizedKey == nil) return;
    if (NSBundle.customStringsName) {
        [self setTitle:NSLocalizedStringFromTable(LocalizedKey,NSBundle.customStringsName,nil) forState:UIControlStateNormal];
    }else{
        [self setTitle:NSLocalizedString(LocalizedKey, nil) forState:UIControlStateNormal];
    }
}
- (NSString*)HighlightedKey{
    return objc_getAssociatedObject(self, @selector(HighlightedKey));;
}
- (void)setHighlightedKey:(NSString*)HighlightedKey{
    objc_setAssociatedObject(self, @selector(HighlightedKey), HighlightedKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (HighlightedKey == nil) return;
    if (NSBundle.customStringsName) {
        [self setTitle:NSLocalizedStringFromTable(HighlightedKey,NSBundle.customStringsName,nil) forState:UIControlStateHighlighted];
    }else{
        [self setTitle:NSLocalizedString(HighlightedKey, nil) forState:UIControlStateHighlighted];
    }
}
- (NSString*)SelectedKey{
    return objc_getAssociatedObject(self, @selector(SelectedKey));;
}
- (void)setSelectedKey:(NSString*)SelectedKey{
    objc_setAssociatedObject(self, @selector(SelectedKey), SelectedKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (SelectedKey == nil) return;
    if (NSBundle.customStringsName) {
        [self setTitle:NSLocalizedStringFromTable(SelectedKey,NSBundle.customStringsName,nil) forState:UIControlStateSelected];
    }else{
        [self setTitle:NSLocalizedString(SelectedKey, nil) forState:UIControlStateSelected];
    }
}
- (NSString*)DisabledKey{
    return objc_getAssociatedObject(self, @selector(DisabledKey));;
}
- (void)setDisabledKey:(NSString*)DisabledKey{
    objc_setAssociatedObject(self, @selector(DisabledKey), DisabledKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (DisabledKey == nil) return;
    if (NSBundle.customStringsName) {
        [self setTitle:NSLocalizedStringFromTable(DisabledKey,NSBundle.customStringsName,nil) forState:UIControlStateDisabled];
    }else{
        [self setTitle:NSLocalizedString(DisabledKey, nil) forState:UIControlStateDisabled];
    }
}

支持Xib快捷設置,右邊爲對應的Key


Demo對應的Key

"textLabel" = "當前語言爲中文";
"textFieldPlaceholder" = "測試textField";
"textButtonDefault" = "按鈕正常狀態";
"textButtonSelect" = "按鈕選中狀態";
"textButtonHighliaght" = "按鈕高亮狀態";
"textButtonDisable" = "按鈕不可操作狀態";
"changeLanguage" = "切換語言";

四、UILabel+KJLanguage 和 UITextField+KJLanguage

這兩其實差不多,UITextField設置placeholder屬性,UILabel設置text屬性

- (NSString*)LocalizedKey{
    return objc_getAssociatedObject(self, @selector(LocalizedKey));;
}
- (void)setLocalizedKey:(NSString*)LocalizedKey{
    objc_setAssociatedObject(self, @selector(LocalizedKey), LocalizedKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    if (LocalizedKey == nil) return;
    if (NSBundle.customStringsName) {
        self.placeholder = NSLocalizedStringFromTable(LocalizedKey,NSBundle.customStringsName,nil);
    }else{
        self.placeholder = NSLocalizedString(LocalizedKey, nil);
    }
}

使用示例

到此基本就介紹的差不多了,大致使用如下

#import "KJLanguageVC.h"
#import "NSBundle+KJLanguage.h"
@interface KJLanguageVC ()
@property (weak, nonatomic) IBOutlet UIButton *button;

@end

@implementation KJLanguageVC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    _weakself;
    [self.button kj_addAction:^(UIButton * _Nonnull kButton) {
        kButton.selected = !kButton.selected;
    }];
    
    __block UIButton *changebutton = [[UIButton alloc] initWithFrame:CGRectMake(0, kScreenH - 60, kScreenW-150, 40)];
    [self.view addSubview:changebutton];
    changebutton.centerX = kScreenW/2;
    changebutton.backgroundColor = UIColor.whiteColor;
    changebutton.layer.borderWidth = 1;
    changebutton.layer.borderColor = UIColor.blueColor.CGColor;
    changebutton.layer.masksToBounds = YES;
    changebutton.layer.cornerRadius = 5;
    changebutton.titleLabel.font = [UIFont systemFontOfSize:14];
    [changebutton setTitle:NSLocalizedString(@"changeLanguage", nil) forState:UIControlStateNormal];
    [changebutton setTitleColor:UIColor.blueColor forState:UIControlStateNormal];
    [changebutton kj_addAction:^(UIButton * _Nonnull kButton) {
        NSString *language = NSBundle.currentLanguage;
        if ([language isEqualToString:@"en"]) {
            language = @"zh-Hans";
        }else{
            language = @"en";
        }
        [NSBundle kj_setCurrentLanguage:language complete:nil];
        [NSBundle kj_switchoverLanguage:^UIViewController * _Nonnull(KJLoadLanguageViewController * _Nonnull loadvc) {
            loadvc.view.backgroundColor = [UIColor.greenColor colorWithAlphaComponent:0.3];
            return weakself;
        } complete:^{
            [changebutton setTitle:NSLocalizedString(@"changeLanguage", nil) forState:UIControlStateNormal];
        }];
    }];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

End

到此就差不多了,粗略封裝,望大神補充
該工具我也提交到Pod上,使用 pod 'KJExtensionHandler/Language' # 多語言模塊

備註:本文用到的部分函數方法和Demo,均來自三方庫KJExtensionHandler,如有需要的朋友可自行pod 'KJExtensionHandler'引入即可

多語言介紹就到此完畢,後面有相關再補充,寫文章不容易,還請點個小星星傳送門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章