Skip to content

Instantly share code, notes, and snippets.

@nekonora
Created March 27, 2021 11:55
Show Gist options
  • Save nekonora/f7f87ed82c872c4845e5bc189d9d4c0e to your computer and use it in GitHub Desktop.
Save nekonora/f7f87ed82c872c4845e5bc189d9d4c0e to your computer and use it in GitHub Desktop.
///
/// Swift script to parse, find & replace a set of values with corresponding keys
/// from a given file.
/// In this case for example it's used to replace strings in `"my.String".localized()`
/// with their R.swift generated counterparts.
///
/// How to use:
/// - copy the script into the project root folder
/// - set permissions: `chmod -R +x CleanKeys.swift`
/// - run: `./CleanKeys.swift`
/// - ??
/// - profit
///
/// Disclamer: for ease of use, the entire block of code from R.generated.swift containing the keys
/// `static let myStringKey = Rswift.StringResource......` has been copied inside a file `generatedKeys.txt`
/// in the same folder of this script. An example is attached to this gist.
#!/usr/bin/env swift
import Foundation
let dirPath = FileManager.default.currentDirectoryPath
let generatedKeyPath = "/generatedKeys.txt"
let thisFileName = "CleanKeys.swift"
func getContentOfFile(at path: String) -> String {
let keyFilesPath = dirPath + path
do {
let contents = try String(contentsOfFile: keyFilesPath)
return contents
} catch {
print("error reading file!! \(error.localizedDescription)")
return ""
}
}
func writeNewContentToFile(at path: String, newContent: String) {
let fileURL = URL(fileURLWithPath: dirPath + path)
do {
try newContent.write(to: fileURL, atomically: true, encoding: .utf8)
}
catch {
print("error writing file!! \(error.localizedDescription)")
}
}
func getKeys(from content: String) -> [(key: String, value: String)] {
let lines = content
.components(separatedBy: "\n")
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { $0.starts(with: "static") }
let keys = lines
.map { line -> (String, String) in
let components = line.components(separatedBy: " ")
let key = components[2]
let value = components[5]
.replacingOccurrences(of: "\"", with: "")
.replacingOccurrences(of: ",", with: "")
return (key, value)
}
return keys
}
func getProjectSwiftFilesPaths() -> [String] {
let enumerator = FileManager.default.enumerator(atPath: dirPath)
let filePaths = (enumerator?.allObjects as! [String])
.filter{ $0.contains(".swift") && $0 != thisFileName }
.map { "/" + $0 }
return filePaths
}
func replaceInFile(path: String, keys: [(key: String, value: String)]) {
var contentOfFile = getContentOfFile(at: path)
guard !contentOfFile.isEmpty else { return }
guard keys.map(\.value).contains(where: contentOfFile.contains) else {
print("File does not contain relevant values, skipping")
return
}
let valuesToReplace = keys.filter { contentOfFile.contains($0.value) }
valuesToReplace.forEach {
let oldValueFormat = "\"\($0.value)\".localized()"
let newKey = "R.string.localizable.\($0.key)()"
contentOfFile = contentOfFile.replacingOccurrences(of: oldValueFormat, with: newKey)
print("\(path) - replaced: \($0.value)")
}
writeNewContentToFile(at: path, newContent: contentOfFile)
}
func main() {
let content = getContentOfFile(at: generatedKeyPath)
let keys = getKeys(from: content)
let files = getProjectSwiftFilesPaths()
files.forEach { file in
replaceInFile(path: file, keys: keys)
}
}
main()
/// This is a block of code directly from R.generated.swift
/// en translation:
///
/// Locales: es, en
static let myLocalizedKey = Rswift.StringResource(key: "my.localized.key", tableName: "Localizable", bundle: R.hostingBundle, locales: ["es", "en"], comment: nil)
/// en translation:
///
/// Locales: es, en
static let reminderTitle18 = Rswift.StringResource(key: "reminder.title.18", tableName: "Localizable", bundle: R.hostingBundle, locales: ["es", "en"], comment: nil)
/// en translation:
///
/// Locales: es, en
static let reminderTitle12 = Rswift.StringResource(key: "reminder.title.12", tableName: "Localizable", bundle: R.hostingBundle, locales: ["es", "en"], comment: nil)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment