当我们的应用仅仅面向国内用户群,一般仅支持一种语言--中文就可以了。当面向国外用户时就需要进行国际化了,不仅仅是语言的转变,也可能包括设计风格,页面布局、交互效果的转变,如微信,微博,QQ这类应用都有着切换语言的功能。

iOS常用的国际化流程

1.建立strings文件。2.在Localization勾选支持的语言,在不同的后缀的同文件名的strings中设置标题。3.使用NSLocalizedStringFromTable(key, tbl, comment) 这个宏取出key对应的value。
这样的做法方便快捷,但有一些缺点。1.完全是根据手机系统设置的语言来进行国际化的。2.手机系统语言更改后,需将App Kill后,重新进入才有改变。可以看出给用户带来很大的不便,一些用户根本不知道如何设置语言,而且还去跳出应用,再Kill应用。我们需要的是应用内切换语言,所见即所得。

应用内切换语言

先看下微信的做法

111.gif

可以看出选择新语言,保存后就直接切换了。这样的用户体验就比较好了。

关键

1.NSBundle

An NSBundle object represents a location in the file system that groups code and resources that can be used in a program.NSBundle objects locate program resources, dynamically load and unload executable code, and assist in localization. You build a bundle in Xcode using one of these project types: Application, Framework, plug-ins.

2.宏 NSLocalizedStringFromTableInBundle

它的定义
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) [bundle localizedStringForKey:(key) value:@"" table:(tbl)]
Returns a localized version of a string.The key for a string in the specified table.从指定的bundle里的table中返回对应key的值。
上面两点就是应用内切换的关键
先浏览下Demo架构

structure.png

使用storyboard方式,常见的TabBar+Navigation形式,第一个页面的按钮来切换语言,第二个来显示当前语言。

建立FGLanguageTool类来管理语言的切换,因为许多地方都要用到,将其设计为单例。并定义一个宏来加载设定的语言。

#define FGGetStringWithKeyFromTable(key, tbl)
[[FGLanguageTool sharedInstance] getStringForKey:key withTable:tbl] #import <Foundation/Foundation.h> @interface FGLanguageTool : NSObject +(id)sharedInstance; /**
* 返回table中指定的key的值
*
* @param key key
* @param table table
*
* @return 返回table中指定的key的值
*/
-(NSString *)getStringForKey:(NSString *)key withTable:(NSString *)table; /**
* 改变当前语言
*/
-(void)changeNowLanguage; /**
* 设置新的语言
*
* @param language 新语言
*/
-(void)setNewLanguage:(NSString*)language; @end

对应的.m文件

#define CNS @"zh-Hans"
#define EN @"en"
#define LANGUAGE_SET @"langeuageset" #import "AppDelegate.h"
#import "FGLanguageTool.h" static FGLanguageTool *sharedModel; @interface FGLanguageTool() @property(nonatomic,strong)NSBundle *bundle;
@property(nonatomic,copy)NSString *language; @end @implementation FGLanguageTool +(id)sharedInstance
{
if (!sharedModel)
{
sharedModel = [[FGLanguageTool alloc]init];
} return sharedModel;
} -(instancetype)init
{
self = [super init];
if (self)
{
[self initLanguage];
} return self;
} -(void)initLanguage
{
NSString *tmp = [[NSUserDefaults standardUserDefaults]objectForKey:LANGUAGE_SET];
NSString *path;
//默认是中文
if (!tmp)
{
tmp = CNS;
}
else
{
tmp = EN;
} self.language = tmp;
path = [[NSBundle mainBundle]pathForResource:self.language ofType:@"lproj"];
self.bundle = [NSBundle bundleWithPath:path];
} -(NSString *)getStringForKey:(NSString *)key withTable:(NSString *)table
{
if (self.bundle)
{
return NSLocalizedStringFromTableInBundle(key, table, self.bundle, @"");
} return NSLocalizedStringFromTable(key, table, @"");
} -(void)changeNowLanguage
{
if ([self.language isEqualToString:EN])
{
[self setNewLanguage:CNS];
}
else
{
[self setNewLanguage:EN];
}
} -(void)setNewLanguage:(NSString *)language
{
if ([language isEqualToString:self.language])
{
return;
} if ([language isEqualToString:EN] || [language isEqualToString:CNS])
{
NSString *path = [[NSBundle mainBundle]pathForResource:language ofType:@"lproj"];
self.bundle = [NSBundle bundleWithPath:path];
} self.language = language;
[[NSUserDefaults standardUserDefaults]setObject:language forKey:LANGUAGE_SET];
[[NSUserDefaults standardUserDefaults]synchronize];
[self resetRootViewController];
} //重新设置
-(void)resetRootViewController
{
AppDelegate *appDelegate =
(AppDelegate *)[[UIApplication sharedApplication] delegate];
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UINavigationController *rootNav = [storyBoard instantiateViewControllerWithIdentifier:@"rootnav"];
UINavigationController *personNav = [storyBoard instantiateViewControllerWithIdentifier:@"personnav"];
UITabBarController *tabVC = (UITabBarController*)appDelegate.window.rootViewController;
tabVC.viewControllers = @[rootNav,personNav];
}
@end

