简体   繁体   中英

Convert localizable.string file to JSON in iOS swift

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?

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)
        }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM