38

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()?

LuLuGaGa
  • 13,089
  • 6
  • 49
  • 57
Oleh H
  • 846
  • 1
  • 10
  • 18

7 Answers7

55

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))
        }
    }
}
marc-medley
  • 8,931
  • 5
  • 60
  • 66
LuLuGaGa
  • 13,089
  • 6
  • 49
  • 57
  • Thanks, it was helpful! But I had some issues because it was several languages already added. – Oleh H Oct 27 '19 at 14:27
  • 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 this – Joseph Beuys' Mum Oct 29 '19 at 15:47
  • What exactly was the problem? – LuLuGaGa Oct 29 '19 at 17:01
  • 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 World – Joseph Beuys' Mum Oct 29 '19 at 17:06
  • @JosephBeuys'Mum I have added info how to run previews in various localised versions. Please let me know if it resolved your issue. Thanks – LuLuGaGa Oct 30 '19 at 00:14
  • 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 anyway – Joseph Beuys' Mum Oct 30 '19 at 09:27
  • 7
    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 fine – Joseph Beuys' Mum Oct 30 '19 at 09:37
  • 6
    Have also discovered (I think) that calling the strings file anything other than *Localizable* means it won't work – Joseph Beuys' Mum Oct 31 '19 at 17:06
  • 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? – mallow Nov 25 '19 at 05:17
  • 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. – Daniel Roethlisberger May 25 '20 at 14:03
  • God! @everyone Do not forget to correctly name the file to Localizable.strings ! – LetsGoBrandon Aug 30 '20 at 21:10
  • 1
    I distilled all of these instructions for SwiftUI Localization into a tutorial if anyone is interested: https://www.ibabbleon.com/swiftui_localization_tutorial.html – Localizer Jan 19 '21 at 20:48
22

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!"
c roald
  • 1,984
  • 1
  • 20
  • 30
  • 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 value – Rocker Aug 02 '20 at 05:34
  • Thanks a lot man, was already getting frustrated about this and thought there was no solution – Big_Chair Dec 30 '21 at 23:12
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

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
Oleh H
  • 846
  • 1
  • 10
  • 18
6

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

Localizable.strings file:

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

SwiftUI view file:

Text(LocalizedStringKey("Dismiss"))
Mike Lee
  • 2,440
  • 26
  • 12
  • Not sure if this was ever necessary. According to [Apple's docs](https://developer.apple.com/documentation/swiftui/localizedstringkey): _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._ – Robin Daugherty Aug 19 '22 at 14:02
5

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...
Ramis
  • 13,985
  • 7
  • 81
  • 100
1

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)
}
Roland Lariotte
  • 2,606
  • 1
  • 16
  • 40
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"])
Ahmadreza
  • 6,950
  • 5
  • 50
  • 69