我们的应用都是需要国际化的,字符串也是重要的一环。一般来说,我们是通过一个string资源文件来实现这个目的的,我们需要支持几种语言,就把这个文件本地化多少次。代码中需要用NSLocalizedString这个宏,比如,我希望设置一个tableView的title:

  1. self.navigationItem.title = NSLocalizedString(@"test", nil);
self.navigationItem.title = NSLocalizedString(@"test", nil);

我们这里加了英文和简体中文两种语言。

如果客户选择了我们没有本地化的语言呢?比如,我们选择了繁体中文,那么这个title会显示什么呢?我们一般都希望显示英语。这点在iOS7以前确实没问题,但在iOS7上就变了,你会发现这个语言会选择前一次使用的语言。也就是说,在iOS7上,我先选择,英语,然后换成简体中文,最后换成繁体中文,此时会显示简体中文!

我在开发的一个应用也遇到了这个问题,经过检查,发现这是iOS7调整了语言的顺序导致的。

对比setting页的多国语言设定页:

我们可以很清楚的看出,iOS6上,英语总是位于第二,余下的按照你的设置顺序反向排列;而iOS7不是这样的,它完全是按照你设置语言的顺序反向排列。

在我们调用NSLocalizedString这个宏的时候,系统会按照这个顺序去找本地化的语言文件。这样,当我们选择了繁体中文时,系统发现没有这个语言的本地化,于是按照顺序去逐个检测,iOS6就会使用英语,而iOS7就会使用上一次的语言。

原因已经确定了,那么我们怎么修改呢?有两种方法,下面我们一一来讲。

1. 把应用需要的默认语言放到语言表的第二个位置上,这样可以确保当前语言没有本地化时会显示默认语言

我们知道在UserDefault里面的AppleLanguages里面存储这当前的语言列表,我们可以获得这张列表,然后调整顺序,这样,我们可以确保默认语言放在第二个。代码如下:

  1. NSMutableArray *langArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"AppleLanguages"];
  2. NSUInteger def_lang_index = [langArray indexOfObject:@"en"];
  3. if (def_lang_index != 1 && def_lang_index != 0) {
  4. NSMutableArray *tempArray = [NSMutableArray arrayWithObjects:langArray[0], @"en", nil nil];
  5. [langArray removeObject:langArray[0]];
  6. [langArray removeObject:@"en"];
  7. [tempArray addObjectsFromArray:langArray];
  8. [[NSUserDefaults standardUserDefaults] setObject:tempArray forKey:@"AppleLanguages"];
  9. [[NSUserDefaults standardUserDefaults]synchronize];
  10. }
    NSMutableArray *langArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"AppleLanguages"];
NSUInteger def_lang_index = [langArray indexOfObject:@"en"];
if (def_lang_index != 1 && def_lang_index != 0) {
NSMutableArray *tempArray = [NSMutableArray arrayWithObjects:langArray[0], @"en", nil];
[langArray removeObject:langArray[0]];
[langArray removeObject:@"en"];
[tempArray addObjectsFromArray:langArray]; [[NSUserDefaults standardUserDefaults] setObject:tempArray forKey:@"AppleLanguages"];
[[NSUserDefaults standardUserDefaults]synchronize];
}

需要注意的是,这份代码必须放在main.m文件里面UIApplicationMain()之前,否则,应用本次是不起作用的,只能在下次起作用。

2.  指定Bundle里面的resource文件

第一种方法虽然一劳永逸,但感觉修改的很粗暴,不够优雅!第二种方法才能突出我们程序员们的高大上,不多说了,上代码!

  1. static NSBundle *bundle = nil;
  2. - (NSString*)getCurrentLanguage
  3. {
  4. NSArray *langArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"AppleLanguages"];
  5. return langArray[0];
  6. }
  7. - (void)setLanguage:(NSString *)l {
  8. NSLog(@"preferredLang: %@", l);
  9. NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
  10. if (!path) {
  11. path = [[ NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ];
  12. //[self resetLocalization];
  13. }
  14. bundle = [NSBundle bundleWithPath:path];
  15. }
  16. - (NSString *)get:(NSString *)key alter:(NSString *)alternate {
  17. return [bundle localizedStringForKey:key value:alternate table:nil];
  18. }
static NSBundle *bundle = nil;

- (NSString*)getCurrentLanguage
{
NSArray *langArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"AppleLanguages"];
return langArray[0];
} - (void)setLanguage:(NSString *)l {
NSLog(@"preferredLang: %@", l);
NSString *path = [[ NSBundle mainBundle ] pathForResource:l ofType:@"lproj" ];
if (!path) {
path = [[ NSBundle mainBundle ] pathForResource:@"en" ofType:@"lproj" ];
//[self resetLocalization];
}
bundle = [NSBundle bundleWithPath:path]; } - (NSString *)get:(NSString *)key alter:(NSString *)alternate {
return [bundle localizedStringForKey:key value:alternate table:nil];
}

这几个方法分别是获得当前语言,设置语言——如果没有资源文件就是用默认语言,最后的get:alter:方法就是实际调用的方法,当然,这个没有NSLocalizedString这样方便,所以我们再用宏包装一下:

  1. #define MYLocalizedString(key, comment) \
  2. [self get:(key) alter:(comment)]
#define MYLocalizedString(key, comment) \
[self get:(key) alter:(comment)]

使用的时候如下:

  1. [self setLanguage:[self getCurrentLanguage]];
  2. self.navigationItem.title = MYLocalizedString(@"test", nil);
    [self setLanguage:[self getCurrentLanguage]];
self.navigationItem.title = MYLocalizedString(@"test", nil);

OK,结束了,赶紧试一下吧。

这两种方法都可以使用,个人当然推荐第二种方法,如果第二种方法在扩充一下,可以自己写一个类,这样我们可以确保所有的项目的使用了。

http://blog.csdn.net/sakulafly/article/details/25489863

最新文章

  1. yii + elasticsearch 手册
  2. Java递归算法——变位字
  3. Aspect Oriented Programming using Interceptors within Castle Windsor and ABP Framework AOP
  4. centos安装youcompleteme
  5. URAL 1097 Square Country 2 离散化
  6. iOS开发——语法OC篇&BOOL / bool / Boolean / NSCFBoolean
  7. 简易的highcharts公共绘图模块封装--基于.net mvc
  8. 用BroadcastReceiver监听网络状态的变化
  9. haxe 嵌入swf 读取里面的内容
  10. Verilog风格
  11. 【1】【leetcode-92】 反转链表 II
  12. Django 项目连接数据库Mysql要安装mysqlclient驱动出错 : Failed building wheel for mysqlclient:
  13. codeforces166E
  14. Android应用开发-数据存储和界面展现(二)
  15. 【转】利用Psyco提升Python运行速度
  16. ATG精准科技-前端面试题
  17. winform 开发中 把耗时操作 封装起来 异步执行(.net 4.0)
  18. 自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本 (转载)
  19. BD09坐标(百度坐标) WGS84(GPS坐标) GCJ02(国测局坐标) 的相互转换
  20. linux日志查询技巧

热门文章

  1. 基于SSM的单点登陆05
  2. 利用Metasploit进行Linux提权
  3. spring security使用哈希加密的密码
  4. What's the difference between UTF-8 and UTF-8 without BOM?
  5. viewport简介
  6. spring3: AOP 之切面实例化模型 ——跟我学spring3
  7. 5.8 页面对象(Page Object)模式
  8. 【总结】对异步处理的http接口进行性能测试
  9. 通用 mysql配置
  10. HDU 1856 并查集