美文网首页iOS开发搬砖
iOS 国际化(App内语言切换)

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

作者: 光之盐汽水 | 来源:发表于2018-10-11 16:10 被阅读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,结束了!

    相关文章

      网友评论

        本文标题:iOS 国际化(App内语言切换)

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