iOS实践——语言切换

ps:有一种需求,叫做app内语言切换,我的这个版本,代码更具体一些,请勿喷
ps:哎,有一种需求,叫做网络下载语言包进行多语言切换,目的是再添加语言支持,不用另发版本,此功能下回分析~~

语言切换.PNG

0.文件结构介绍

InternationalControl           ——控制切换语言工具类(关键)
ALCommentMethod                ——便捷设置文字工具类
DLLanguageObject               ——语言附加信息实体类,充当数据载体功能
ALChooseLanguageVC             ——选择语言具体控制器,业务具体相关,仅做参考,请自行实现

1.相关宏

1)便捷切换文字

#define DLLocal(localName) [ALCommentMethod localizationString:localName]

2)相关通知

//1.添加通知
#define  ADDChangeLanguageNotification            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeLanguage) name:AL_NOTIFICATION_CHANGE_LANGUAGE object:nil]

//2.发送通知
#define  POSTChangeLanguageInfoNotification       [[NSNotificationCenter defaultCenter] postNotificationMainThreadName:AL_NOTIFICATION_CHANGE_LANGUAGE object:nil]

//3.移除通知
#define  REMOVEUpdateUserInfoNotification [[NSNotificationCenter defaultCenter] removeObserver:self]

2.接受通知后进行刷新文字(此处处理方式,总觉着不够技术含量,若有更好的方式,请告知)

#pragma mark - 初始化
- (void)initToolView{
    //...
    self.bottomToolView = bottomToolView;
    ADDChangeLanguageNotification;//添加通知
}

- (void)changeLanguage{
    //重新刷新一下界面文字
    self.appName.text = DLLocal(@"bottom_tool_choose_app");
    [self setNeedsLayout];
}

- (void)dealloc{
    REMOVEUpdateUserInfoNotification;//移除通知
}

3.代码

1) InternationalControl 控制切换语言工具类(关键)

#import <Foundation/Foundation.h>

@class DLLanguageObject;

@interface InternationalControl : NSObject
+(NSBundle *)bundle;/**< 获取当前资源文件 */

+(void)initUserLanguage;/**< 初始化语言文件 */
+(NSString *)userLanguage;/**< 获取应用当前语言 */
+(DLLanguageObject *)currentLanguage;/**< 获取应用当前语言 */
+(NSString *)userLanguageEnOrZh; /**< 返回 en 或者 zh */

#pragma mark - 定制语言
+(void)setUserlanguage:(DLLanguageObject *)lanObj;/**< 设置当前语言 */

+ (NSString *)currentSysLanguage;/**< 获取当前系统语言 */
@end
#import "InternationalControl.h"
#import "DLLanguageObject.h"

#define kUserLanguageObject @"userLanguageObject"
#define kAppleLanguages @"AppleLanguages"

@implementation InternationalControl

static NSBundle *bundle = nil;
static DLLanguageObject *langObj = nil;

+ ( NSBundle * )bundle{
    return bundle;
}

+(void)initUserLanguage{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    NSData *lanDataBox = [def valueForKey:kUserLanguageObject];
    langObj = [NSKeyedUnarchiver unarchiveObjectWithData:lanDataBox];
    
    if(!langObj){
        //获取系统当前语言版本(中文zh-Hans,英文en)
        NSArray* languages = [def objectForKey:kAppleLanguages];
        NSString *current = [languages objectAtIndex:0];
        
        if ([current isEqualToString:@"zh-Hans-CN"]) {
            langObj = [DLLanguageObject languageType:DLLanguageTypeCn];
        }else{
            langObj = [DLLanguageObject languageType:DLLanguageTypeEn];
        }
        
        NSData *lanData = [NSKeyedArchiver archivedDataWithRootObject:langObj];
        [def setObject:lanData forKey:kUserLanguageObject];
        [def synchronize];//持久化,不加的话不会保存
    }
    
    //获取文件路径
    NSString *path = [[NSBundle mainBundle] pathForResource:langObj.lanCode ofType:@"lproj"];
    bundle = [NSBundle bundleWithPath:path];//生成bundle
}

#pragma mark - 定制语言
+(void)setUserlanguage:(DLLanguageObject *)lanObj{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    //1.第一步改变bundle的值
    NSString *path = [[NSBundle mainBundle] pathForResource:lanObj.lanCode ofType:@"lproj" ];
    bundle = [NSBundle bundleWithPath:path];
    
    //2.改变记录
    langObj = lanObj;
    
    //3.持久化
    NSData *lanData = [NSKeyedArchiver archivedDataWithRootObject:lanObj];
    [def setObject:lanData forKey:kUserLanguageObject];
    [def synchronize];//持久化,不加的话不会保存
}

+(NSString *)userLanguageEnOrZh{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    NSData *lanDataBox = [def valueForKey:kUserLanguageObject];
    DLLanguageObject *lanObj = [NSKeyedUnarchiver unarchiveObjectWithData:lanDataBox];
    if ([lanObj.lanCode isEqualToString:@"en"]){
        return @"en";
    } else{
        return @"zh";
    }
}

+(NSString *)userLanguage{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    NSData *lanDataBox = [def valueForKey:kUserLanguageObject];
    DLLanguageObject *lanObj = [NSKeyedUnarchiver unarchiveObjectWithData:lanDataBox];
    return lanObj.lanCode;
}

+(DLLanguageObject *)currentLanguage{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    NSData *lanDataBox = [def valueForKey:kUserLanguageObject];
    DLLanguageObject *lanObj = [NSKeyedUnarchiver unarchiveObjectWithData:lanDataBox];
    return lanObj;
}

+ (NSString *)currentSysLanguage{
    NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
    NSArray* languages = [def objectForKey:kAppleLanguages];
    return [languages objectAtIndex:0];
}
@end

