前言
对于APP的国际化,大家应该都不陌生,常用的微信、微博、支付宝等应用均支持多种语言(国家数不一定一致)。默认情况下显示语言是跟随系统变化的,而APP内手动修改后不会随系统改变(本地存储偏好)。多语言对于受众不止于中国的APP还是很有必要的,至少同时支持英文,当然不排除只支持英文的国际APP如Instagram。
本文主要对国际化中遇到的问题进行记录与解答,可能在通用熟知的部分会简单描述带过。
新增语言支持设置
注:项目默认开发语言为English英文
添加新语言,项目 -> Project -> Info -> Localizations -> 点击加号添加语言如
简体中文
创建用于项目内自定义需要国际化的字符串集Localizable.strings,这里面放除info.plist以外的所有国际化
在iOS下新建Strings File类型并命名为Localizable
创建配置info.plist国际化的字符串集InfoPlist.strings,此文件放App名字、info.plist里面参数国际化
参照上一步在iOS下新建String File类型并命名为InfoPlist
分别对Localizable.string和InfoPlist.string添加支持多语言,任意选择一个语言选择Localize,然后把所有支持的语言勾上
纯代码定义不同语言内容时,需要在引号后面加分号,不然编译会通不过
通用国际化(项目内自定义显示文字)
在每个语言的strings文件中添加需要支持国际话的说明,每个语言里面的key需要一样。我的处理方法是定义了一个专门放key的一个常量定义文件,并且定义和key一致,方便在纯代码国际化的时候调用
1 | // MARK: Common |
然后在该文件里面同时定义了一个方便国际化的全局使用函数Localize,即国际化使用纯代码需要用的函数,我这里没有传comment,有需求的可以自己更改
1 | func localize(key: String) -> String { |
使用:在代码中需要国际话的地方,调用localize函数即可,传入自己定义的key,如
1 | assetsLbl.text = localize(key: TitleTotalAssets) |
配置相关国际化(如隐私权限,App名称等info.plist)
APP名字国际化
在InfoPlist.strings各个文件下添加CFBundleDisplayName=”对应语言的APP名字”;
1
CFBundleDisplayName = "对应语言的APP名字";
相机权限
1
NSCameraUsageDescription = "对应语言的相机权限说明";
相册访问权限
1
NSPhotoLibraryUsageDescription = "对应语言使用相册权限说明";
相册存储权限
1
NSPhotoLibraryAddUsageDescription = "对应语言相册存储权限说明";
蓝牙访问权限
1
NSBluetoothPeripheralUsageDescription = "对应语言蓝牙访问权限说明";
推送国际化
根据苹果官方文档介绍,提供了两种方案,一种是服务器做国际化,一种是APP本地做国际化,我这里选择的是APP做国际化,服务器配合。APP做推送国际化,用到loc-key
和loc-args
,将他们通过payload的方式推送到手机上,以个推为例,服务器需要通过setAPNInfo(Payload payload)将这些信息推到客户端。
我们的推送只包含了Title和一条基本信息,也就是最基本的推送信息展示,所以和服务器商量好分别定义好Title、body的key和body的args,定义如下:
1 | "title-loc-key" : "NOTIFICATION_TITLE", // 这个key将会在Localizable.strings需要国际化的通知标题。内容自己定义,只要和服务器商量好 |
国际化示例:
英文
1 | "NOTIFICATION_TITLE" = "Transaction confirmed"; |
中文
1 | "NOTIFICATION_TITLE" = "交易已确认"; |
应用内切换
原理,重新加载本地语言文件,即在应用内切换语言后,改变该APP的语言,然后重新加载对应语言包。
当前APP的语言偏好保存在本地,key为AppleLanguages,应用内切换时可以更改该值,启动时可以通过该key获取。
切换语言包,可以写一个集成Bundle的类重写localizedString方法,以便重新加载,代码如下
1 | class ExBundle: Bundle { |
1 | extension Bundle { |
在APP启动时,调用一次onLanguage swizze使用ExBundle
闪烁问题解决:将切换语言VC添加到根navigation中,代码如下:
1 | guard let nav = StoryboardSegue.sceneNamed("RootNav@Main") as? UINavigationController else { return } |
其他(如阿拉伯语布局)
当语言为阿拉伯语时,系统布局会自动为从右到左排列和显示,包括返回。前提是你的布局严格按照autolayout来做,如果发现任然是从左到右的,那可能是你的布局约束存在问题。如果有些控件显示,如光标显示没有颠倒,这个时候就需要代码手动设置,任何你想要设置的控件都可以使用以下代码实现:
1 | view.semanticContentAttribute = .forceRightToLeft |