iOS国际化

作者: DDY | 来源:发表于2017-07-03 11:05 被阅读76次

    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
    

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

    相关文章

      网友评论

        本文标题:iOS国际化

        本文链接:https://www.haomeiwen.com/subject/ibsacxtx.html