What's NSLocalizedString equivalent in Swift?

121,805

Solution 1

The NSLocalizedString exists also in the Swift's world.

func NSLocalizedString(
    key: String,
    tableName: String? = default,
    bundle: NSBundle = default,
    value: String = default,
    #comment: String) -> String

The tableName, bundle, and value parameters are marked with a default keyword which means we can omit these parameters while calling the function. In this case, their default values will be used.

This leads to a conclusion that the method call can be simplified to:

NSLocalizedString("key", comment: "comment")

Swift 5 - no change, still works like that.

Solution 2

I use next solution:

1) create extension:

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}

2) in Localizable.strings file:

"Hi" = "Привет";

3) example of use:

myLabel.text = "Hi".localized

enjoy! ;)

--upd:--

for case with comments you can use this solution:

1) Extension:

extension String {
    func localized(withComment:String) -> String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: withComment)
    }
}

2) in .strings file:

/* with !!! */
"Hi" = "Привет!!!";

3) using:

myLabel.text = "Hi".localized(withComment: "with !!!")

Solution 3

A variation of the existing answers:

Swift 5.1:

extension String {

    func localized(withComment comment: String? = nil) -> String {
        return NSLocalizedString(self, comment: comment ?? "")
    }

}

You can then simply use it with or without comment:

"Goodbye".localized()
"Hello".localized(withComment: "Simple greeting")

Please note that genstrings won't work with this solution.

Solution 4

By using this way its possible to create a different implementation for different types (i.e. Int or custom classes like CurrencyUnit, ...). Its also possible to scan for this method invoke using the genstrings utility. Simply add the routine flag to the command

genstrings MyCoolApp/Views/SomeView.swift -s localize -o .

extension:

import UIKit

extension String {
    public static func localize(key: String, comment: String) -> String {
        return NSLocalizedString(key, comment: comment)
    }
}

usage:

String.localize("foo.bar", comment: "Foo Bar Comment :)")

Solution 5

Swift 3 version :)...

import Foundation

extension String {
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
}
Share:
121,805

Related videos on Youtube

Rafał Sroka
Author by

Rafał Sroka

sSSSs SSSSSSS SSSSSSS SSSSS .--' '--. / \ / | | \ / / \ : / \ \ ( ( ) : ( ) ) \ \ / \ / / _`\/ . \/`_____ /~~; ;~~~~~/| / '.__|__.' _/ /__________________/ | |

Updated on July 18, 2022

