可视化(sb)国际化

在之前悠游宝的一个项目中也做过国际化,当时是很据.string文件生成然后通知切换,今天看到了网上一篇可视化国际化的文章,在这里做下记录



环境

系统环境: iOS7 - iOS9

开发环境: Swift2 & Xcode7

DEMO: LocalDemo

这个Demo的功能主要是切换语言后相应的界面文字&图片以及搜索引擎都会随语言变化。我们会围绕这个DEMO进行讲解,读者可以先下载这个Demo运行看下效果再往下



iOS国际化原理分析

国际化其实都大同小异,其核心思想就是为每种语言单独定义一份资源。

iOS就是通过xxx.lproj目录来定义每个语言的资源,这里的资源可以是图片,文本,Storyboard,Xib等。我们可以看看LocalDemo源代码的物理目录结构

Base,暂时无需理会

English

中文

每种语言都有自己的 语言代码.lproj文件夹,加载资源时只需要加载相应语言文件夹下的资源就OK,这步可以系统为我们完成,也可以手动去做。

项目源代码中如果有多个不同目录的国际化资源,则会有产生多个xxx.lproj,但在编译打包后,会集中放在app的根目录中的xxx.lproj中,不信你看~

开始国际化



首先点击项目->PROJECT->Info->Localizations中添加要支持的语言.

此处Use Base Internationalization开启状态下,每个国际化资源文件会有个Base选项,主要针对String,Storyboard,Xib作为一个基础的模板,像后述storyboard国际化中方案二就是基于Base
StoryBoard进行改动。

在点击+ 添加相应语言时会弹出以下对话框,意思是为现有的资源添加语言文件,我们点击Finish就行了.

文本的国际化



主要针对代码中的字符串进行国际化,比如说一些消息,UI标题等。

我们通过一个Localizable.strings文件来存储每个语言的文本,它是iOS默认加载的文件,如果想用自定义名称命名,在使用NSLocalizedString方法时指定tableName为自定义名称就好了,但你的应用规模不是很大就不要分模块搞特殊了。

每个资源文件如果想为一种语言添加支持,通过其属性面板中的Localization添加相应语言就行了,此时Localizable.strings处于可展开状态,子级有着相应语言的副本。我们把相应语言的文本放在副本里面就行了.

此处Base与前面提过到的开启Use Base Internationalization是有关联的,只有开启了全局Use Base Internationalization此处才会显示。那为什么这里没有勾选Base?Base做为一个基础模板,作用于Strings文件是没有太大意义的,另外去掉Base意义着在Base.lproj中少了一个strings文件,APP大小也所有下降,这点对于图片的Base更是如此.

在上图可以看到其实就是为每一套语言新建一份strings,其内容采用"key" = "value";的格式,注意有;号

我们在代码中这样写就行了


1

2

3

NSLocalizedString("首页",comment: "")

NSLocalizedString("好友",comment: "")

NSLocalizedString("我",comment: "")

另外中文strings【Localizable.strings(Simplified)】可以不要的(可以理解为中文为APP的默认语言),因为key就是value,当找不到相应的语言strings或value时会直接返回key。nice!这样一来我们做文本的国际化就只要维护一个英文副本strings就O了

图片的国际化



二种方案,通过原生支持与自定义命名

注意,新版Xcode中Images.xcassets不支持国际化(属性页面中没有Localization),Xcode5以前是支持的

  • 方案一:自定义文本命名

利用文本国际化的方式,在代码中调用


1

UIImage(named: NSLocalizedString("search_logo",comment: ""))

不推荐,一是因为做法太low了,工作量明显加大。二是不能在Storyboard或XIB中使用

  • 方案二:原生支持

同上,Base副本去掉。另外需要注意的是,使用这种方式,在XIB或Storyboard中引用图片时如果只使用名称是实时显示不了的,一定要加上后缀名。如avater.png

使用方式不变,iOS会自动找相应语言(xxx.lproj)下的图片


1

UIImage(named: "avater")

