SwiftUI - Localization of a dynamic Text

Viewed 3310

I am struggling with the locilization of some of my TextFields. Usually a "normal" localization of a Text() or TextField() works without any problem in my App if the text I want to translate is hardcoded like this:

Text("English Text")

I translate it in my Localizable.strings like this:

"English Text" = "German Text";

Now I want to translate TextFields which are more dynamic, but where I know each possible entry:

                TextField("New note" + (refresh ? "" : " "),text: $newToDo, onCommit: {
                    self.addToDo()
                    self.refresh.toggle()
                })

(The refresh is necessary because of a SwiftUI bug sometimes not showing the placeholder-text again.)

Another example would be:

    func dayWord() -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.timeZone = TimeZone.current
        dateFormatter.locale = Locale(identifier: "de_DE")
        dateFormatter.dateFormat = "EEEE"
        return dateFormatter.string(from: self)
    }

    var day: String {
        return data.date.dateFromMilliseconds().dayWord()
    }

   Text(day.prefix(2))

The Text(day.prefix(2)) has only seven possible states, but I don't know what to write as a key in my Localizable.strings.

2 Answers

Use NSLocalizedString, like

TextField(NSLocalizedString("New note", comment: "") + (refresh ? "" : " "), ...

According to SwiftUI convention, the Text() label is automatically localized only when it has a string "literal". When the text is a variable, you need to use LocalizedStringKey(). Other localizable texts inside Button() or TextField() also require LocalizedStringKey(). So you need to change this to:

Text(LocalizedStringKey(String(day.prefix(2))))

This converts day.prefix(2) into a String, because it is actually a substring, and then calls LocalizedStringKey() to make it localizable. In your Localizable.strings file you could add all 7 possibilities.

"Mo" = "Mo";
"Di" = "Tu"; 
//etc.

but why would you? Instead, use:

dateFormatter.locale = Locale(identifier: Locale.preferredLanguages.first)
...
Text(day.prefix(2)) 

to determine the user's current language and display that. Apple returns the text in the proper language, so this text doesn't need to be localized any further.

TextField() does need localization using LocalizedStringKey():

TextField(LocalizedStringKey("New note") + (refresh ? "" : " "),text: $newToDo, onCommit: {
                    self.addToDo()
                    self.refresh.toggle()
                })

As Asperi points out, for "New note" the same can be accomplished using NSLocalizedString(), which might be better depending on how you like to work. The benefits are: easily adding a comment for the translator, and automatic export into the xliff when you choose Editor -> Export for localization…

By contrast, SwiftUI's LocalizedStringKey() requires you to manually add strings to the Localizable.strings file. For your day.prefix(2) example, I think it would make more sense to get the user's preferred language and display the localized date directly.

Related