Recently I want to add other language support to my app. In WWDC23: Discover String Catalogs, Apple recommended using LocalizedStringResource
to represent and pass around localizable strings. But LocalizedStringKey
is widely used in SwiftUI. For some views, there goes the following error if I directly give LocalizedStringResource
.
struct MyView: View {
var title: LocalizedStringResource
var body: some View {
VStack {
Text(title)
Button(title) { } // Error
.help(title) // Error
}
}
}
Initializer 'init(_:action:)' requires that 'LocalizedStringResource' conform to 'StringProtocol'
I know I can solve it naively by String(localized:)
, but it's wired because of the extra code.
Button(String(localized: title)) { }
.help(String(localized: title))
Should I always do the conversion manually? Is there a better way?
Should I use LocalizedStringKey
to pass the value? But Apple recommends LocalizedStringResource
. What's the trade off?
LocalizedStringResource
is more flexible, you can specify the table name and bundle of the string resource, and even a default value. Quote from the WWDC,
LocalizedStringResource is the recommended type for representing and passing around localizable strings. It not only supports initialization using a string literal, but can also be provided with a comment, table name, or even a default value that's different from the string key.
LocalizedStringKey
is just the key part of a string resource. There is no table name or bundle associated with it. If you do want to specify the table name and bundle for a LocalizedStringKey
, you need to pass those to the Text
initialiser that takes those parameters.
So if you are just writing your own app and you are only ever going to have one table and/or bundle, then using LocalizedStringKey
is not really that different.
For SwiftUI, you should not use String(localized:)
to convert a LocalizedStringResource
. It does not respect SwiftUI's locale
environment value, and Text
would not display the string as markdown.
You should just create a Text
out of the LocalizedStringResource
:
struct MyView: View {
var title: LocalizedStringResource
var body: some View {
VStack {
Text(title)
Button {
} label: {
Text(title)
}
.help(Text(title))
}
}
}