2)ALCommentMethod 便捷设置文字工具类

#import <Foundation/Foundation.h>
#import "InternationalControl.h"

@interface ALCommentMethod : NSObject
+ (NSString *)localizationString:(NSString *)key;
@end
#import "ALCommentMethod.h"
@implementation ALCommentMethod
+ (NSString *)localizationString:(NSString *)key{
    NSBundle *langBundle = [InternationalControl bundle];
    NSString *str = [langBundle localizedStringForKey:key value:@"" table:nil];
    return str;
}
@end

3)DLLanguageObject 语言附加信息实体类,充当数据载体功能

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSUInteger,DLLanguageType){
    DLLanguageTypeEn = 0,
    DLLanguageTypeCn
};
@interface DLLanguageObject : NSObject<NSCoding>

@property (nonatomic,assign) DLLanguageType langType;/**< 语言类型 */
@property (nonatomic,strong) NSString *lanCode;/**< 语言代码字符串 */
@property (nonatomic,strong) NSString *titile;/**< 标题 */
@property (nonatomic,strong) NSString *subTitle;/**< 子标题  */
@property (nonatomic,assign) BOOL isSelected;/**< 选中与否 */

#pragma mark - 快速创建
+ (instancetype)languageType:(DLLanguageType)langType;
- (instancetype)initWithLanType:(DLLanguageType)langType;
@end
#import "DLLanguageObject.h"

#define kEnLan @"en"
#define kCnLan @"zh-Hans"

@implementation DLLanguageObject

+ (instancetype)languageType:(DLLanguageType)langType{
    return [[self alloc] initWithLanType:langType];
}


- (instancetype)initWithLanType:(DLLanguageType)langType{
    self = [super init];
    if (self) {
        self.langType = langType;
    }
    return self;
}

- (void)setLangType:(DLLanguageType)langType{
    _langType = langType;
    switch (langType) {
        case DLLanguageTypeEn:{
            _lanCode = kEnLan;
            self.titile = @"English";
            self.subTitle = @"English";
            break;
        }
        case DLLanguageTypeCn:{
            _lanCode = kCnLan;
            self.titile = @"简体中文";
            self.subTitle = @"Chinese,Simpified";
            break;
        }
            
        default:
            break;
    }
}

#pragma mark -
//This is important to for saving the alarm object in user defaults
-(void)encodeWithCoder:(NSCoder *)encoder{
    [encoder encodeInteger:self.langType forKey:@"langType"];
    [encoder encodeObject:self.lanCode forKey:@"lanCode"];
    [encoder encodeObject:self.titile forKey:@"titile"];
    [encoder encodeObject:self.subTitle forKey:@"subTitle"];
    [encoder encodeBool:self.isSelected forKey:@"isSelected"];
}

//This is important to for loading the alarm object from user defaults
-(id)initWithCoder:(NSCoder *)decoder{
    self.langType = [decoder decodeIntegerForKey:@"langType"];
    self.lanCode = [decoder decodeObjectForKey:@"lanCode"];
    self.titile = [decoder decodeObjectForKey:@"titile"];
    self.subTitle = [decoder decodeObjectForKey:@"subTitle"];
    self.isSelected = [decoder decodeBoolForKey:@"isSelected"];
    return self;
}
@end

4)ALChooseLanguageVC 选择语言具体控制器,业务具体相关,仅做参考,请自行实现

#import "ALChooseLanguageVC.h"
#import "ALLanguageCell.h"
#import "DLLanguageObject.h"
#import "InternationalControl.h"

@interface ALChooseLanguageVC ()
@property (nonatomic,strong) NSMutableArray *dataList;/**< 数据源 */
@property (nonatomic,strong) DLLanguageObject *selectedLan;/**< 选中的语言 */
@end

@implementation ALChooseLanguageVC

- (NSMutableArray *)dataList{
    if (!_dataList) {
        _dataList = [NSMutableArray array];
        
        DLLanguageObject *lanEn = [DLLanguageObject languageType:DLLanguageTypeEn];
        DLLanguageObject *lanCn = [DLLanguageObject languageType:DLLanguageTypeCn];
        
        [_dataList addObject:lanEn];
        [_dataList addObject:lanCn];
    }
    return _dataList;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = DLLocal(@"language_chage_title");
    [self settingRightButton];
    
    
    NSInteger index = 0;
    for (DLLanguageObject *lanObj in self.dataList) {
        DLLanguageObject *currentLanguage = [InternationalControl currentLanguage];
        if ([lanObj.lanCode isEqualToString:currentLanguage.lanCode]) {
            currentLanguage.isSelected = YES;
            self.selectedLan = currentLanguage;
            break;
        }
        index++;
    }
    
    [self.dataList replaceObjectAtIndex:index withObject:self.selectedLan];
    [self.tableView reloadData];
}

- (void)settingRightButton{
    [self replaceRightBarButtonItemWithTitle:UBTLocalizedString(@"phone_search_sure") image:nil target:self action:@selector(comfirmSettingLanguage)];
}

- (void)comfirmSettingLanguage{
    [InternationalControl setUserlanguage:self.selectedLan];
    POSTChangeLanguageInfoNotification;
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataList.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ALLanguageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ALLanguageCell"];
    cell.lanObj = [self.dataList objectAtIndexWithExamine:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    self.selectedLan.isSelected = NO;
    DLLanguageObject *lan = [self.dataList objectAtIndexWithExamine:indexPath.row];
    lan.isSelected = YES;
    self.selectedLan = lan;
    [self.tableView reloadData];
}

@end

参考:iOS应用内部切换语言,不跟随系统

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

推荐阅读更多精彩内容