iOS开发搬砖

iOS 国际化(App内语言切换)

2018-10-11  本文已影响353人  光之盐汽水

想要实现App内的语言切换功能,那么首先要创建国际化语言文件,用于存储对应语言显示的文本。
1、创建国际化语言文件
command+N,选择Other里面的Empty文件。

image.png
我们将其命名为Localizable.strings
选中刚才创建的文件,在其右侧的的属性栏中点击Localize按钮。
image.png
2、设置项目需要支持的语言
选中project--->info--->Localization。
我们会发现里面默认有一个英语,我们可以点击左下角的➕号添加支持的语言。
image.png
点击+号,选择简体中文。
image.png
默认全选,点击完成即可:
image.png
这时我们展开Localizable.strings、Main.storyboard和LaunchScreen.storyboard,会看到多了一些文件。
image.png
3、文本国际化
英文语言文件.png
中文语言文件.png
大家看这个可能会有疑问,不知道是什么意思。
"首页" = "首页";
"首页" = "Homepage";
其实这两个是一个文本的不同语言的展示。“=”号左面的相当于key值;“=”号右面的相当于value值。不过为了使用方便,更容易理解,我这里直接使用了中文的内容作为key值。
使用方法的话:NSLocalizedString(@"首页", nil);
这样,在中文语言的时候返回“首页”(中文),在英文语言中返回“ Homepage”(英文)。

如果你是用xib或者Storyboard展示文本的话,想要文本国际化展示的话,需要另外的方法。

image.png
首先选中xib或者Storyboard,选中需要支持的语言。 中文
英文

我们可以看到对应的文件里面有对应的显示文本。如果要想xib随着设置的不同语言展示不同的文本的话,可以在这两个文件中修改。

4、本地存储语言设置
使用NSUserDefaults存储本地语言设置。
直接上代码:这是一位大神分享的代码,我复制了一份,效果很不错,看原文请点这里原文.

存储、获取、重置本地语言设置

#import <Foundation/Foundation.h>

@interface UWConfig : NSObject

/**
 用户自定义使用的语言,当传nil时,等同于resetSystemLanguage
 */
@property (class, nonatomic, strong, nullable) NSString *userLanguage;

/**
 重置系统语言
 */
+ (void)resetSystemLanguage;

@end
#import "UWConfig.h"

static NSString *const UWUserLanguageKey = @"UWUserLanguageKey";
#define STANDARD_USER_DEFAULT  [NSUserDefaults standardUserDefaults]

@implementation UWConfig

+ (void)setUserLanguage:(NSString *)userLanguage
{
    //跟随手机系统
    if (!userLanguage.length) {
        [self resetSystemLanguage];
        return;
    }
    //用户自定义
    [STANDARD_USER_DEFAULT setValue:userLanguage forKey:UWUserLanguageKey];
    [STANDARD_USER_DEFAULT setValue:@[userLanguage] forKey:@"AppleLanguages"];
    [STANDARD_USER_DEFAULT synchronize];
}

+ (NSString *)userLanguage
{
    return [STANDARD_USER_DEFAULT valueForKey:UWUserLanguageKey];
}

/**
 重置系统语言
 */
+ (void)resetSystemLanguage
{
    [STANDARD_USER_DEFAULT removeObjectForKey:UWUserLanguageKey];
    [STANDARD_USER_DEFAULT setValue:nil forKey:@"AppleLanguages"];
    [STANDARD_USER_DEFAULT synchronize];
}

@end

切换bundle

#import <Foundation/Foundation.h>

@interface NSBundle (UWUtils)

+ (BOOL)isChineseLanguage;

+ (NSString *)currentLanguage;

@end
#import "NSBundle+UWUtils.h"
#import "UWConfig.h"
#import <objc/runtime.h>

@interface UWBundle : NSBundle

@end

@implementation NSBundle (UWUtils)

+ (BOOL)isChineseLanguage
{
    NSString *currentLanguage = [self currentLanguage];
    if ([currentLanguage hasPrefix:@"zh-Hans"]) {
        return YES;
    } else {
        return NO;
    }
}

/*
 *  设置默认语言类型
 */
+ (NSString *)currentLanguage
{
//    return [UWConfig userLanguage] ? : [NSLocale preferredLanguages].firstObject;
    return [UWConfig userLanguage] ? : @"zh-Hans";
}

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //动态继承、交换,方法类似KVO,通过修改[NSBundle mainBundle]对象的isa指针,使其指向它的子类UWBundle,这样便可以调用子类的方法;其实这里也可以使用method_swizzling来交换mainBundle的实现,来动态判断,可以同样实现。
        object_setClass([NSBundle mainBundle], [UWBundle class]);
    });
}

@end


@implementation UWBundle

- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName
{
    if ([UWBundle uw_mainBundle]) {
        return [[UWBundle uw_mainBundle] localizedStringForKey:key value:value table:tableName];
    } else {
        return [super localizedStringForKey:key value:value table:tableName];
    }
}

+ (NSBundle *)uw_mainBundle
{
    if ([NSBundle currentLanguage].length) {
        NSString *path = [[NSBundle mainBundle] pathForResource:[NSBundle currentLanguage] ofType:@"lproj"];
        if (path.length) {
            return [NSBundle bundleWithPath:path];
        }
    }
    return nil;
}

@end

5、使用方式
当切换app语言的时候,先存储本地语言的设置;然后刷新界面即可。

- (IBAction)simplifiedChinese:(UIButton *)sender {
    [UWConfig setUserLanguage:@"zh-Hans"];
    
    // 刷新界面
    [self reloadTabBarViewController];
}

- (IBAction)english:(UIButton *)sender {
    [UWConfig setUserLanguage:@"en"];
    
    // 刷新界面
    [self reloadTabBarViewController];
}

刷新界面
我这儿是直接刷新了tabBar控制器。

- (void)reloadTabBarViewController {
    
    UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];
    
    UITabBarController *tbc = [storyBoard instantiateInitialViewController];
    // 跳转到个人中心页面(即设置语言的那个tabBarItem)
    tbc.selectedIndex = self.tabBarController.selectedIndex;
    
    // 创建设置页面
    UIViewController *settingVC = [storyBoard instantiateViewControllerWithIdentifier:@"setting"];
    settingVC.hidesBottomBarWhenPushed = YES;
    
    // 创建语言选择界面
    FiFLanguageController *languageVC = [storyBoard instantiateViewControllerWithIdentifier:@"chooseLanguage"];
    languageVC.hidesBottomBarWhenPushed = YES;
    
    UINavigationController *nvc = tbc.selectedViewController;
    
    // 备用
    NSMutableArray *vcs = nvc.viewControllers.mutableCopy;
    [vcs addObjectsFromArray:@[settingVC, languageVC]];
    
    //解决奇怪的动画bug。异步执行
    dispatch_async(dispatch_get_main_queue(), ^{
        
        //注意刷新rootViewController的时机,在主线程异步执行
        //先刷新rootViewController
        [UIApplication sharedApplication].keyWindow.rootViewController = tbc;
        
        //然后再给个人中心的nvc设置viewControllers
        nvc.viewControllers = vcs;
    });
}

ok,结束了!

上一篇下一篇

猜你喜欢

热点阅读