Plurals localization in SwiftUI Previews. Bugs explained

Dmitriy Kalachniuk
3 min readNov 26, 2020

Well, I’ve read so far a lot of stories about how quickly test localization with SwiftUI Previews (here, here and here). Works great!

import SwiftUIstruct ContentView: View {var body: some View {
Text("item")
}
}
struct ContentView_Previews: PreviewProvider {static var previews: some View {
ForEach(Locale.all, id: \.identifier) { locale in
ContentView()
.previewLayout(PreviewLayout.sizeThatFits)
.padding()
.environment(\.locale, locale)
.previewDisplayName(Locale.current.localizedString(forIdentifier: locale.identifier))
}
}
}
extension Locale {
static let all = Bundle.main.localizations
.map(Locale.init)
.filter { $0.identifier != "base" }
}
Preview of localization with SwiftUI Previews

But lets go deeper…

So far it works great with simple localization keys. But how is it going with plurals localization?

We add Localizable.strigsdict to the project with following content for english and russian languages:

English Localizable.stringsDict
Russian Localizable.stringsDict

If you are not familiar enough with localizable stringsdict you can find nice explanation here.

Now we change the code of our content view — we will use Stepper for quick test

struct ContentView: View {

@State private var number: UInt = 1
private var pineapplesText: String {
String.localizedStringWithFormat(NSLocalizedString("pineapples", comment: ""), number)
}
var body: some View {
VStack {
Stepper(pineapplesText, onIncrement: {
number += 1
}, onDecrement: {
if number > 0 {
number -= 1
}
})
.background(Color(.systemBackground))
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {static var previews: some View {
ForEach(Locale.all, id: \.identifier) { locale in
ContentView()
.previewLayout(PreviewLayout.sizeThatFits)
.padding()
.environment(\.locale, locale)
.previewDisplayName(Locale.current.localizedString(forIdentifier: locale.identifier))
}
}
}
extension Locale {
static let all = Bundle.main.localizations
.map(Locale.init)
.filter { $0.identifier != "base" }
}

Cool! 😎 Lets see the result!

Wait, what? Why russian translation has wrong output?
Did I do something wrong?

Let’s check in the simulator. We change system language in schema to Russian and run the build

Russian plural test in

It is working in the simulator!

Russian plural localization

So it looks like a pure Xcode bug 🐛 Unfortunately.

Now let’s add one more language for localization — dutch.

Previews are updated. Now we see 3 views(with wrong plural translations)

Then I remove dutch localization from the project and check that nl.lproj is removed as well

I refresh previews and…

Dutch preview is still there!!! Common Xcode, go home - you are drunk.

Command+Q and open project again to force refresh the previews — still the same! Dutch preview is there.

One more bug 🐛…

The solution that I found to fix this — clean the project. After that I again see 2 previews.

That’s it guys! If you know how to fix plural locazation in Previews — please let me know and thank you for reading!

P.S. Check out my other post and github account with MacOS tool for speeding up your development! Thanks 🙏

--

--