关于我:大厂摸鱼 + 业余独立开发,之后会输出深度技术文章 + 独立开发技巧
我的往期技术文章合集:RickeyBoy - Gitbub
我的独立开发 App:iColors - 设计灵感 配色助手
上一篇:
独立开发之 App 国际化全步骤(三):Core Data 模型升级
独立开发之 App 国际化全步骤(四):Core Data 模型解析
🎯 App 内语言环境搭建
当我们做完上面的一切操作之后,App 目前看起来已经大体上适配了国际化了,我们可以直接看下效果。
修改默认语言
目前我们可以通过直接设置 App 的默认语言,来查看多语言的效果。可以在真机的设置页面,进行修改:
当然,如果是通过 Xcode 直接进行测试,可以通过修改 Scheme 中的 App Language 设置,来选择默认的语言:
如果是通过 SwiftUI Preview,可以这样快速测试多语言:
Swift
CustomView()
.environment(.locale, .init(identifier: "en")) // use English
.environment(.locale, .init(identifier: "zh-Hans")) // 使用中文
iOS 中的语言体系
再进行接下来的内容之前,我们需要先了解一下 iOS 中的语言体系。在上面的代码中,注意到我们使用了语言代码 "zh-Hans" 和 "en" 指定对应的语言,来调整 SwiftUI Preview 中需要展示的语言。那么这里的代码到底是什么意思?
Information about linguistic, cultural, and technological conventions for use in formatting data for presentation.
首先我们需要知道,iOS 中使用 Locale 来记录语言和地区信息。比如 Locale 中,有几个属性,我们可以获取到对应的信息:
language: Locale.Language
:语言信息,中文、英语等currency: Locale.Currency?
:货币信息,人民币、美元、欧元等region: Locale.Region?
:地区,中国内地,香港,美国等
那么如何初始化一个 Locale 类型呢?一种最简单的方法,就是通过 identifier 来直接创建,比如 "zh-Hans" 就代表简体中文,而 "en" 就代表英文,更多的还有 "fr" 代表法语等等,详细的对应关系可以参考 ioslocaleidentifiers - Github
支持 App 内语言选择
目前语言选择的逻辑有两个主流的方式,一个是直接在 App 内支持语言选项,另一个是不支持 App 内选择语言,而是直接使用设置中选中的语言。
其实两种方式并没有非常明显的优缺点,支持 App 内切换的话可能灵活一点,但是实现起来相对难一些。可以根据具体 App 诉求进行选择。
我这里主要讲解第一种,即支持语言在 App 内进行选择,我的 App 也是用的这种方式。
要实现这样一个语言选择逻辑,我们要来自定义一下支持的语言。就 iColors App 来说,目前就需要支持三种语言,中文 + 英文,以及使用系统默认的语言。那么通过枚举类型,进行类似于下面的定义即可:
为了方便读者理解,这里罗列的仅是摘要的简单版本。想要详细使用的话,可以参考:LanguageManager-SwiftUI - Github 中的代码
Swift
public enum Languages: String {
case en
case zhHans = "zh-Hans"
case deviceLanguage
}
注意,这里 Languages 类型的 rawValue 其实对应的就是前文提到的 Locale 的语言代码。
与此同时,我们需要通过单例,记录当前选择的语言即可:
Swift
public class LanguageSettings: ObservableObject {
@Published public var selectedLanguage: Languages = .deviceLanguage
}
当然我们还需要一个转换逻辑,将我们定义的 Languages 模型和 iOS 的 Locale 模型关联起来。当我们选择 .deviceLanguage 时,直接使用当前默认的 Locale,否则使用我们选择的 language:
Swift
public class LanguageSettings: ObservableObject {
@Published public var selectedLanguage: Languages = .deviceLanguage
public var locale: Locale {
if selectedLanguage == .deviceLanguage {
return Locale.current
} else {
return Locale(identifier: selectedLanguage.rawValue)
}
}
}
这样我们就完成了一个简单的语言选择逻辑系统,我们只需要在 App 初始化时将 LanguageSettings 的单例初始化并通过 environment 进行环境变量的关联,并且将 locale 信息设置给整个 App 即可,这样我们全局的语言就已经设置好了。
Swift
@main
struct XXXApp: App {
@StateObject var settings = LanguageSettings()
var body: some Scene {
WindowGroup {
ContentView()
.environment(.locale, settings.locale)
.environmentObject(settings)
}
}
}
增加语言选择页面
有了目前的语言管理框架,那么实现一个语言选择页面,就是一个非常简单的逻辑了。我们可以增加一个数组,保存支持的语言:
Swift
public class LanguageSettings: ObservableObject {
...
public let supportedLanguages: [Languages] = [.zh, .en, .deviceLanguage]
}
之后,在语言选择页面,展示所有支持的语言,然后在选择后绑定到当前选择的语言 selectedLanguage
即可:
Swift
struct MeLanguageSelection: View {
@EnvironmentObject var languageSettings: LanguageSettings
var body: some View {
VStack {
// list all choice
ForEach(languageSettings.supportedLanguages, id: .rawValue) { language in
CustomChoiceView(language)
.onTapGesture {
// binding
languageSettings.selectedLanguage = language
}
}
}
}
...
}