I want to make a modern language change, but I don’t know how to restart the application, or rather I know, but for me it works with an error and not the way I want. In other applications I saw that the language is updated without leaving the application, the slider is just spinning and that’s it, the language replaced. How to achieve this in SwiftUI?
This is how I run the application:
import SwiftUI
@main
struct MyApp_UkraineApp: App {
@StateObject var appSettings = AppSettings()
var body: some Scene {
WindowGroup {
MainMenuView()
.environmentObject(appSettings)
}
}
}
This is how I change languages:
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
}
}
I get this error, I know why it appears, but I don’t know how to fix it:
Thread 1: Fatal error: No ObservableObject of type AppSettings found. A View.environmentObject(_:) for AppSettings may be missing as an ancestor of this view.
But the main question is how to make sure that there is a modern language update without restarting the application?
You can put
environment(\.locale, ...)
at the root of your app to set language.The environment is not directly settable though, so you will need to store the setting somewhere (in an
@Observable
orObservableObject
).When you want to change the language:
See the Observation migration guide for how to do this with
ObservableObject
.