对于图片的放置,正确姿态应该是需要国际化的图片放在自定义Group里面,不需要国际化的图片放在Images.xcassets

Storyboard&XIB的国际化



前面的两种资源国际化比较简单,但Storyboard国际化就稍微麻烦了点。同样它也有二种方案

  • 方案一:每种语言定制一套Storyboard

在上图我们可以看到,每种语言都可以切换为strings或Storyboard(默认为strings)。如果选用Interface Builder Storyboard方案,那么每种语言都有一套相应的Storyboard,各个语言Storyboard间的界面改动不关联.

  • 方案二:基于基础的Base StoryBoard以及每种语言一套strings

基于一个基础的Storyboard,可以看作是一个基础的模板,Storyboard里面所有的文本类资源(如UILabel的text)都会被放在相应语言的strings里面。此时我们为Storyboard里的字符类资源作国际化只需要编辑相应语言的strings就行了

首选方案二。因为采用方案一,意义着你每改动一个界面元素就得去相应语言Storyboard一一改动,那跟为每个语言新起一个项目是一样的道理。但是采用方案二,我们只需改动Base Storyboard就行了.

注意,方案二中相应语言的strings一旦生成后,Base Storyboard有任何编辑都不会影响到strings,这就意味着如果我们删除或添加了一个UILabel的text,strings也不能同步改动。

还好,Xcode为我们提供了ibtool工具来生成Storyboard的strings文件。


1

ibtool Main.storyboard --generate-strings-file ./NewTemp.string

但是ibtool生成的strings文件是BaseStoryboard的strings(默认语言的strings),且会把我们原来的strings替换掉。所以我们要做的就是把新生成的strings与旧的strings进行冲突处理(新的附加上,删除掉的注释掉),这一切可以用这个pythoy脚本来实现,见AutoGenStrings.py。然后我们将借助Xcode
中 Run Script来运行这段脚本。这样每次Build时都会保证语言strings与Base Storyboard保持一致。

应用内切换语言



应用启动时,首先会读取NSUserDefaults中的key为AppleLanguages的内容,该key返回一个String数组,存储着APP支持的语言列表,数组的第一项为APP当前默认的语言。

在安装后第一次打开APP时,会自动初始化该key为当前系统的语言编码,如简体中文就是zh-Hans。


1

2

//获取APP当前语言

(NSUserDefaults.standardUserDefaults().valueForKey("AppleLanguages") as! Array)[0]

那么我们要实现语言切换改变AppleLanguages的值即可,但是这里有一个坑,因为苹果没提供给我们直接修改APP默认语言的API,我们只能通过NSUserDefaults手动去操作,且AppleLanguages的值改变后APP得重新启动后才会生效(才会读取相应语言的lproj中的资源,意义着就算你改了,资源还是加载的APP启动时lproj中的资源),猜测应该是框架层在第一次加载时对AppleLanguages的值进行了内存缓冲


1

2

3

4

//设置APP当前语言

var def = NSUserDefaults.standardUserDefaults()

def.setValue([“zh-Hans”], forKey:"AppleLanguages")

def.synchronize()

那么问题来了,如何做到改变AppleLanguages的值就加载相应语言的lproj资源?

其实,APP中的Storyboard的加载,图片与字符串的加载都是在NSBundle.mainBundle()上操作的,那么我们只要在语言切换后把NSBundle.mainBundle()替换成当前语言的bundle就行了,这样系统通过NSBundle.mainBundle()去加载资源时实则是加载的当前语言bundle中的资源

lproj目录可以用一个NSBundle表示:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

import Foundation

 

/**

*  当调用onLanguage后替换掉mainBundle为当前语言的bundle

*/

private  let _bundle:UnsafePointer=  unsafeBitCast(0,UnsafePointer.self)

class BundleEx: NSBundle {

