I'm trying to change a locale on a fly, but it doesn't work for interpolated strings:
//this struct is mandatory
struct Constants {
static let download = LocalizedStringResource("Download", table: "General")
static let items = LocalizedStringResource("%lld item", table: "General")
}
struct ContentView: View {
@State private var language: String = "uk"
var body: some View {
ZStack {
Rectangle().foregroundStyle(.white)
VStack {
Text(Constants.download)
Text(String(format: String(localized:Constants.items), 13))
}
.padding()
}
.onTapGesture {
language = (language == "en") ? "uk" : "en"
}
.environment(\.locale, .init(identifier: language))
.id(language) //try to force reload UI..
}
}
Result:
Also, please note, if you change a scheme language parameter:
Then it will load string and interpolation will work for selected language:
But after that, still, changing a locale doesn't update language value with interpolation.
Looks like a SwiftUI internal logic problem? Or is there maybe could be some workaround for this?
My General.xcstrings translated:
This happens because String(localized:)
doesn't care about SwiftUI's environment. It only looks at the locale of the LocalizedStringResource
, which will be the system locale.
Rather than static let
s in Constants
, you should make the interpolated strings functions, so that you can format them in place:
static func items(_ n: Int) -> LocalizedStringResource {
LocalizedStringResource("\(n) Items", table: "General")
}
Usage:
Text(Constants.items(13))
This work because you are directly giving the resource to Text
, and Text
can localise it using SwiftUI's environment.
I'm not sure why you are using LocalizedStringResource
instead of LocalizedStringKey
. Unless you do need specific functionalities from LocalizedStringResource
, use LocalizedStringKey
instead.