在ViewController里使用下面类似的方式进行赋值

self.navigationItem.title = FGGetStringWithKeyFromTable(@"RootTitle", @"Main");
self.languageLabel.text = FGGetStringWithKeyFromTable(@"NowLanguage", @"Person");

"Main","Person"就是strings文件的名字。"RootTitle"和"NowLanguage"就是key。

setting.png

这些就是我们的代码部分,还有一些资源文件要进行配置,就是我们的多语言文件。
1,添加支持的语言,选择工程。

add.png

点击Localizations区域的+号,添加新的语言,我们这里示例就选择简体中文。
2,建立strings文件
方法1.选择一个storyboard,这里我们使用工程默认的Main.storyboard,在File Inspecter。在Localization栏中勾选支持的语言。系统就会生成对应的文件。方法2.我们直接新建strings资源文件。在该文件的File Inspecter的Localization栏中勾选支持的语言。

strings.png

图中的Main是用方法1创建的,Person是用方法2创建的。这些同名的文件仅仅依靠后缀来区分,对应相应的资源。在这些文件中添加对应的key和value,如
Person.strings(English)文件中内容

"NowLanguage"="English";
"PersonTitle"="Person";

Person.strings(Chinese(Simplified))文件中内容

"NowLanguage"="中文";
"PersonTitle"="个人";

即在不同的相同文件名不同后缀名文件中设置不同的value。

几个关键点

1,当我们设置支持多语言后创建多语言文件后,工程文件结构中多了一些文件夹,Base是工程默认的,而后面的两个就是我们设置多语言后自动生成的,对应相应的英文和简体中文。分别以en和zh-Hans开头,所以FGLanguageTool中将中文和英文定义为en和zh-Hans来加载对应的bundle。

directory.png

里面存放的就是对应的strings文件

stings.png

2.NSLocalizedStringFromTableInBundle,从指定的bundle中去指定table的key的值。
3.更改语言后,重新设置rootViewController,使得可以重新加载语言。

最终效果

change.gif
文/FarmGuo(简书作者)
原文链接:http://www.jianshu.com/p/627da5a9992c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

