Skip to content

Instantly share code, notes, and snippets.

@abubakrr
Created May 2, 2022 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abubakrr/857410a840352e4449907b1ca88ceaba to your computer and use it in GitHub Desktop.
Save abubakrr/857410a840352e4449907b1ca88ceaba to your computer and use it in GitHub Desktop.
How to unit test localizable strings in Swift
import XCTest
enum Language: String, Codable {
case english = "en"
case italian = "it"
static let supported: [Language] = [.english, .italian]
static let defaultLanguage: Language = .english
var displayName: String {
switch self {
case .english:
return "English"
case .italian:
return "Italiano"
}
}
}
final class LocalizationTests: XCTestCase {
func test_supportedLanguages_haveNonNilBundle() {
for language in Language.supported {
XCTAssertNotNil(getBundle(for: language))
}
}
func test_supportedLanguages_haveNonNilDictionary() {
for language in Language.supported {
XCTAssertNotNil(getLocalizedDictionary(for: language), "Localizable.strings file not found for \(language.displayName) language")
}
}
func test_translatedWords_basedOnDefaultLocale() {
let defaultLanguage = Language.defaultLanguage
let defaultLocalizedDictionary = getLocalizedDictionary(for: defaultLanguage)!
let supportedLanguagesExceptDefault = Language.supported.filter { $0 != defaultLanguage }
for language in supportedLanguagesExceptDefault {
let localizedDictionary = getLocalizedDictionary(for: language)!
for (key, defaultTranslation) in defaultLocalizedDictionary {
if let translation = localizedDictionary[key] {
if translation == defaultTranslation {
debugPrint("⚠️Warning: '\(key)' has identical translations at \(defaultLanguage.displayName) and \(language.displayName)")
}
} else {
XCTFail("'\(key)' is not translated into \(language.displayName)")
}
}
}
}
}
// MARK: - Helpers
extension LocalizationTests {
private func getLocalizedDictionary(for language: Language) -> [String: String]? {
guard let bundle = getBundle(for: language) else {
return nil
}
return getLocalizableDictionary(from: bundle)
}
private func getBundle(for language: Language) -> Bundle? {
guard let path = Bundle.main.path(forResource: language.rawValue, ofType: "lproj") else {
return nil
}
return Bundle(path: path)
}
private func getLocalizableDictionary(from bundle: Bundle) -> [String: String]? {
guard let path = bundle.path(forResource: "Localizable", ofType: "strings") else {
return nil
}
return NSDictionary(contentsOfFile: path)?.reduce(into: [String: String](), { $0[$1.key as! String] = $1.value as? String})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment