iOS 多语言快捷设置Xib设置

前言

  • 关于多语言国际化的介绍,现在越来越多的App走向国际,因此多语言/国际化就变得比较常见,我呢比较喜欢偷懒,也比较喜欢整理,因此我封装了一套下面的工具来方便大家一起使用。

. Demo地址

xxx
WX20210104-155026@2x.png

关于怎么去配置国际化的信息,我就不做多余的赘述,这些文章就挺详细 iOS 国际化开发3分钟实现iOS语言本地化/国际化[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


Xib设置

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 'KJEmitterView/Language' # 多语言模块

备注:本文用到的部分函数方法和Demo,均来自三方库KJEmitterView,如有需要的朋友可自行pod 'KJEmitterView'引入即可

多语言介绍就到此完毕,后面有相关再补充,写文章不容易,还请点个小星星传送门

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容