Reputation: 67
I have 3 Localizable files in my project Localizable.string(English), Localizable.string(German) and Localizable.string(French) with several keys and values of form localizationKey1 = "Text1 in english";
. I want them to be converted in a single json file in format
{
"localizationKey1": {
"en": "Text1 in english",
"de": "Text1 in german",
"fr": "Text1 in french"
},
"localizationKey2": {
"en": "Text2 in english",
"de": "Text2 in german",
"fr": "Text2 in french"
} and so on depending on number of keys
}
How do I go about it?
EDIT: I was able to the required JSON format based on the answer by @Francis but the orders of the outer and inner keys are messed up. Is there any way to order them?
Upvotes: 0
Views: 1617
Reputation: 3285
Try this
let path1 = (Bundle.main.path(forResource: "Localizable", ofType: "strings", inDirectory: nil, forLocalization: "en"))
let path2 = (Bundle.main.path(forResource: "Localizable", ofType: "strings", inDirectory: nil, forLocalization: "de"))
let path3 = (Bundle.main.path(forResource: "Localizable", ofType: "strings", inDirectory: nil, forLocalization: "fr"))
let dict1 = NSDictionary(contentsOfFile: path1!)
let dict2 = NSDictionary(contentsOfFile: path2!)
let dict3 = NSDictionary(contentsOfFile: path3!)
var newDict = [String : Any]()
for (key, value) in dict1! {
var value2 = ""
var value3 = ""
if let keyVal = dict2?[key] as? String {
value2 = keyVal
}
if let keyVal = dict3?[key] as? String {
value3 = keyVal
}
let tempDict = ["en": value, "de": value2, "fr": value3]
newDict["\(key)"] = tempDict
}
do {
let data = try JSONSerialization.data(withJSONObject: newDict, options: .prettyPrinted)
let dataString = String(data: data, encoding: .utf8)!
print(dataString) //This will give you the required JSON format
} catch {
print("JSON serialization failed: ", error)
}
Upvotes: 1
Reputation: 16774
You could try reading the file as normal UTF8
txt file. You would iterate through lines, break lines into components separated by " = " and put the result into some dictionary. Then serialize the dictionary into JSON data.
Maybe something like the following:
func parseLocalizationStringFilesToJSON(files: [(path: String, key: String)]) throws -> Data {
// Generate a dictionary that will be in the end parsed to JSON
var dictionary: [String: [String: String]] = [String: [String: String]]()
// Iterate through all files
try files.forEach { file in
// try reading file as UTF8 string
let fileString = try String(contentsOfFile: file.path, encoding: .utf8)
// Break down file string to lines
let lines = fileString.components(separatedBy: .newlines)
// Extract from each line
lines.forEach { line in
// TODO: Skip lines that do not start with "
let separator = " = " // A separator used to separate key-value in strings file
let lineComponents = line.components(separatedBy: separator) // Break down to components
if lineComponents.count >= 2 { // There may be more than 2 components. Imagine: localizationKey1 = "A = B";
// TODO: Trim the key to remove whitespaces and "
let key = lineComponents[0] // Key is always the first component
// TODO: Trim the value to remove whitespaces and "
let value = lineComponents[1...].joined(separator: separator) // The rest must be joined back together
var innerDictionary: [String: String] = dictionary[key] ?? [String: String]() // Extract current sub-json at this key or create a new sub-json
innerDictionary[file.key] = value // Assign a new value
dictionary[key] = innerDictionary // Put back to main dictionary
}
}
}
// Serialize it to JSON data
return try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
}
This method is not tested but just written on the fly. It also has 3 points that still need to be implemented to remove all the extra parts and to ignore irrelevant lines.
The usage would be like:
let jsonData: Data = try? parseLocalizationStringFilesToJSON(files: [
(Bundle.main.path(forResource: "Localizable", ofType: "string(English)"), "en"),
(Bundle.main.path(forResource: "Localizable", ofType: "string(German)"), "de"),
(Bundle.main.path(forResource: "Localizable", ofType: "string(French)"), "fr")
])
I hope this at least gets you started. I suggest you ask other more specific questions if things go wrong or if you have trouble finding answers on parts that are still to be done.
Upvotes: 0