How to Implement Localization in Swift Ui

How to implement localization in Swift UI

When you look at documentation for Text you can see that it takes LocalizedStringKey not a String into its initializer:

init(_ key: LocalizedStringKey, tableName: String? = nil, bundle: Bundle? = nil, comment: StaticString? = nil)

It makes localizing very straightforward. All you have to do is:

  • create a new file of type "Strings File", call it Localizable.strings
  • select the new file and navigate to File Inspector in the right hand side panel and click Localize...
  • go to your project file to the Localizations section and add another language to the list - Xcode will create localization files for you

When you select you Localizable.strings you will see that it contains files for the original language and the language you have just added. That's where you put your translations, i.e. key - localized text pairs.

If you have a text like this is your app:

Text("Hello World!")

You have to now add to your Localizable.strings your translations:

for your base language:

"Hello World!" = "Hello World!";

and for your second language (in this case German):

"Hello World!" = "Hallo Welt!";

To see your previews localised you can define them like this:

struct ContentViewView_Previews: PreviewProvider {

static var previews: some View {
ForEach(["en", "de"], id: \.self) { id in
ContentView()
.environment(\.locale, .init(identifier: id))
}
}
}

SwiftUI localization doesn't work shows only keys Xcode

Make sure you have the Localizable.strings file in your project. There is where LocalizedStringKey looks for the keys/values as a default.

https://developer.apple.com/documentation/swiftui/localizedstringkey

If you want to define a different file use the

Text(LocalizedStringKey, tableName: String?, bundle: Bundle?, comment: StaticString?)

initializer and the tableName should match your .strings file name.

SwiftUI Localization - how to make the UI component and its function the base for localization

Turns out that it is quite easy. All I had to do is provide the optional argument value in the NSLocalizedString.init.

The NSLocalizedString function has the following signature

/// - parameter key: An identifying value used to reference a localized string.
/// Don't use the empty string as a key. Values keyed by the empty string will
/// not be localized.
...
/// - parameter value: A user-visible string to return when the localized string
/// for `key` cannot be found in the table. If `value` is the empty string,
/// `key` would be returned instead.

NSLocalizedString(_ key: String, tableName: String? = nil, bundle: Bundle = Bundle.main, value: String = "", comment: String)

If the value argument is not provided the translation entry after exporting for localization looks as follows:

File.swift

NSLocalizedString("Cancel", comment: "Cancel button")

en.xliff

<trans-unit id="Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Cancel</target>
<note>Cancel button</note>
</trans-unit>

However, if the value argument is provided, the resulting translation entry looks as follows:

File.swift

NSLocalizedString("Navigation.Button.Cancel", value: "Cancel", comment: "Cancel button")

en.xliff

<trans-unit id="Navigation.Button.Cancel" xml:space="preserve">
<source>Cancel</source>
<target>Cancel</target>
<note>Cancel button</note>
</trans-unit>

Localization SwiftUI

You can use LocalizedStringKey:

In your app:

let greeting: LocalizedStringKey = "Greeting"
let text = Text(greeting)

In your English Localizable.strings file:

"Greeting" = "Hello";

In your Spanish Localizable.strings file:

"Greeting" = "Hola";

SwiftUI Localization and Enums

The answer is much simpler than writing extensions and doing complicated work. Instead of writing a static let, when a variable is present you write a static func. This all takes place in the LocalizationString.swift file's enum and looks like this:

static func testText(name: String) -> LocalizedStringKey { LocalizedStringKey("TEST_TEXT \(name)") }

To use this in your view:

Text(LocalizationStrings.testTest(name: varname))

If you need more variables, just add them into the function.

SwiftUI: Variable strings not exported for localization

Ok, so after tinkering with localization some more, I found an approach that works well.

The tutorial I linked to (https://www.ibabbleon.com/swiftui_localization_tutorial.html) does not talk about this, and makes things confusing with LocalizedStringKey and Text(String, comment: String). Some other tutorials also go down this route, but it makes code really ugly because it moves data into Text. So if you want to separate data from the view, you have to include Text (a UI element) in the view model. Alternatively, if you use LocalizedStringKey, you can't include comments for the translator.

Fortunately, there is a much simpler way!

struct ContentView: View {
let normalString = "This is not exported for localization. Good for previews!"
let localizedString = String(localized: "This is exported for localization.", comment: "You can add a comment for the translator, too!")

var body: some View {
VStack {
Text(normalString)
Text(localizedString)
}
}
}

SwiftUI Localization

What you are doing is you are giving back an already interpolated string with %@ to an interpolated string. So the string that you are generating looks like this: "schoolLocation %@ Some Name". You can do it this way:

struct Translation {
struct school{
static func location(name: String): LocalizedStringKey {
return "schoolLocation \(name)"
}
}
}

And then you can use your translation like this:

var location = "Some Name"
.navigationBarTitle(Translation.school.location(name: location))

NSLocalizedString and value with SwiftUI

I have finally found an answer right after posting my question:

// ContentView.swift

Text("3 Tomatoes")
/* or */
Text("\(tomatoes.count) Tomatoes")
/* replaced by */
Text(String(format: NSLocalizedString("%lld text-tomatoes", comment: ""), tomatoes.count))

// Localizable.strings (en)

"%lld text-tomatoes" = "%lld Tomatoes";

It's working like a charm!

Other example: Localization with String interpolation in SwiftUI



Related Topics



Leave a reply



Submit