I'd like to create a custom SwiftUI view that supports extracting its title string along with the localization comment into a string catalog. Like the SwiftUI Text
view does. I have a view with an init similar to the localization init of Text. But it looks like I'm missing something obvious.
Two questions:
-
How do I get the actual localized string using a
LocalizedStringKey
? -
Why is the comment not picked up and added to the string catalog?
// 1) My custom view with localization support: // I'd like to build a view which supports extraction of strings into a string catalog like the SwiftUI `Text` view does. struct MyLocalizableView: View { private var localizedTitle: String init (_ titleKey: LocalizedStringKey, table: String? = nil, bundle: Bundle? = nil, comment: StaticString? = nil) { // PROBLEM I: // The following line does not work. I is a fantasy call. It depicts my idea how I would expect it to work. // My question is: How do I get the actual localized string using a `LocalizedStringKey`? self.localizedTitle = String(localizedKey: titleKey, table: table, bundle: bundle, comment: comment) } var body: some View { // At this point I want to do an operation on an actual string and not on a LocalizedStringKey. So I can't just pass the LocalizedStringKey value along. // Do `isEmpty` or some other operation on an actual string: if localizedTitle.isEmpty { Text("Show one thing") } else { Text("Show another thing") Text("** \(localizedTitle) **") } } } // 2) The call site: struct ContentView: View { var body: some View { // PROBLEM II: "My title key" is picked up and is extracted into the string catalog of the app. But the comment is NOT! MyLocalizableView("My title key", comment: "The title of the view...") .padding() } }
Hi there! I'll answer the second question first.
The comment is not picked up because:
- the string extraction process doesn't look at plain
String
parameters, unless they are declared viaString(localized:)
- the
comment
is in a separate parameter from thetitleKey
(i.e. from yourLocalizedStringKey
), so the string extraction process doesn't know to associate the two
You can associate the key and the comment by using a LocalizedStringResource
instead, which has the bundle, table, and comment baked into the type. The string extraction process looks at these and knows to associate the comments with the keys. For example:
struct MyLocalizableView: View { let localizedTitle: LocalizedStringResource var body: some View { Text(localizedTitle) } } struct ContentView: View { var body: some View { MyLocalizableView(localizedTitle: LocalizedStringResource("My title key", comment: "My comment")) } }
You can read up on LocalizedStringResource
on its documentation page.
Another alternative to this, of course, would be to add the comments manually inside of your String Catalog (or .strings
and .stringsdict
files), instead of in code.
As for your first question: you can evaluate the contents of a LocalizedStringResource
by using the String(localized:)
initializer, like so:
struct MyLocalizableView: View { let localizedTitle: LocalizedStringResource var body: some View { if String(localized: localizedTitle).isEmpty { Text("Show one thing") } else { Text("Show another thing") Text("** \(localizedTitle) **") } } }
Although, depending on your situation, you may want to instead consider making your localizedTitle
a LocalizedStringResource?
instead of a LocalizedStringResource
, and checking to see if the localizedTitle
is nil
.