SwiftUI版通知栏应用开发(4) ——多语言本地化适配
开发多语言版本的 APP,估计是大家希望的,尤其对于 iOS/Mac APP 的开发,上线 App Store 多希望在其它地区也能使用,所以今天主要想学习怎么基于 SwiftUI 做一些文本和字符串文字多语言化。
相信市面上不少这样的文章可供参考
Project 配置
首先,在 Project Info 选项中,选择 Localization
增加一个「中文」本地化配置,如果你需要其他语言,可以相对应的添加:
接下来,新建对应的 Group
文件夹,如本文的两个 Group
:en.lproj
、zh-Hans.lproj
:
在这两个 Group
里,同时创建同名的 Strings
文件:Localizable
:
代码编写
创建完成之后,我们分别创建一个 Preferences
demo:
在我们的主 View 上引入变量 locale
:
popOver.contentViewController?.view = NSHostingView(rootView: MainView().environment(\.locale, .init(identifier: "en")))
然后创建一个 Text
:
Text("Preferences")
.font(.customf(22))
.padding(.bottom, 10.0)
刚开始我们定义的是 en
,执行看看效果:
如果我们改为 zh-Hans
:
MainView().environment(\.locale, .init(identifier: "zh-Hans"))
结果也就不一样了:
Locale 变化功能
基本功能实现了,接下来就是设置一个开关来变化 Locale 了。
首先,创建一个 Picker
:
Section(header: Text("localization")) {
Picker("", selection: $localeViewModel.localeString) {
ForEach(LocaleStrings.allCases) { localeString in
Text(localeString.rawValue)
.tag(localeString.suggestedLocalication)
}
}
.pickerStyle(SegmentedPickerStyle())
}
其中,我定义两个 enum
来做选择的类型:
enum Localication: String, CaseIterable, Identifiable {
case zh_Hans = "zh-Hans"
case en = "en"
var id: String { self.rawValue }
}
enum LocaleStrings: String, CaseIterable, Identifiable {
case zh_Hans = "中文"
case en = "English"
var id: String { self.rawValue }
}
extension LocaleStrings {
var suggestedLocalication: Localication {
switch self {
case .zh_Hans: return .zh_Hans
case .en: return .en
}
}
}
这个好理解,因为显示的 String 和提供给 locale 的字符串不一致,如显示的是「中文」,提供给 locale 的是 zh-Hans
,这里我借助 suggestedLocalication
做桥梁转换。
最后,我们创建一个 Combine ViewModel 变量 localeString,以供实时变化改变本地化字符串内容。
class LocaleViewModel: ObservableObject {
@Published var localeString: Localication
}
最后,只需要在具体的 View 里加入 ViewModel 订阅变量 localeString 的更新:
// ContentView.swift
import SwiftUI
struct ContentView: View {
@ObservedObject private var timerViewModel: TimerViewModel
@ObservedObject private var localeViewModel: LocaleViewModel
init(timerViewModel: TimerViewModel, localeViewModel: LocaleViewModel) {
self.timerViewModel = timerViewModel
self.localeViewModel = localeViewModel
}
var body: some View {
Text("localization")
.font(.customf(14))
.padding()
.environment(\.locale, .init(identifier: localeViewModel.localeString.rawValue))
}
}
好了,代码编写完毕,我们运行看效果:
小结
基本跑通本地化多语言适配流程,接下来就是不断增加新的语言和翻译工作。
未完待续