【问题标题】:Convert localizable.string file to JSON in iOS swift在 iOS swift 中将 localizable.string 文件转换为 JSON
【发布时间】:2020-04-27 01:51:42
【问题描述】:

我的项目 Localizable.string(English)、Localizable.string(German) 和 Localizable.string(French) 中有 3 个可本地化的文件,其中包含 localizationKey1 = "Text1 in english"; 形式的几个键和值。我希望它们以格式转换为单个 json 文件

{
    "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
}

我该怎么做?

编辑: 我能够根据@Francis 的回答获得所需的 JSON 格式,但是外部和内部键的顺序搞砸了。有什么方法可以订购吗?

【问题讨论】:

标签: ios json parsing swift4.2 xcode11.3


【解决方案1】:

您可以尝试像普通的UTF8 txt 文件一样读取文件。您将遍历行,将行分成由“ = ”分隔的组件并将结果放入某个字典中。然后将字典序列化为 JSON 数据。

可能类似于以下内容:

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

此方法未经测试,只是动态编写的。它还有 3 点仍需要实现,以删除所有多余的部分并忽略不相关的行。

用法如下:

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")    
])

我希望这至少能让你开始。如果出现问题,或者如果您无法找到仍有待完成的部分的答案,我建议您提出其他更具体的问题。

【讨论】:

    【解决方案2】:

    试试这个

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

    【讨论】:

    • 感谢您的回答。这完全按照我需要的格式打印 JSON,但我确实有一个问题,外键和内键不按顺序排列。例如:如果在我的可本地化文件中我有键,说 key1 = value1, key2 = value 2 输出就像 { "key2": {"de": value2, "en":value2,”fr":value2 } , "key1":{"en":value1, "fr":value1, "de":value1}}。有没有办法订购?
    • 您可以根据排序顺序获取键或值,但我怀疑您是否可以按可本地化文件的顺序获取整个字典,因为字典没有顺序。
    猜你喜欢
    • 1970-01-01
    • 2016-07-22
    • 2015-01-06
    • 1970-01-01
    • 2019-03-15
    • 2015-10-05
    • 2015-06-19
    • 1970-01-01
    相关资源
    最近更新 更多