SwiftUI本地化-应用内切换语言

现在很多App都有提供多种语言,能够让用户选择自己最熟悉的语言不仅会极大提高用户体验,而且还会提升App的质量。本文将会完整的介绍怎么为一个App添加多种语言支持,并且无需重启系统就可以实现应用内切换语言版本,但是不会详细介绍每一种本地化表达式的规则。

添加语言

Project Navigation 中,点击PROJECT ,选择Info 可以在Localizations中进行语言的添加。

点击+,选择需要添加的语言。这里就是告诉iOS我们的App会支持哪些语言。

创建本地化文本映射字符串文件

在iOS中,系统是通过查找键值对的方式实现本地化的,这个映射文件就是字符串文件,类型是.strings,格式如下:

Swift 复制代码
// en
apple = "Apple";
Swift 复制代码
// zh
apple = "苹果";

右键项目目录或command+N 创建文件,选择Strings File ,命名为Localizable. strings

选中目录中Localizable. strings ,点击右边的按钮Localize... ,选择生成Localizable. strings对应的语言文件。由于我这里已经生成好了,不方便截图,直接看最后的生成结果:

然后在对应的文件中创建需要本地化的文本键值对了,注意每一行都要;结束,最后一行也是。

如果en环境的key和value是一样的,那么en的字符串文件内容可以为空。其实到了这一步,我们的App已经完成了本地化支持了,是跟随系统的语言自动适配。

实现应用内切换

如果我们的App有一个设置页面,里面有一个切换语言的功能,我们希望通过切换语言来实时的改变UI上的文本语言,那现在还远远不够。

@EnvironmentObject

@EnvironmentObjectSwiftUI 的一个属性包装器,用于在整个视图层中传递一个遵循ObservableObject协议的对象来共享数据,在这个对象中,如果一个属性用@Published来修饰,当这个属性值发生变化时,所有依赖这个属性的视图都会收到通知并重新渲染。

我们可以通过这个配合修改视图的Locale环境变量来达到应用内动态的切换语言的目的。先定义一个AppState类,用来保存App的状态:

Swift 复制代码
final class AppState: ObservableObject {
    
    @Published var localeIdentifier: String = "en-US"
    
    init() {
        // 获取系统的Locale
        var id = Locale.current.identifier;
        if let identifier = UserDefaults.standard.string(forKey: "locale_identifier") {
            // 使用用户上次的设置。如果用户有选择语言,就要保存起来
            id = identifier
        }
        
        if id.hasPrefix("zh") {
            _localeIdentifier = Published(initialValue: "zh-CN")
        }
    }
}

初始化App时创建AppState,并使用.environmentObject()保存起来,以便其他View通过@EnvironmentObject获取使用:

Swift 复制代码
@main
struct DingsApp: App {
    
    @StateObject private var appState = AppState()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                // ContentView()已经加了Locale环境,这个视图就本地化了
                .environment(\.locale, Locale(identifier: appState.localeIdentifier))
                .environmentObject(appState)
        }
    }
}

如果我们需要对MainView本地化,就需要增加属性AppState ,并使用它的localeIdentifier属性来设置视图的environment,这样当localeIdentifier改变了,视图的locale也会变化,视图就会使用新的locale来渲染:

Swift 复制代码
struct MainView: View {

    @EnvironmentObject private var appState: AppState
    
    var body: some View {
        VStack {
            ...
        }
        .environment(\.locale, Locale(identifier: appState.localeIdentifier))
    }
}

切换语言功能

当用户选择不同的语言时,修改AppStatelocaleIdentifier属性值,并保存到用户数据中:

Swift 复制代码
Button {
    select(for: "zh-Hans")
}
    
private func select(for language: String) {
    let localeIdentifier = (language == "zh-Hans") ? "zh-CN" : "en-US"
    appState.localeIdentifier = localeIdentifier
    UserDefaults.standard.set(localeIdentifier, forKey: "locale_identifier")
}

其他

有一些地方比较特殊,比如通过函数取得的字符串key,数组里面取的字符串key等就无法本地化,例如:

Swift 复制代码
private let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]

// 无法本地化
Text(months[index])

这个时候我们可以通过拓展String,增加一个方法,来手动调用获取不同环境下的值。

Swift 复制代码
extension String {
    func localizedString(identifier: String = "en-US") -> String {
        let language = identifier == "zh-CN" ? "zh-Hans" : "en"
        if let path = Bundle.main.path(forResource: language, ofType: "lproj") {
            if let bundle = Bundle(path: path) {
                return bundle.localizedString(forKey: self, value: self, table: nil)
            }
        }

        return self
    }
}

然后在调用StringlocalizedString方法就可以了。

Swift 复制代码
Text(months[index].localizedString(identifier: appState.localeIdentifier))

另外,还有Date 的格式化也不是使用视图的environment ,而是使用Textformat ,所以对于Date可以这样处理:

Swift 复制代码
Date().formatted(Date.FormatStyle(date: .abbreviated, time: .omitted, locale: Locale(identifier: appState.localeIdentifier)))

好了,就这些了,现在我们的App应该可以很好的实现应用内切换语言了。谢谢支持,原创不易,转载请注明来源。

相关推荐
missmisslulu12 小时前
电容笔值得买吗?2024精选盘点推荐五大惊艳平替电容笔!
学习·ios·电脑·平板
GEEKVIP13 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
GEEKVIP13 小时前
如何在 Windows 10 上恢复未保存/删除的 Word 文档
macos·ios·智能手机·电脑·word·笔记本电脑·iphone
奇客软件14 小时前
iPhone使用技巧:如何恢复变砖的 iPhone 或 iPad
数码相机·macos·ios·电脑·笔记本电脑·iphone·ipad
奇客软件2 天前
如何从相机的记忆棒(存储卡)中恢复丢失照片
深度学习·数码相机·ios·智能手机·电脑·笔记本电脑·iphone
GEEKVIP2 天前
如何修复变砖的手机并恢复丢失的数据
macos·ios·智能手机·word·手机·笔记本电脑·iphone
一丝晨光2 天前
继承、Lambda、Objective-C和Swift
开发语言·macos·ios·objective-c·swift·继承·lambda
GEEKVIP2 天前
iPhone/iPad技巧:如何解锁锁定的 iPhone 或 iPad
windows·macos·ios·智能手机·笔记本电脑·iphone·ipad
KWMax2 天前
RxSwift系列(二)操作符
ios·swift·rxswift
Mamong3 天前
Swift并发笔记
开发语言·ios·swift