我们的应用都是需要国际化的,字符串也是重要的一环。一般来说,我们是通过一个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

iOS6和iOS7代码的适配(6) —— NSLocalizedString的更多相关文章

  1. iOS6和iOS7代码的适配(1)

    苹果的iOS7推出后,对于所有的应用来说都提出了一个天然的需求--适配不同版本的SDK.目前来说,用iOS6的SDK生成的应用,可以在iOS7的系统上跑,UI上也保持了原来的风格样式,这是苹果做的向下 ...

  2. iOS6和iOS7代码的适配(3)——坐标适配

    由于iOS7里面status bar和视图是重叠在一起了,所以应用的y坐标就没法和以前一致了,需要重新计算设定.基本上,你的应用用Xcode5运行一下就能看见这个问题,这里写了一个最简单的例子,一个V ...

  3. iOS6和iOS7代码的适配(5)——popOver

    popOver这个空间本身是iPad only的,所以iPhone上见不到,我记得微信上有个这样的弹出框,有扫一扫等几个菜单项,估计这是腾讯自己实现的,用于菜单的扩展. popOver从iOS6到iO ...

  4. iOS6和iOS7代码的适配(4)——tableView

    iOS7上不少控件的样子有了变化(毕竟要扁平化嘛),不过感觉变化最大的肯定非tableView莫属.因为这个控件的高度可定制性,原先是使用及其广泛的,这样的一个改变自然也影响颇大. 1.accesso ...

  5. iOS6和iOS7代码的适配(2)——status bar

    用Xcode5运行一下应用,第一个看到的就是status bar的变化.在iOS6中,status bar是系统在处理,应用中不需要考虑这部分,iOS7之后是应用在处理,每个ViewControlle ...

  6. IOS6和IOS7的屏幕适配问题

    自从IOS7出来以后,以前写在IOS6上或者更低版本的程序,跑在IOS7的模拟器上就会出现一些问题.最大的问题就是,所有的UI空间都会统一向上移动20个点(如果空间的y值为0,就会被StatusBar ...

  7. (ios7) 解决代码布局View, ios7 中 subView 高度增加StatusBar20dp的问题,保证Ios6,ios7代码一致

    在ios7 布局中,Status Bar 和 ToolBar ,NavigateBar 等都包含在ViewControl的主View中. 这样原来ios6 的View布局 整体向上移动了20dp,下面 ...

  8. 适配iOS6与iOS7

    适配屏幕其实很简单,但为了保持兼容性以及写的代码的通用性,以及最小的改动代码,本人按照如下的一种方式来适配,可以一劳永逸. 1. 先定义几个宏,分辨表示应用可以使用区域的高度,屏幕可用区域的高度,屏幕 ...

  9. iOS- <项目笔记>iOS6 & iOS7屏幕图片适配

    1.为非视网膜\视网膜屏幕分别准备2份图片,比如: 1> 非视网膜 abc.png 2> 视网膜 abc@2x.png 程序检测视网膜屏到会自动替换@2x 2.程序启动图片 * 程序启动过 ...

随机推荐

  1. linux比较两个文件的不同(6/21)

    cmp 命令:比较任意两个类型的文件,且吧结果输出到标准输出,默认文件相同不输出,不同的文件输出差异 必要参数 -c 显示不同的信息-l 列出所有的不同信息-s 错误信息不提示 选择参数 -i< ...

  2. 20145219 《Java程序设计》实验二 Java面向对象程序设计实验报告

    20145219 <Java程序设计>实验二 Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S. ...

  3. [CF19E]Fairy

    给定一张n个点m条边的无向图,求删除哪一条边后,能够确保构成一个二分图,输出所有可能 解法:我们知道二分图的性质是没有奇环,这道题我们也应该从这个方面入手来考虑. 如果没有奇环的话我们当然想怎么删就怎 ...

  4. Mybatis配置插入数据返回主键ID

    需要在insert方法中添加 <insert id="insertSelective" parameterType="com.midou.ott.model.MDA ...

  5. linux下gzip压缩同样内容大小不一样

    一份数据,两种传输方式进行收集. 一份数据:有多台数据采集节点或者多个数据源 两种方式:一种是从依次多个采集节点或者多个数据源将数据拷贝过来,合并为一个文件 另外一种是多个采集节点或者数据源同时向汇总 ...

  6. C# 捕获数据库自定义异常

    在 SQL Server 的存储过程中根据业务逻辑的要求,有时需要抛出自定义异常,由C#程序俘获之并进行相应的处理.SQL Server 抛出自定义异常和简单,像这样就可以了:RAISERROR('R ...

  7. RadioButton实现多选一

    RadioButton实现多选一 一.简介 二.RadioButton实现多选一方法 1.将多个RadioButton放在一个RadioGroup里面 <RadioGroup android:i ...

  8. ActiveMQ 性能调优

    本章重点 学习普通的性能调优技巧 怎么优化生产者和消费者 调优实例 简介 ActiveMQ 的性能高度依赖于多种不同的因素,包括:网络代理拓扑架构,传输层,底层网络的服务质量和速度,硬件,操作系统和 ...

  9. lightoj1213推公式

    很容易推出来的公式ans=n^(k-1)*k*sum 然后快速幂就好了 #include<map> #include<set> #include<cmath> #i ...

  10. 音悦台mv视频下载

    需要获取的页面: 参考了此处,做了修改,代码如下: #coding:utf-8 import urllib2 import urllib import re import sys import os ...