iOS应用内语言切换功能的更多相关文章

  1. iOS开发——iOS国际化 APP内语言切换

    最近一个一直在迭代的老项目收到一份新的开发需求,项目需要做国际化适配,简体中文+英文.由于项目中采用了storyboard和纯代码两种布局方式,所以国际化也要同时实现.上网查了些资料,实现了更改系统语 ...

  2. Android app应用多语言切换功能实现

    最近在做一个多语言切换的功能,类似于微信的语言切换,搜了下资料基本上都是以下这种: 1. 实现的效果 和微信类似,在设置界面打开切换语言的界面,选择语言后重启 HomeActivity,语言切换完成, ...

  3. iOS - 国际化语言切换

    iOS国际化:如何切换语言   1.国际化就是将标签.提示信息等信息放到资源文件中,随着程序需要的语言提供对应的资源文件.以key/value对存储,每个资源的key值不变,value随着需求改变. ...

  4. Android学习–Android app 语言切换功能

    功能: app用户根据自己的语言喜好,设置app语言.语言设置只针对本app,并在下次启动应用时保留前一次启动设置. 更新语言: public static void changeAppLanguag ...

  5. vue-i18n vue-cli项目中实现国际化 多语言切换功能 一

    vue-cli项目中引入vue-i18n 安装: npm install vue-i18n可参考vue-i18n官网文档 main.js中引入: import Vue from 'vue' impor ...

  6. Android应用内语言切换实现(转)

    使用Java反射机制 IActivityManager与ActivityManagerNative都是非公开类,使用Java反射去调用其中的方法. 第一步.使用Android开放的api更改Confi ...

  7. react项目实现多语言切换

    网站的语言切换功能大家都见过不少,一般都是一个下拉框选择语言,如果让我们想一下怎么实现这个功能,我相信大家都是有哥大概思路,一个语言切换的select,将当前的选择的语言存在全局,根据这个语言的key ...

  8. ASP.NET MVC5多语言切换快速实现方案

    功能 实现动态切换语言,Demo做了三种语言库可以切换,包括资源文件的定义,实体对象属性设置,后台代码Controller,IAuthorizationFilter,HtmlHelper的实现,做法比 ...

  9. Android原生多语言切换方案,兼容Android10

    前言 一个应用若需要国际化,至少需要支持中文和英语这两种语言,而同时随着谷歌的系统的更新,安卓系统可以设置当前语言的首选语言.因此,本文立足于此,多语言的切换方案为:App固定的文字内容,跟随系统,中 ...

随机推荐

  1. [置顶] VS自带工具:dumpbin的使用

    有时候我们想查看一个exe引用了哪些动态库,或者我们想看某个动态库包含哪些接口函数,这个时候可以使用dumpbin.exe工具: 1.输入Dumpbin -imports calldll.exe查看它 ...

  2. oracle解析xml完成版第二次修改

    其实XML字符串就好像是ORACLE中的外部表,因此Oracle对 解析XML字符串一些规则要求非常严格.XML字符串提供的数据就是一张表,所以Oracle必须提供跟 xml数据一致的列头 示例一 S ...

  3. UIScrollView 之图片缩放

    UIScrollView 之图片缩放 有些时候,我们可能要对某些内容进行手势缩放,如下图所示 UIScrollView不仅能滚动显示大量内容,还能对其内容进行缩放处理 也就是说,要完成缩放功能的话,只 ...

  4. Swift进阶

    概述 访问控制 Swift命名空间 Swift和ObjC互相调用 Swift和ObjC映射关系 Swift调用ObjC ObjC调用Swift 扩展—Swift调用C 反射 扩展—KVO 内存管理 循 ...

  5. 记一次npapi插件无窗口(windowless )化下的妙巧思路然后解决问题的超爽体验过程

     1:问题 集成第三方的ocx控件,用来做pdf显示和签名.如果用窗口化插件做,很简单,加载ocx到窗口中,再显示到网页即可.但这样有个缺点.就是这个窗口会浮动在网页元素的上面,导致遮挡住网页元素.比 ...

  6. 66 Plus One(大数+1Easy)

    题目意思:vector<int> v存数   eg.123  则v[0]=1,v[1]=2,v[2]=3,加1后返回一个vector 思路:先判断新的vector长度是否需要加1,然后从v ...

  7. javascript权威指南学习笔记1

    打开这本书,进入到javascript的世界.以前都是看各种视频,感觉什么收获也没有,反而弄得脑袋混乱,希望能够按照这本书的节奏掌握javascript这门语言,为我的前端学习打下基础. 学习前准备: ...

  8. 插入数据显示 Duplicate entry '4913' for key 'user_id'

    提示信息翻译:插入4913 使索引重复 分析:索引如果是primary unique这两两种,那么数据表的数据对应的这个字段就必须保证其每条记录的唯一性.否则就会产生这个错误. 一般发生在对数据库写操 ...

  9. lua curl动态链接库编译安装

    关于lua curl的资料网上并不是很多.找来找去就那么几个,所以我绝得很有必要把我的经验记下来,以防下次忘记                                              ...

  10. C:\WINDOWS\system32\config\systemprofile\Desktop引用了一个不可用的位置

    使用迅雷下载压缩文件到桌面时,下载完毕后,如果直接点击"打开文件",则迅雷会报错: C:\WINDOWS\system32\config\systemprofile\Desktop ...