NEW: Learn to build the incredible iOS 15 Weather app today! >>

SOLVED: How to localize Text() inside a List?

Forums > SwiftUI

Good evening, I have created a test project at Github showing my problem:

screenshot

It displays a list of games in the ContentView.swift:

List($vm.currentGames, id: \.self) { $gameNumber in
    NavigationLink(
            destination: GameView(gameNumber: gameNumber)
        ) {
        Text("game-number #\(gameNumber)")
    }
}

which is coming from the GamesViewModel.swift:

class GamesViewModel: ObservableObject /*, WebSocketDelegate */ {
    @Published var currentGames: [Int] = [20, 30]
    @Published var displayedGame: Int = 0

And for localization in DE, EN, RU I have added Localizable.strings:

"app-title" = "Wähle ein Spiel!";
"update-games" = "Spiele erneuern";
"join-random-game" = "Zufallsspiel beitreten";
"game-number #%d" = "Spiel #%d";

If you look at the above screenshot, you will see that the first 3 entries are localized properly, but the last one game-number #%d is not working (marked by the red arrow in the screenshot)

Is it because the Text is inside of a List and is updated dynamically?

Best regards Alex

   

Trying usng the placeholder %lld instead of %d.

   

Thanks for replying! Here the things I have already unsuccessfully tried:

  • Replaced %d by %lld
  • Removed the # char on both sides
  • Replaced game-number by just game
  • Tried to use Text(LocalizedStringKey("game-number #\(gameNumber)"))
  • Tried to use Text(String(format: NSLocalizedString("game-number #%d", comment: ""), gameNumber)) (always shows EN)

   

The first three work because Text will automatically look for those keys in Localizable.strings. I've found it to be hit or miss with interpolated strings and struggled with an issue just like yours.

My solution was to write a func that would return the desired string. It didn't feel very SwiftUI-y to me, but it worked, and I needed to move on haha.

func gameNumberTitle(for int: Int) -> String {
  let numberString = String(int)
  let gameNumberTitle = String(format: NSLocalizedString("game-number %@" , comment: ""), numberString)
  return gameNumberTitle
}

In localizable.strings, you'd have:

"game-number %@" = "Spiel #%@";

And you'd use it in your View like:

List($vm.currentGames, id: \.self) { $gameNumber in
    NavigationLink(
            destination: GameView(gameNumber: gameNumber)
        ) {
        Text(gameNumberTitle(gameNumber))
    }
}

   

When you run it in tthe dubug usally get

[strings] ERROR: /*the string*/ not found in table Localizable of bundle CFBundle

Then you should have what the complier looking for?

   

Good evening, no I do not see any bundle related errors, when compiling or when debugging the app.

However, I have now got a good workaround advice at the Stackoverflow:

List($vm.currentGames, id: \.self) { $gameNumber in
    NavigationLink(
        destination: GameView(gameNumber: gameNumber)
    ) {
        Text("game-number #\(String(gameNumber))")
    }
}

And use the string instead of the number in the Localizable.strings:

"game-number #%@" = "Game #%@";
"game-number #%@" = "Spiel #%@";
"game-number #%@" = "Игра #%@";

Best regards Alex

   

As an addition to what @matthewloewen mentioned about interpolated strings being "hit or miss", this is often because we really shouldn't be interpolating strings themselves, but rather Texts. This keeps everything as a LocalizedStringKey.

Text("game-number #\(Text(gameNumber, format: .number))")

This should result in the Localized.strings working correctly. Another benefit to this approach is when you use Export Localizations in Xcode that the compiler can also better identify your LocalizedStringKeys.

1      

Hacking with Swift is sponsored by Sentry

SPONSORED With Sentry’s error and performance monitoring for iOS, you see mobile vitals that actually matter, can solve any latency issues quickly, and learn how each release is performing over time.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.