How to implement localization in Swift UI
Asked Answered
S

8

40

Can anybody help me? I can't find any description of the localization in Swift UI. Can anyone please give advice or better an example of how to localize for example Text()?

Sension answered 27/10, 2019 at 10:4 Comment(0)
C
58

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))
        }
    }
}
Cootie answered 27/10, 2019 at 11:13 Comment(12)
Thanks, it was helpful! But I had some issues because it was several languages already added.Sension
I followed these instructions to the letter and it did not work. I'm running iOS 10.15.1 Beta and Xcode 11.1. Any advice gladly accepted. For now I'm going to assume a glitch in the beta software and not lose any more time on thisTaveras
What exactly was the problem?Cootie
in Localizations.strings (English) "Hello World" = "In English"; in Localizations.strings (French) "Hello World" = "En Francais"; in var body: some View { Text("Hello World") } on screen -> Hello WorldTaveras
@JosephBeuys'Mum I have added info how to run previews in various localised versions. Please let me know if it resolved your issue. ThanksCootie
Hi @LuLuGaGa. I wasn't viewing previews, although I was using the simulator. Just tried on an actual device with the amended preview code (cos: why tf not?) and: same result [sadface]. But thank you anywayTaveras
I found the problem @LuLuGaGa. It transpires that I wasn't following the instructions to the letter, as I said I had. My localisations string file was in a subfolder. Put it at the project level and it works fineTaveras
Have also discovered (I think) that calling the strings file anything other than Localizable means it won't workTaveras
It works. Good answer. But is there a way to make it more simple? Let's say I have many languages and later I will change some base texts in the app. Maintaining this seems complex. Should update every single language and change base text in this file? Isn't there another way? Some dictionary in a spreadsheet or something?Autocrat
I had to wrap the String I pass to Text in an explicit LocalizedStringKey() for this to work. Not sure if I'm doing something wrong.Newmarket
God! @everyone Do not forget to correctly name the file to Localizable.strings !Educe
I distilled all of these instructions for SwiftUI Localization into a tutorial if anyone is interested: ibabbleon.com/swiftui_localization_tutorial.htmlAmenable
A
23

There is a thing you can do wrong that's not made very clear in any explanation I've seen. It turns out that Text("hello") is only interpreted as a localization key if you pass it a literal. If you pass a variable of type String, this doesn't happen. The answer is instead to declare the variable as type LocalizedStringKey.

  Text("hello") //-> implicitly treats string literal as a key; looks up and displays "Hello World!"
  let cap1:String = "hello"
  Text(cap1)   //-> no lookup for explicit String variable; just displays "hello"
  let cap2:LocalizedStringKey = "hello"
  Text(cap2)   //-> looks up explicit LocalizedStringKey value; displays "Hello World!"
Amytal answered 26/5, 2020 at 20:38 Comment(2)
If cap2 has placeholder for dynamic value then how we will pass the value e.g. let cap2: LocalizedStringKey = "hello %@". Display string will "Hello ABC" where ABC is dynamic valueSkit
Thanks a lot man, was already getting frustrated about this and thought there was no solutionLooney
J
7

You can simply wrap the string in LocalizedStringKey before giving it to Text().

Localizable.strings file:

"Dismiss" = "关闭";
"Cancel" = "取消";

SwiftUI view file:

Text(LocalizedStringKey("Dismiss"))
Joacimah answered 12/5, 2020 at 2:8 Comment(1)
Not sure if this was ever necessary. According to Apple's docs: When you use the initializer Text("Hello"), SwiftUI creates a LocalizedStringKey for you and uses that to look up a localization of the Hello string.Glochidiate
S
6

For swift UI file, you just need to insert string key from localization .strings file

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("selectLanguage")
            Text("languagesList")
        }
        
        
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environment(\.locale, .init(identifier: "en"))
    }
}

and this is an example from .strings file

"selectLanguage" = "Select language";
"languagesList" = "Languages list";

result is here:

screenshot

Sension answered 27/10, 2019 at 14:27 Comment(0)
C
6

To localise your app you need:

  1. Use SwiftUI elements like: Text("Nice"). Nice becomes the key in Localizable.strings.
  2. In the cases where text is not in the SwiftUI element needs to use NSLocalizedString.
  3. Select you app target.
  4. Export localisation: Edit -> Export for Localisation...
  5. Give exported files to translator.
  6. Import translations: Edit -> Import Localisations...
Crwth answered 13/2, 2020 at 3:37 Comment(0)
S
2

To use Localazable in SwiftUI, you can perform this way:

import SwiftUI to use LocalizedStringKey in your files

//MARK: - File where you enum your keys to your Localized file
enum ButtonName: LocalizedStringKey {
case submit
case cancel
}

//MARK: - Your Localized file where are your translation
"submit" = "Submit is pressed";
"cancel" = "Cancel";

//MARK: - In your code
let submitButtonName = ButtonName.submit.rawValue
let cancelButtonName = ButtonName.cancel.rawValue

VStack {
Text(submitButtonName)
Text(cancelButtonName)
}
Spoilsman answered 19/2, 2020 at 11:13 Comment(0)
W
0

I created this custom SwiftUI Text

struct Localized: View {
    var text: String
    var arg: Any?
    var body: some View {
        if let arg = arg {
            if let arg = arg as? [Any] {
                Text(String(format: NSLocalizedString(text, comment: ""), arg.compactMap({String(describing:$0)}).joined(separator: " ")).replacingOccurrences(of: "(null)", with: ""))
            } else {
                Text(String(format: NSLocalizedString("\(text) %@", comment: ""), String(describing: arg)))
            }
        } else {
            Text(LocalizedStringKey(text))
        }
    }
 }

Usage:

Localized(text: "hello")
Localized(text: "this %@ %@", arg: [4, "a"])
Welter answered 19/4, 2022 at 4:24 Comment(0)
T
0

New from WWDC 2023: String Catalog

Toilworn answered 19/10, 2023 at 17:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.