Comments

  • Rafał Sroka
    Rafał Sroka almost 2 years

    Is there an Swift equivalent of NSLocalizedString(...)? In Objective-C, we usually use:

    NSString *string = NSLocalizedString(@"key", @"comment");
    

    How can I achieve the same in Swift? I found a function:

    func NSLocalizedString(
        key: String,
        tableName: String? = default,
        bundle: NSBundle = default,
        value: String = default,
        #comment: String) -> String
    

    However, it is very long and not convenient at all.

    • Matej Ukmar
      Matej Ukmar almost 9 years
      Best is to create shorter version of code snippet: NSLocalizedString("", comment: "") ... I liked the extension solution, but the problem is genstrings will not capture these strings into translation file.
    • LShi
      LShi about 7 years
      In Swift 3 you can just use NSLocalizedString("Cancel", comment: "Cancel button title") taking advantage of the default values. It is convenient I think.
    • LightMan
      LightMan almost 6 years
      This is a very good article about localization (string extension, different strings tables and even pluralization): medium.com/@marcosantadev/…
    • Mendy
      Mendy about 5 years
      This is a very good article about localization in Swift for a robust architecture medium.com/@mendibarouk/…
  • Marcin
    Marcin over 9 years
    it's only difference that comment can't be nil, and autocompletion is far from intuitive for short version.
  • Apps 4 U
    Apps 4 U over 9 years
    this is not working any more I get error saying that not enough arguments are used.
  • Neil
    Neil about 9 years
    Not that the above is correct in Xcode 6.3, Swift 1.2 with the specific change from objective-c, the comment (as Marcin stated) cannot be nil, but it can be "" (empty).
  • Avi Cohen
    Avi Cohen about 9 years
    @drOX You might consider editing your code to: return NSLocalizedString(self, comment: self)
  • Ned
    Ned about 9 years
    The only issue with this is that you won't be able to use the genstrings utility to generate your .strings files.
  • dr OX
    dr OX almost 9 years
    @AviCohen q.v. after "upd"
  • Gui Moura
    Gui Moura almost 9 years
    That's a very good idea! I also made it a little bit smarter by changing to func localized(comment: String = "") -> String so it becomes smaller and with optional comments :)
  • Chris
    Chris over 8 years
    Any idea how to use genstrings with this?
  • Joney Spark
    Joney Spark over 8 years
    A nil/empty comment makes it hard to relocate the string later in the string file; if nothing else add class/file name where it's used as the comment.
  • Pascal
    Pascal over 8 years
    where would you put such a snippet in the project?
  • Erik van der Neut
    Erik van der Neut about 8 years
    Everybody is very excited about this answer, but the BIG problem (for any serious project with several languages) is that this completely messes up your management of your translated messages, because genstrings only works on literal strings passed in to NSLocalizedString. With this clever workaround, you lose the ability to update your .strings files using the genstrings tool, and at least for me that means I will not be able to use this simplified approach.
  • Tomek Cejner
    Tomek Cejner about 8 years
    I found this great solution implemented in github.com/marmelroy/Localize-Swift. Problem of genstrings is also resolved by custom python script included by the author. I am not an author.
  • Jeremiah
    Jeremiah almost 8 years
    This is bad practice. Comments are recommended and helpful unless you are doing all of the translation yourself.
  • Ken Ko
    Ken Ko over 7 years
    Similar to the comment on genstrings - it will also mess up the built-in Xcode XLIFF export/import process too, because that tool is also a lexical parser of source code, and won't know how to export the strings anymore.
  • David James
    David James over 7 years
    I don't understand why people think this is a good answer? What is the point of using localization API at all (even with the extension) if you can't export/import it properly via Xcode for translation???
  • guido
    guido over 7 years
    For those that like/need the xcode import/export feature, I created a little AppleScript that puts the NSLocalizedString function around the string you select. I linked it to a shortcut key. Simply select the string you want to localise and hit the shortcut key. This was not my idea. Got it from somewhere on the internet, but can't remember where, sorry. Here's the script: on run {input, parameters} set new_text to "NSLocalizedString(" & input & ",comment:\"translatorComment\")" return new_text end run
  • Cristian Cardoso
    Cristian Cardoso over 7 years
    Swift 3. bundle: Bundle.main
  • LShi
    LShi about 7 years
    Sorry I don't get the point of many answers here. What's the benefit of the method over using NSLocalizedString("Cancel", comment: "Cancel button title") ?
  • GYFK
    GYFK about 7 years
    @LShi some people were complaining, that NSLocalizedString looks less Swiftier, than it should look. String.localized on the other hand looks more Swifty but you are unable to use gesntrings utility with it which is commonly used to ease your work with internationalization. My point is that it`s pretty easy to mix both approaches. So mainly it is a question of readability.
  • iDevAmit
    iDevAmit almost 7 years
    The thing to note is that Strings defined in the described way are static strings. The app should be relaunched after changing language in iOS Settings app. If not, relaunch it by yourself in order to see changes. It can also have a memory overhead, since we initialize all strings at once, not at the time they’re needed.
  • May Phyu
    May Phyu almost 7 years
    @drOX , Bro could you help me please stackoverflow.com/questions/44304498/… ?
  • damianostre
    damianostre almost 7 years
    @guido How do you make the Applescript available in Xcode? Via Services? And what shortcut did you set up? In Xcode's Preferences, or in System Preferences, or where?
  • guido
    guido almost 7 years
    I set it up system wide. It's available through services, but it always use my shortcut key: cmd-shift-F12
  • art-of-dreams
    art-of-dreams over 6 years
    I think it's better to use computed properties here, like this static var Hello: String = { return NSLocalizedString("Hello") }
  • José
    José about 6 years
    It is bad practice to leave out the comments.
  • GatoCurioso
    GatoCurioso about 6 years
    @José Thanks for your comment. The code was meant as an idea, not as template for copy and paste. But I added the option to add comments if you want ;)
  • shim
    shim over 5 years
    Even if you're translating yourself, the comments would be helpful, especially in a large project.
  • BangOperator
    BangOperator over 5 years
    @Warpzit Just out of curiosity, how do you collect all your strings that need to be localised.
  • Warpzit
    Warpzit over 5 years
    @BangOperator Well right now we have a script that converts a csv file to the localized files. We're planning to transition to one of the online tools that can manage all translations on multiple platforms. In other words, we wont be importing or exporting any translations from xcode, we'll simply just override the files.
  • Cristik
    Cristik over 4 years
    Downvoted because it doesn't follow the Swift naming guidelines
  • Cristik
    Cristik over 4 years
    What happens if you need to do another round of genstrings? Do you replace back all .localized by NSLocalizedString?
  • Christian Gossain
    Christian Gossain over 4 years
    This answer is amazing and should be upvoted more! This is the simplest solution I've found so far if you're looking to avoid bringing in yet another library. This is a good native solution.
  • Wimukthi Rajapaksha
    Wimukthi Rajapaksha about 4 years
    extension String { func localized(withComment:String, table_name: String?) -> String { return NSLocalizedString(self, tableName: table_name, bundle: Bundle.main, value: "", comment: withComment) } } if you use this code, default it will check the string in Localizable.strings file. And if you want to check in another file, you can pass the file name in parameters, let contentHelloWorld = "hello_world".localized(withComment: "hello", table_name: "Localizable-SP")
  • Ethan Allen
    Ethan Allen almost 4 years
    This is the correct answer. Once Apple does update it for Swift, Xcode will be able to just auto-convert this API to its new Swift API and nothing else will break. Even in Xcode's Refractor menu currently (v 11.4.1) there is a Wrap in NSLocalizedString option which make things really easy by just highlighting text, right-clicking, and selecting the menu item.
  • arlomedia
    arlomedia over 3 years
    I use a translation database that has a place for comments, and have no need for these comments or the empty "comment:" arguments to be in my code. So I'm using this, plus an underscore before the "key:" argument, to make the function calls even cleaner.
  • Ethan Allen
    Ethan Allen almost 3 years
    This is perfect for realtime Info.plist user defined build settings translation when using multiple Xcode Schemes. Thanks!
  • devjme
    devjme over 2 years
    This also worked for me but instead of a signaling a . at the end for current dir I had to add the actual folder to the genstrings command like this: genstrings MyCoolApp/Views/SomeView.swift -s localize -o en.lproj