    override func localizedStringForKey(key: String, value: String?, table tableName: String?) -> String {

        if let bundle = languageBundle() {

            return bundle.localizedStringForKey(key, value: value, table: tableName)

        }else{

            return super.localizedStringForKey(key, value: value, table: tableName)

        }

    }

}

 

extension NSBundle{

    private struct Static {

        static var onceToken : dispatch_once_t = 0

    }

    func onLanguage(){

        //替换NSBundle.mainBundle()为自定义的BundleEx

        dispatch_once(&Static.onceToken) {

            object_setClass(NSBundle.mainBundle(), BundleEx.self)

        }

    }

     

    //当前语言的bundle

    func languageBundle()->NSBundle?{

        return Languager.standardLanguager().currentLanguageBundle

    }

}

以上Languager是 iOS-i18n 开源库的一部分,我把项目中国际化部分封装了下,有兴趣的童鞋可以去看看

其他


  • 设置运行语言环境

有时我们第一次安装APP时不想默认跟随系统,那么可以通过Xcode的scheme来指定特定语言

Storyboard实时预览,直接上图~

  • IB中UIImageView国际化无效

解决办法就是为UIImageView扩展一个方法,然后通过IB中的User Defined Runtime Attributes把imageName传进去


1

2

3

4

5

6

7

8

9

10

extension UIImageView{

    var locale:String{

        get{

            return ""

        }

        set(newlocale){

            self.image = localizedImage(newlocale)

        }

    }

}

  • IB中UITextView国际化无效

解决办法和UIImageView类似,扩展一个方法,然后把self.text做为key去strings文件中拿相应语言的value


1

2

3

4

5

6

7

8

9

10

extension UITextView{

    var locale:Bool{

        get{

            return true

        }

        set(newlocale){

            self.text = localized(self.text)

        }

    }

}

  • LaunchScreen.xib的国际化

很遗憾,到目前为止,还不支持LaunchScreen.xib的国际化,我们只能通过自定义一个LaunchViewController来完成此需求,但也有些不足,就是应用启动时会黑屏一段时间,所以建议启动页面不要弄国际化.

时间: 2024-09-14 03:16:52

可视化(sb)国际化的相关文章

从汉化到国际化

摘要: 1 按照JAVA的国际化设计框架规范:如何通过Linux系统的本地化设置让JAVA应用支持中文 2 按照Java Webapp设计框架规范:通过web.xml设置解决URLEncoder.encode()方法和系统缺省编码方式相关的问题 3 以GOOGLE的搜索引擎为例:说明如何将国际化和本地化应用到自己的应用设计中(Unicode inside Locale outsite) 通过Linux系统的本地化设置让JAVA应用支持中文 Java 编程技术中汉字问题的分析及解决 这篇文章很不错

国际化的SRE

[写作目的] SRE在AE的定义仅仅指与可用性相关,当它指一种技术方面时,是指原来的稳定性的概念:当它用来指团队时,是指各技术团队负责稳定性的同学组成的虚拟团队,类似于原来的稳定性小组. AliExpress的Alexa排名50名内,甚至超过bing的网站:App也在接近上百国家购物类App下载量排名第一.在AE的整个发展过程中,在稳定性治理方面踩过很多坑,积累了丰富的经验. 因此写作目的有两个: 一.随着集团国际化的必然趋势,以及国际化的共同技术特点,期望能将经验输出给集团,甚至是SRE的一些

我的Java开发学习之旅------>Java资源的国际化详解

internationalization (国际化)简称 i18n,因为在i和n之间还有18个字符,localization(本地化 ),简称L10n. 国际化相关的Java类 Java国际化主要通过如下3个类完成 java.util.ResourceBundle:用于加载一个资源包 java.util.Locale:对应一个特定的国家/区域.语言环境. java.text.MessageFormat:用于将消息格式化 国际化资源文件 为实现程序的国际化,必须提供程序所需要的资源文件.资源文件的

悉尼科技大学数据场馆实现数据可视化

