iOS国际化
https://github.com/starainDou 欢迎点星
NSLocalizedString
Xcode中有本地化的内置支持
- NSLocalizedString的定义:
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
第一个参数key是从Localizable.strings这个文件中读取对应的key-value值。
第二个参数comment可以是nil,可以是一段为空的字符串,也可以是对key的注释。
- 本地化字符串
添加语言支持
AddLanguage.png建立String File文件,命名命名为“Localizable,生成一个Localizable.strings文件(名字不要其他的)
Localizable.png选中新建的Localizable.strings文件,点击右边的Localize,添加English和Chinese
Localize.png在Localizable.strings(English) 文件中写 "OK" = "OK";(不要忘记写分号)
在Localizable.strings(Chinese) 文件中写 "OK" = "确定";(不要忘记写分号)
使用
define OKText NSLocalizedString(@"OK", nil)
如果你的strings文件名字不是Localizable而是自定义的话,如hel.strings,那么你就得使用NSLocalizedStringFromTable()来读取本地化字符串 NSLocalizedStringFromTable(@"hello",@"hel", nil)
如果不能添加语言支持(localizations--choose files and reference language to create...为空白)
打开工程配置,搜 /* Begin XCBuildConfiguration section */
在之前添加段落
/* Begin PBXVariantGroup section /
4C0E56D11F09E6B900583071 / Localizable.strings / = {
isa = PBXVariantGroup;
children = (
4C0E56D01F09E6B900583071 / en /,
4C0E56D21F09E6C200583071 / zh-Hans /,
);
name = Localizable.strings;
sourceTree = "<group>";
};
ABCB97AC1D71D063000DEBEF / LaunchScreen.storyboard / = {
isa = PBXVariantGroup;
children = (
ABCB97AD1D71D063000DEBEF / Base /,
4C0E56CC1F09E37B00583071 / zh-Hans /,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/ End PBXVariantGroup section */
然后添加直接添加Localizable.strings,方法见上,不考虑别的问题,然后回到配置文件搜索
/* Localizable.strings in Resources /
复制ID
搜/ Begin PBXVariantGroup section /,将/ Localizable.strings */ 前面的ID 替换保存即可
XCBuildConfiguration
封装的工具,在APP内切换语言
你可以用黑魔法为全局添加,不过需要处理很多特殊情况。
DDYLanguageTool.h
/**
* 语言国际化使用方式
* 1.AppDelegata中 -application:didFinishLaunchingWithOptions: 里设置默认(初始化即可) [DDYLanguageTool sharedManager];
* 2.选择语言后 [[DDYLanguageTool sharedManager] ddy_SetLanguage:_selectLanguage callback:nil];
*/
#import <Foundation/Foundation.h>
/** 英汉双语 */
#if TARGET_IPHONE_SIMULATOR
#define DDYStr(Chinese,English) [DDYCurrentLanguage isEqualToString:IOS_9_LATER?@"zh-Hans-US":@"zh-Hans"] ? Chinese : English
#elif TARGET_OS_IPHONE
#define DDYStr(Chinese,English) [DDYCurrentLanguage isEqualToString:IOS_9_LATER?@"zh-Hans-CN":@"zh-Hans"] ? Chinese : English
#endif
extern NSErrorDomain DDYLanguageErrorDomain;
#define kDDYLanguageErrorSuccess 0 // 设置语言成功
#define kDDYLanguageErrorUnknown -1 // 未知错误
#define kDDYLanguageErrorNil -2 // 语言为空
#define kDDYLanguageErrorNotSupport -3 // 不支持的语言
static NSString *const DDY_CN = @"zh-Hans";
static NSString *const DDY_EN = @"en";
@interface DDYLanguageTool : NSObject
/** 单例对象 */
+ (instancetype)sharedManager;
/** 获取当前语言 */
- (NSString *)localLanguage;
/** 切换语言(汉英时) */
- (void)changeLanguage;
/** 设置语言(较多语言支持时) */
- (void)ddy_SetLanguage:(NSString *)language callback:(void (^)(NSError *error))callback;
@end
DDYLanguageTool.m
#import "DDYLanguageTool.h"
#import <objc/runtime.h>
#define DDYLanguageSet @"DDYLanguageSet"
NSErrorDomain DDYLanguageErrorDomain = @"DDYLanguageErrorDomain";
//----------------------- NSBundle子类 -----------------------//
static const char _bundle = 0;
@interface DDYBundleExt : NSBundle
@end
@implementation DDYBundleExt
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
NSBundle *bundle = objc_getAssociatedObject(self, &_bundle);
return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName];
}
@end
//------------------------ 语言设置工具类 -----------------------//
@implementation DDYLanguageTool
#pragma mark - 单例对象
static DDYLanguageTool *_instance;
+ (instancetype)sharedManager {
return [[self alloc] init];
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone {
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
#pragma mark 初始化
- (instancetype)init {
if (self = [super init]) {
NSString *currLanguage = DDYUserDefaultsGet(DDYLanguageSet);
// 默认语言(中英)
if (!currLanguage) {
currLanguage = DDYStr(DDY_CN, DDY_EN);
}
DDYUserDefaultsSet(currLanguage, DDYLanguageSet)
[DDYUserDefaults synchronize];
[self setLanguage:currLanguage];
}
return self;
}
#pragma mark 获取当前语言
- (NSString *)localLanguage {
return DDYUserDefaultsGet(DDYLanguageSet);
}
#pragma mark 切换语言(中英时)
- (void)changeLanguage {
[DDYUserDefaults setObject:[DDYUserDefaultsGet(DDYLanguageSet) isEqualToString:DDY_CN] ? DDY_EN : DDY_CN forKey:DDYLanguageSet];
[DDYUserDefaults synchronize];
}
#pragma mark 设置语言(较多语言支持时)
- (void)ddy_SetLanguage:(NSString *)language callback:(void (^)(NSError *error))callback {
if ([language ddy_blankString]) {
if (callback) callback([NSError errorWithDomain:DDYLanguageErrorDomain code:kDDYLanguageErrorNil userInfo:@{@"reason":@"设置的语言不能为空"}]);
} else {
[self setLanguage:language];
[DDYUserDefaults setObject:language forKey:DDYLanguageSet];
[DDYUserDefaults synchronize];
if (callback) callback([NSError errorWithDomain:DDYLanguageErrorDomain code:kDDYLanguageErrorSuccess userInfo:@{@"reason":@"设置成功"}]);
}
}
#pragma mark 私有方法 设置语言
- (void)setLanguage:(NSString *)language {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object_setClass([NSBundle mainBundle], [DDYBundleExt class]);
});
objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end