如何动态更改 SwiftUI 本地化

Tik*_*der 8 ios swift swiftui

如何在 SwiftUI 中动态更改应用程序的本地化?

我认为我们可以使用下面的代码,但我们应该找到 SwiftUI 方法。

func localized(_ lang:String) -> String {

    let path = Bundle.main.path(forResource: lang, ofType: "lproj")
    let bundle = Bundle(path: path!)

    return NSLocalizedString(self, tableName: nil, bundle: bundle!, value: "", comment: "")
}}
Run Code Online (Sandbox Code Playgroud)

Tik*_*der 7

首先,我们应该创建 2 个Localizable.strings文件,在我的例子中是enru

我们应该存储我们当前的语言对象,我选择将其属性存储在UserSettingslike中,我们也可以在初始化变量时ObservableObject使用以保留所选的语言@AppStoragelang

class UserSettings: ObservableObject {
    
    @Published var lang: String = "ru"
    
    var bundle: Bundle? {
        let b = Bundle.main.path(forResource: lang, ofType: "lproj")!
        return Bundle(path: b)
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以像.environmentObject()in一样使用这个设置对象SceneDelegate.swift,因此层次结构中的每个视图都将被更新。

var settings = UserSettings()
// ...
= UIHostingController(rootView: contentView.environmentObject(settings))
Run Code Online (Sandbox Code Playgroud)

为了View获得理想的行为,请注意我们应该bundleText初始化中指定。

struct ContentView: View {
    
    @EnvironmentObject var settings: UserSettings
    
    var body: some View {
        VStack {
            Text("App", bundle: settings.bundle)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以更改应用程序中某个位置的语言,这只是示例循环示例,您可以changeLanguage()在 of 中调用此函数scene(_ scene:, willConnectTo:, options connectionOptions:),并且每 3 秒语言就会更改一次。

func changeLanguage() {
    print(#function)
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        self.settings.lang = self.settings.lang == "ru" ? "en" : "ru"
        self.changeLanguage()
    }
} 
Run Code Online (Sandbox Code Playgroud)


小智 5

@Tikhonov Alexander 这是否意味着必须在每个 Text 元素中指定包标识符?是否有一种简单的方法可以为所有文本元素设置此设置,或者是否有另一种方法可以动态更改区域设置标识符?目前我正在通过更改区域设置来测试其他语言的预览。

    static var previews: some View {
        TestView()
            .environment(\.locale, Locale(identifier: "ru"))
    }
Run Code Online (Sandbox Code Playgroud)