iOS之基础知识iOS之功能细节

iOS国际化

2017-07-03  本文已影响76人  DDY

https://github.com/starainDou 欢迎点星

NSLocalizedString

Xcode中有本地化的内置支持

#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

码农不易,点个星星支持下吧 DDYLanguageTool

上一篇下一篇

猜你喜欢

热点阅读