文章讲的是悉尼科技大学数据场馆实现数据可视化,2015年9月1日(悉尼)悉尼科技大学数据场馆(Data Arena)身临其境的视觉和听觉观感将大数据研究发现带入新领域. 多家媒体受邀体验了这一挑战观感并潜力无限的艺术呈现装置.目前这一装置位于Ultimo Broadway的悉尼科技大学工程和信息技术大楼一层运行. 作为澳洲唯一.全球为数不多的类似装置的领跑者,悉尼科技大学数据场馆(Data Arena)旨在简化人们每天收集到并试图理解的大量繁复多样的数据,并帮助人们从中受益. 悉尼科技大学副校长

锦江国际电商CEO包磊:大平台国际化

在旅游酒店行业,包磊是拥有20余年从业经验的老兵:而在互联网行业,他却是一位创业"新人".在一座历史建筑的顶层,他坐在本报记者对面,外面是开放式大平台办公室的喧闹,青春与历史感的莫名混搭,让人有几分时空与情绪错乱之感.但这就是这位上海锦江国际电子商务有限公司(下简称"锦江国际电商")副董事长兼首席执行官要的感觉,他告诉我们,正因为有了锦江国际集团百年的积累.个人职业20年的历练,才会有过去一年他和团队的爆发性成长,以及对未来发展的信心.他与团队创业的平台,是具有近一

VC欣赏、家人是阻力,极客化、国际化——90后创业生态

90后开始登台. 季逸超,PeakJi,1992年北京生人,曾在北大附中读书时单独一人做出猛犸浏览器.在大学参加的一次活动中,本不想创业的他,没能抵挡住红杉资本合伙人周逵"诱惑",后获得徐小平和红杉资本投资,成立了PeakLabs实验室.有着高知父母的他是典型的"90后技术宅",从小学就开始研习编程,后来推出的猛犸浏览器从设计到美工.开发.测试.运营等工作,全部由他一人独立完成,他曾坦言管理和销售不是他的长项,目前PeakLabs也不要求坐班,所有核心成员基本通过邮

地理信息企业国际化必不可少

宋关福资料图片.超图软件供图 人物介绍 宋关福 中国地理信息产业协会副会长,北京超图软件股份有限公司总裁,我国GIS软件开发带头人.1996年后一直致力于地理信息系统软件研究,主持并直接参加SuperMap GIS软件的设计与研发工作,曾荣获中国软件企业十大领军人物等多项荣誉. 超图软件是中国和亚洲领先的地理信息系统平台软件企业,主要从事GIS基础平台和应用平台软件的研究.开发.推广和服务. 阿里巴巴投资2.94亿美元入股高德软件.谷歌开发者大会地图成最大亮点.中国地理信息大会召开--近日,资本

极客化国际化90后创业生态:VC欣赏、家人是阻力

"90后"创业群体能在短时间内迅速崛起,与教育生态的变化密切相关 90后开始登台季逸超,Peak Ji,1992年北京生人,曾在北大附中读书时单独一人做出猛犸浏览器.在大学参加的一次活动中,本不想创业的他,没能抵挡住红杉资本合伙人周逵"诱惑",后获得徐小平和红杉资本投资,成立了Peak Labs实验室.有着高知父母的他是典型的"90后技术宅",从小学就开始研习编程,后来推出的猛犸浏览器从设计到美工.开发.测试.运营等工作,全部由他一人独立完成,他

FROONT在线可视化响应式网页设计工具

  Froont是一个允许设计师在线设计响应式网页的工具,不需要程序员介入的设计编程工具,为设计师们提供了可视化的在线网页设计环境,绝对是响应式网页设计的利器.如果你还在为用PS画出网站在不同设备上的 demo 图,并和攻城师苦苦兼容各浏览器而懊恼的话,来试试Froont吧! 制作过程中,Froont会根据你的网页将呈现的设备:比如手机.平板.笔记本或者是宽屏电脑,自动调整页面布局,适应各个块之间的相对位置. 嗯,如果你有神马不懂的,可以看首屏那个视频,戳 Watch video 即可,了解后再