iOS开发-本地化- 根据App设置加载本地化资源

网上看到一些关于:“根据App设置”加载本地化资源的文章。但都只讲到了界面文字的本地化,却没有关于图标,视频等其他资源的本地化实现方式。

今天,正好我们的App中需要这种功能,便自己实现了一套。里面除了“文字”外,还实现了“图像”,“plist”的加载。其他如“视频”,“json”等文件可调用:BALocalizedFile方法来加载。

这里就把实现的代码贴出来,便于大家参考。

头文件:BALocalized.h

//
//  BALocalized.h
//  mhMoney
//
//  Created by wuzhigang on 2024/2/27.
//

#import <Foundation/Foundation.h>

#define kAppLanguage @"AppLanguage"

//获取系统语言字符串
NSString* BALocalizedSystemLanguage(void);

//保存App语言设置到配置文件中。
//传入:
//language:"en", "zh-Hans"等本地化目录名
void BALocalizedSaveLanguage(NSString *language);

//从配置文件读取当前App语言配置。
//返回:
//language:"en", "zh-Hans"等本地化目录名
NSString* BALocalizedReadLanguage(void);

//本地化Bundle获取。
//返回:本地化Bundle
NSBundle* BALocalizedBundle(void);

//返回本地化字符串
//传入:
//key:字符串Key
//table:table
//返回:
//Key对应的本地化字符串
NSString* BALocalizedString(NSString* key, NSString* table);

//初始化本地化语言
//传入:
//language:"en", "zh-Hans"等本地化目录名
void BALocalizedInitLanguage(NSString *language);

//获取本地化资源文件
//传入:
//fileName:文件名
//type:文件扩展名,如"plist", "png", "mp4", "wav"等。
//返回
//本地化的文件路径
NSString* BALocalizedFile(NSString* fileName, NSString* type);

//获取本地化plist
//传入:
//fileName:文件主名
//type:文件扩展名,如"plist", "png", "mp4", "wav"等。
//返回
//plist内容
NSArray* BALocalizedPlist(NSString* fileName);

//获取本地化图片
//传入:
//imageName:图片主名
//返回
//UIImage对象
//注意:其他图片类型,修改该方法内部type值即可。如“jpg"等。
UIImage* BALocalizedImage(NSString* imageName);

实现文件:BALocalized.m

//
//  BALocalized.m
//  mhMoney
//
//  Created by wuzhigang on 2024/2/27.
//

#import "BALocalized.h"

static NSBundle *staticLocalizedBundle;

NSString* BALocalizedSystemLanguage(void){
    NSArray *languages = [NSLocale preferredLanguages]; //系统偏好语言
    NSString *language = languages.firstObject;
    if ([language hasPrefix:@"zh-Hans"]) {
        return @"zh-Hans";
    }
    
    return @"en";
}

void BALocalizedSaveLanguage(NSString *language){
    if (!language || language.length == 0){
        language = @"en";
    }
    
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    if (!userDefaults)
        return;
    
    [userDefaults setValue:language forKey:kAppLanguage];
}

NSString* BALocalizedReadLanguage(void){
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    if (!userDefaults)
        return BALocalizedSystemLanguage();
    
    NSString *language = [userDefaults valueForKey:kAppLanguage];
    
    if (!language || language.length == 0){
        return BALocalizedSystemLanguage();
    }
    
    return language;
}

void BALocalizedInitLanguage(NSString *language){
    staticLocalizedBundle = nil;
    BALocalizedSaveLanguage(language);
}

NSBundle* BALocalizedBundle(void){
    if (staticLocalizedBundle)
        return staticLocalizedBundle;

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString *language = userDefaults ? [userDefaults valueForKey:kAppLanguage] : nil;
    
    if (!language || language.length == 0) {
        return nil;
    }
    
    NSString *path = [NSBundle.mainBundle pathForResource:language ofType:@"lproj"];
    
    if (!path || path.length == 0)
        return nil;

    NSBundle *bundle = [NSBundle bundleWithPath:path];
    
    staticLocalizedBundle = bundle ? bundle : NSBundle.mainBundle;
    
    return staticLocalizedBundle;
}

NSString* BALocalizedString(NSString* key, NSString* table){
    NSBundle *bd = BALocalizedBundle();
    
    if (!bd)
        return nil;
    
    return [bd localizedStringForKey:key value:nil table:table];
}

NSString* BALocalizedFile(NSString* fileName, NSString* type){
    if (!fileName || fileName.length == 0)
        return nil;

    if (!type || type.length == 0)
        return nil;

    NSBundle *bd = BALocalizedBundle();
    
    if (!bd)
        return nil;
    
    return [bd pathForResource:fileName ofType:type];
}

NSArray* BALocalizedPlist(NSString* fileName){
    NSString *filePath = BALocalizedFile(fileName, @"plist");
    
    if (!filePath || filePath.length == 0)
        return nil;
    
    return [[[NSArray alloc] initWithContentsOfFile:filePath] autorelease];
}

UIImage* BALocalizedImage(NSString* imageName){
    if (@available(iOS 17.0, *)){
        NSLocale *locale = [[[NSLocale alloc] initWithLocaleIdentifier:BALocalizedReadLanguage()] autorelease];
        UIImageConfiguration *config = [UIImageConfiguration configurationWithLocale:locale];
        //非Assets资源本地化放在各个语言的bundle中,而Assets中的本地化放在Main Bundle中。
        //故先从非Assets中加载,没有找到再从主bundle中加载。
        NSBundle *bd = BALocalizedBundle();
        UIImage *icon = nil;
        if (bd){
            icon = [UIImage imageNamed:imageName inBundle:bd withConfiguration:config];
        }
        
        if (!icon) {
            icon = [UIImage imageNamed:imageName inBundle:nil withConfiguration:config];
        }
        return icon;
    }
    else{
        //iOS 17.0之前,动态加载本地化图片,需要放在非Assets中。
        NSString *imagePath = BALocalizedFile([NSString stringWithFormat:@"%@%@", imageName, @"@3x"], @"png");

        if (!imagePath || imagePath.length == 0) {
            //从Main bundle中加载Assets下的图片资源。
            return [UIImage imageNamed:imageName];
        }
        else{
            return [UIImage imageWithContentsOfFile:imagePath];
        }

    }
}

注意:加载“图片”资源的实现,在iOS17以后已有对应实现。iOS17之前,要想图片根据App设置语言加载,需要将图片资源放在“Assets”文件夹“之外”的地方,才可以实现加载。图片默认支持@3x的png文件,这里可根据自己的情况进行修改。

简单使用:
1:找到“项目名称-Prefix.pch”,加入#import "BALocalized.h"
2:在Appdelegate中的didFinishLaunchingWithOptions中调用:BALocalizedInitLanguage(BALocalizedReadLanguage());
3:本地化文字,调用:BALocalizedString(key, table),table根据情况可设置为nil。
4:本地化图片,调用:BALocalizedImage(imageName)
5:本地化plist,调用:BALocalizedPlist(fileName)
6:在App设置语言界面中,选中某个语言后,调用:
(1)BALocalizedSaveLanguage(@"en"); //“en"为当前选择的语言名称。
(2)BALocalizedInitLanguage(BALocalizedReadLanguage());
(3)刷新界面(如重设window.rootViewController )。

觉得帮助到你了,记得点赞喔!

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

推荐阅读更多精彩内容