Swift学习15:国际化/多语言适配

张建 lol

前言

项目开发中不同语言环境需要进行多语言适配,例如:中文、英语、法语、俄语、葡萄牙语等

  • 纯代码界面开发时,直接添加本地化语言文件,并针对键值对获取即可

下面我们来介绍如何国际化:

全局添加需要适配的多语言

PROHECT -> Info -> Localizetions 下:选择 + 号添加:

Chinese,Simplified:中文简体
Chinese,Traditional:中文繁体
English - Development Localization:英语
French(fr):法语
Russian:俄语
Arabic:阿拉伯语

添加完成之后的效果:

细心的朋友会发现如今 English 后面是 1 File Localized,这是因为 英语 是系统默认加入的,并且同一时刻为 Main.storyboardLaunchScreen.storyboard 设置了多语言

纯代码本地化

  1. 创建本地化文件

默认文件名为 Localizable ,不要去修改

  • 点击 Next,Save As:Localizable

Localizable.strings 就是你需要的本地化文化

  • 关联对应的本地化语言

点击右侧的 Localizable,关联本地化语言

  • 勾选需要关联的本地化语言,全部勾选

  1. 在本地化文件中设置 Key-Value

注意:不要忘记行末的 ;

分别在对应的本地化语言文件中,设置不同的 Key-Value

  1. 调用本地化
  • 使用 NSLocalizedString 函数来访问 Localizable.strings 资源文件

  • NSLocalizedString 函数第一个参数为对应的 键名,第二个是自定义的说明,给开发或翻译人员看的。

1
2
3
// 调用字符串对应的本地化符号
let title = NSLocalizedString("title", comment: "title")
MyLog(message: title)

这种设置完之后仅仅能让应用随系统的语言进行切换,而用户不能手进行切换

图片本地化

  1. 选中需要本地化的图片,同上面一样点击 Localize... ,创建本地化 图片资源文件

  1. 关联你需要本地化的语言

  1. 图片 Show In Finder,可以看到在 中文和英文资源下都有这个图片,把需要替换的图片换掉即可

  1. 图片使用和平常一样
1
let img = UIImage(named: "loading.png")

App 名称的 本地化

  1. 要实现应用名称根据语言环境显示不一样的名称,只需要创建 InfoPlist.strings 文件,创建 InfoPlist.strings 并关联语言

  1. 获取info.plist中的key

点击 Infoplist 右键选择 Open As -> Source Code,查看我们所要获取权限的原始key。

新版Xcode获取不出来数据不用急,去代码中将info打印出来,拿到key效果一样。

1
2
let infoPlist = Bundle.main.infoDictionary
MyLog(message: infoPlist)
  1. 本地化文件中,对key-value进行配置
1
2
3
4
5
// Chinese,Simplified
"CFBundleDisplayName" = "中图云书房"

// English
"CFBundleDisplayName" = "SRSF"
  1. 运行App,然后切换手机语言为英文,会发现软件名称变成了英文

Xcode中切换语言

为了调试国际化,我们除了可以进入 模拟器或真机 切换系统语言,也可以在 Xcode 中配置相关项,使 Debug 环境下运行时预览不同语言和地区 App的界面效果

  1. 选择 Product -> Scheme -> Edit Scheme -> Run -> Options -> App Language

  1. 切换语言后,运行工程

应用内切换语言

纯代码本地化只能跟随系统进行切换,并不能手动进行切换,下面先介绍一下相关宏

1
2
3
4
5
6
7
8
9
10
11
12
// 尾随系统切换, 多语言文件名称必须是Localizable
NSLocalizedString("title", nil);

// 以下三个都能够手动设置多语言
// 第一个參数:是多语言中的key
// 第二个參数:是多语言文件的名字
// 第三个參数:是对key的自定义的说明,一般传nil
NSLocalizedStringFromTable(@"title", @"Localizable", nil);
// 指定多语言文件名称和bundle
NSLocalizedStringFromTableInBundle(@"title", @"Localizable", bundle, nil);
// 在上面的基础上添加一个默认值的參数
NSLocalizedStringWithDefaultValue(@"title", @"Localizable", bundle, @"label", nil);
  1. Resources -> Show In Finder后,发现每一种语言都有对应的文件目录,后缀是 .lproj

总结:
1、因此 ar.lproj、en.lproj、fr.lproj、ru.lproj、zh-Hans.lproj、zh-Hant.lproj 为我们可以从本地获取到的 语言资源文件
2、在 App 内切换语言的时候,实际上就是获取 语言资源文件Localizable.strings 文件

  1. 将所有的 语言文件 设置成 字符串类型的枚举 并且有初始值 rawValue, 获取 Localizable.strings
  • 获取 某语言 文件的 value值,相应的想要切换语言的话,直接切换 pathForResource 面的 参数 就可以
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 本地化语言类型
enum LocalizedType: String {
// 字符串需要对应本地的国际化文件名 .lproj
case English = "en" // 英语
case ChineseHans = "zh-Hans" // 简体中文
case ChineseHant = "zh-Hant" // 繁体中文
case Russian = "ru" // 俄语
case Frcench = "fr" // 法语
}


// 获取语言文件路径(可以为:en/zh-Hans/zh-Hant/fr/ru 任意一个)
let languageBundlePath = Bundle.main.path(forResource: LocalizedType.English, ofType: "lproj")
// 获取语言文件路径下对应 key 的 value
let value = Bundle(path: languageBundlePath ?? "")?.localizedString(forKey: "title", value: nil, table: "ZJLocalizable")
MyLog(message: value)
  1. 根据上面的思路,我们可以用 NSUserDefaults 缓存当前的 语言,以便 第一次启动程序程序退出去后,下次进入继续使用上次关闭程序的语言。
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 本地化语言类型
enum LocalizedType: String {
// 字符串需要对应本地的国际化文件名 .lproj
case English = "en" // 英语
case ChineseHans = "zh-Hans" // 简体中文
case ChineseHant = "zh-Hant" // 繁体中文
case Russian = "ru" // 俄语
case Frcench = "fr" // 法语
}

// 初始化启动时语言
func initLaunchLanguage() {
// 获取上一次设置的语言
var languageType = kUserDefault.getInfo(key: "appLanguage")
// 如果是第一次启动
if languageType == nil {
// 获取系统第一个首选语言
let systemLanguage = Locale.preferredLanguages.first!
MyLog(message: systemLanguage)
// 赋值给上一次设置的语言类型
if systemLanguage.hasPrefix(LocalizedType.English.rawValue) {
// 英文
languageType = LocalizedType.English.rawValue
}else if systemLanguage.hasPrefix(LocalizedType.ChineseHans.rawValue)
{
// 简体中文
languageType = LocalizedType.ChineseHans.rawValue
}else if systemLanguage.hasPrefix(LocalizedType.ChineseHant.rawValue)
{
// 繁体中文
languageType = LocalizedType.ChineseHant.rawValue
}else if systemLanguage.hasPrefix(LocalizedType.Frcench.rawValue) {
// 法文
languageType = LocalizedType.Frcench.rawValue
}else if systemLanguage.hasPrefix(LocalizedType.Russian.rawValue) {
// 俄文
languageType = LocalizedType.Russian.rawValue
}else {
// 其他语言
languageType = systemLanguage
}
}
// 缓存语言
kUserDefault.saveInfo(value: languageType!, key: "appLanguage")
// 设置bundle
setCurrentBundle()
}

注:
每次设置完语言,我们跟要更新一下 bundle,以便随时获取 key-value

  1. 接下来,我们要根据缓存的语言来获取本地语言资源文件,赋值给一个全局的 bundle,以便随时可以通过 bundle 来拿到具体语言文件下的 key-value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 设置bundle
func setCurrentBundle() {
// 拿到当前语言
let currentLanguageType = kUserDefault.getInfo(key: "appLanguage") as! String
// 获取本地语言资源路径
let languageBundlePath = Bundle.main.path(forResource: currentLanguageType, ofType: "lproj")
// MyLog(message: languageBundlePath)
guard languageBundlePath != nil else {
return
}
// 获取 bundle
let languageBundle = Bundle(path: languageBundlePath!)
guard languageBundle != nil else {
return
}
// 赋值给全局的 bundle
currentBundle = languageBundle
// MyLog(message: currentBundle)
}
  1. 根据 key 获取 value
1
2
3
4
5
6
// 获取要显示的文本
func getLanguageValueWithKey(key: String) -> String {
let bundle = LocalizableManager.sharedManager.currentBundle
let value = bundle?.localizedString(forKey: key, value: nil, table: nil)
return value ?? ""
}
  1. 至此,我们的 App内+系统 切换国际化语言,大功告成!!!
  • Post title:Swift学习15:国际化/多语言适配
  • Post author:张建
  • Create time:2023-03-15 06:27:39
  • Post link:https://redefine.ohevan.com/2023/03/15/Swift/Swift学习15:国际化-多语言适配/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.