Skip to content

Instantly share code, notes, and snippets.

@dobaduc
Last active November 14, 2019 16:38
Show Gist options
  • Save dobaduc/294d278bb7a285c838b8 to your computer and use it in GitHub Desktop.
Save dobaduc/294d278bb7a285c838b8 to your computer and use it in GitHub Desktop.
Tiny useful wrapper function of NSLocalizedString in Swift
//
// EasyLocalization.swift
//
// Created by Doba Duc on 9/1/15.
// Copyright (c) 2015 Doba Duc. All rights reserved.
//
/// Tiny useful wrapper function of NSLocalizedString in Swift
///
/// @param key Localizable key
/// @param replacements (Optional) A dictionary of replacements to be used in a formatted string.
/// @return Localized string
func lang(key: String, _ replacements: [String: String]? = [:]) -> String {
if let dict = replacements {
var string = NSLocalizedString(key, comment: "")
for (k, v) in dict {
string = string.stringByReplacingOccurrencesOfString("#{\(k)}", withString: v)
}
return string
} else {
return NSLocalizedString(key, comment: "")
}
}
// Assume that your Localizable.strings file looks like below:
// "user.name.format" = "Mr./Ms. #{name}" // Placeholder format: #{<placeholder_key>}
// "welcome.text" = "Welcome to Swift world!"
// ...
// ...
// Usage examples:
print(lang("welcome.text"))
print(lang("user.name.format", ["name": "Smith"]))
@dobaduc
Copy link
Author

dobaduc commented Dec 24, 2015

The example below shows why we need this wrapper around NSLocalizedString and String(format:arguments) function calls to handle localized texts more efficiently.

(Just copy & paste the following code blocks to a playground and see the results)

Handling localized texts as usual

var format = NSLocalizedString("sentence_format", comment: "") // Retrieve the format from strings table

// EN: 
format = "A %@ has %d %@s" // This line is just to make the example work without strings files
var englishText = String(format: format, arguments: ["cat", 4, "leg"]) // --> "A cat has 4 legs"

// JA:
format="%@は%@が%d本あります"
var japaneseText = String(format: format, arguments: ["", "", 4]) // --> "猫は足が4本あります"

Issue with the code above:

  • Can't use the same argument array for any languages due to the grammatical differences
  • Need to pay attention on the type of each argument

In the example above, we can't just write a single line of code that works for both English and Japanese!

let localizedText = String(format: NSLocalizedString("sentence_format", comment: ""), [value1, value2, value3])

Handling localized texts with the wrapper function

func lang(key: String, _ replacements: [String: String]? = [:]) -> String {
    if let dict = replacements {
        var string = NSLocalizedString(key, comment: "")
        for (k, v) in dict {
            string = string.stringByReplacingOccurrencesOfString("#{\(k)}", withString: v)
        }
        return string
    } else {
        return NSLocalizedString(key, comment: "")
    }
}

format = "A #{animal} has #{number} #{organ}s"
var englishText2 = lang(format, ["animal": "cat", "number": "4", "organ": "leg"])  // --> "A cat has 4 legs"

format = "#{animal}は#{organ}が#{number}本あります"
var japaneseText2 = lang(format, ["animal": "", "number": "4", "organ": ""]) // "猫は足が4本あります"

Advantages:

  • No needs to care about argument types or orders
  • Use exactly the same formatting code for any languages
  • Write shorter code instead calling both NSLocalizedString and String(format:arguments)

In short, write 1 single line of code for any languages and let the wrapper handle the rest

let localizedText = lang("sentence_format", ["animal": animalName, "number": numberOfOrgan, "organ": organName])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment