2 min read

How to localize the strings as parameter in SwiftUI

Xcode 15 introduces Localizable.xcstrings, greatly enhancing the localization development experience. By unifying the automatically generated content of Localizable.xcstrings, developers can easily manage the strings that need to be localized.

For SwiftUI applications, common Label/Text/string literals will be automatically retrieved and included in Localizable.xcstrings. However, for some strings that are passed as "arguments," they may not be automatically included in localized strings, leading to translation omissions. This article will introduce a simple method to ensure that strings passed as "arguments" can be correctly localized.

The problem

There is a simple SwiftUI app with a ContentView containing a Text that displays a piece of English text:

struct ContentView: View {
    var body: some View {
      Text("The quick brown fox jumps over the lazy dog")
        .padding()
    }
}

Image.png

After building the project, we can see that the text has been added to the translatable list by checking Localizable.xcstring.

Image.png

Next, let's slightly complicate things by abstracting Text as a component, so that we can make unified UI style adjustments and reuse it.

struct TextComponent: View {

  var content: String

  var body: some View {
    Text(content)
      .padding()
  }
}

struct ContentView: View {
    var body: some View {
      TextComponent(content: "The quick brown fox jumps over the lazy dog")
    }
}

Image.png

Everything looks normal, we have a piece of code that is more structured and easier to extend. However, if we revisit Localizable.xcstring, we will find that the parameter "The quick brown fox jumps over the lazy dog" has disappeared.

Image.png

The solution

According to the content of WWDC23・Session 10155, when a string is passed as a parameter, it cannot be detected and included by Localizable.xcstring. We need to do some minor extra work to handle this situation.

struct TextComponent: View {

  var content: LocalizedStringResource

  var body: some View {
    Text(content)
      .padding()
  }
}

Image.png

Simply change the type of the parameter from a regular String to LocalizedStringResource.

Image.png