如何在不将应用程序留在 SwiftUI 上的情况下更改语言?

How to change the language without leaving the application on SwiftUI?

提问人:Oleksii Ruban 提问时间:10/22/2023 最后编辑:soundflixOleksii Ruban 更新时间:10/22/2023 访问量:155

问:

我想进行现代语言更改,但我不知道如何重新启动应用程序,或者更确切地说,我知道,但对我来说,它有错误,而不是我想要的方式。在其他应用程序中,我看到语言在不离开应用程序的情况下进行了更新,滑块只是在旋转,仅此而已,语言被替换。如何在 SwiftUI 中实现这一点?

这是我运行应用程序的方式:

import SwiftUI

@main
 struct MyApp_UkraineApp: App {
    @StateObject var appSettings = AppSettings()

    var body: some Scene {
        WindowGroup {
            MainMenuView()
                .environmentObject(appSettings)
        }
    }
}

这是我更改语言的方式:

import SwiftUI

struct MainMenuView: View {
    
    @EnvironmentObject private var appSettings: AppSettings
        
    var body: some View {
                HStack {
                    Button("Ukraine") {
                        Language.selected = .ukraine
                        resetApp()
                    }
                    Button("English") {
                        Language.selected = .english
                        resetApp()
                    }
                }
    
    func resetApp() {
        if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
            if let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate {
                windowSceneDelegate.window??.rootViewController = UIHostingController(rootView: MainMenuView())
                }
            }
        }
    }
}

enum Language: String, CaseIterable {
    case english, ukraine

    var code: String {
        switch self {
        case .english: return "en"
        case .ukraine: return "uk"
        }
    }

    static var selected: Language {
        set {
            UserDefaults.standard.set([newValue.code], forKey: "AppleLanguages")
            UserDefaults.standard.set(newValue.rawValue, forKey: "language")
        }
        get {
            return Language(rawValue: UserDefaults.standard.string(forKey: "language") ?? "") ?? .english
        }
    }

    static func switchLanguageBetweenEnglishAndGerman() {
        selected = selected == .english ? .ukraine : .english
    }
}

我收到这个错误,我知道它为什么会出现,但我不知道如何解决它:

线程 1:致命错误:未找到 AppSettings 类型的 ObservableObject。AppSettings 的 View.environmentObject(_:) 可能缺少作为此视图的祖先。

但主要问题是如何确保在不重新启动应用程序的情况下进行现代语言更新?

iOS 的 swift iPhone 的 swiftUI iOS16

评论

0赞 lorem ipsum 10/22/2023
不要使用 rootViewController,这违背了 SwiftUI 的模式,你正在破坏环境

答:

2赞 Sweeper 10/22/2023 #1

您可以将 IN 放在应用的根目录下来设置语言。environment(\.locale, ...)

但是,环境不可直接设置,因此您需要将设置存储在某个位置(在 或 中)。@ObservableObservableObject

@Observable
class LanguageSetting {
    // initialise this from UserDefaults if you like
    var locale = Locale(identifier: "en")
}
// in your App conformance
@State var languageSettings = LanguageSetting()

var body: some Scene {
    WindowGroup {
        ContentView()
            .environment(languageSettings)
            .environment(\.locale, languageSettings.locale)
    }
}

当您想要更改语言时:

@Environment(LanguageSetting.self) var languageSettings

var body: some View {
    Button("Chinese Simplified") {
        // code to update user defaults omitted...

        languageSettings.locale = Locale(identifier: "zh-Hans")
    }
}

有关如何使用 执行此操作,请参阅观察任务迁移指南ObservableObject

评论

0赞 Oleksii Ruban 10/23/2023
为什么此代码不更改此行的语言?语言随处可见,但基于语言的单词集不会改变。Locale.preferredLanguages.first?.starts(with: "uk") == true ? WordsData().ukraineWords : WordsData().englishWords
0赞 Sweeper 10/23/2023
@OleksiiRuban我很确定你的应用程序无法更改。它基于用户在设置应用中的设置。不如也把环境也用进去怎么样?Locale.preferredLanguageslocale
0赞 Oleksii Ruban 10/23/2023
我正在考虑这个问题,我希望用户在首次启动应用程序时从手机上安装的语言开始。为此,我使用以下代码: 但是现在我不知道如何设置显示哪些单词的条件,因为我的标识符是“auto”,而不是“en”或“uk”。@AppStorage("local") var localeIdentifier: String = "auto" var locale: Locale { get { if localeIdentifier == "auto" { return Locale.current } else { return Locale(identifier: localeIdentifier) } } set { localeIdentifier = newValue.identifier } }
0赞 Sweeper 10/23/2023
@OleksiiRuban 这与什么关系?无论如何,不仅仅是当它是 时,还要将 设置为 。如果您仍然有问题,我建议您发布一个新问题。请记住包括一个最小的可重现示例preferredLanguagesreturn Locale.current"auto"AppStorageLocale.current.identifier
0赞 Oleksii Ruban 10/23/2023
我会尽力做到这一点,非常感谢您的帮助。