Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change localization on the fly SwiftUI

Tags:

ios

swift

swiftui

How can I change the localization of the App on the fly in SwiftUI?

I think we can use below code, but we should find SwiftUI approach.

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: "")
}}
like image 284
Tikhonov Aleksandr Avatar asked Nov 02 '19 16:11

Tikhonov Aleksandr


People also ask

How do you do localization in SwiftUI?

Exporting localizations Follow the steps below. In the Project navigator, choose the project, then Editor → Export for Localization. In the dialog box, enter a folder name, select a location where you want it exported, and uncheck English because we do not want to translate that, and finally, click Export.

How do I get localized string in SwiftUI?

In your project settings, go to Build Settings and search for Use compiler to Extract Swift Strings. Make sure to search All settings, not just the Basic ones. Change the value of this setting to Yes. In Xcode, go to Product ▸ Export Localizations….

How do I change localization in Xcode?

To do this, in Xcode, select Product > Scheme > Manage Schemes ... Then in the Run/debug tab, change the "Application Language" to your desired language. And now every time you build and run your app from Xcode, it will use that language as the preferred language.

What is localized string SwiftUI?

LocalizedStringKey is a special type that signals SwiftUI to look up localized strings in your bundle. Use it in custom SwiftUI views to make them ready for localization. Enable the "Use Compiler to Extract Swift Strings" build setting to extract LocalizedStringKeys from code when exporting for localization in Xcode.


1 Answers

First of all, we should create 2 Localizable.strings files, in my case it's en and ru.

And we should store our current language object, I choose store it property in UserSettings like ObservableObject

class UserSettings: ObservableObject {

    @Published var lang: String = "ru"

    var bundle: Bundle? {
        let b = Bundle.main.path(forResource: lang, ofType: "lproj")!
        return Bundle(path: b)
    }
}

We can use this settings object like .environmentObject() in SceneDelegate.swift, so every view in hierarchy will be updated.

var settings = UserSettings()
// ...
= UIHostingController(rootView: contentView.environmentObject(settings))

In View we can get desirable behaviour, note we should specify bundle in Text initialization.

struct ContentView: View {

    @EnvironmentObject var settings: UserSettings

    var body: some View {
        VStack {
            Text("App", bundle: settings.bundle)
        }
    }
}

And now I can change the language on someplace in the app, here is just sample loop example, you can call this function changeLanguage() in the of scene(_ scene:, willConnectTo:, options connectionOptions:) and every 3 seconds language will be changed.

func changeLanguage() {
    print(#function)
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        self.settings.lang = self.settings.lang == "ru" ? "en" : "ru"
        self.changeLanguage()
    }
} 
like image 171
Tikhonov Aleksandr Avatar answered Oct 15 '22 11:10

Tikhonov Aleksandr