skip to Main Content

In my project, I have Localizable.string file which is having more than 10,000 lines keyValue format.
I need to convert all of keys which are dotCase format like "contentsList.sort.viewCount" to lowerCamelCase. how can I convert by using swift scripting? thank you.

as-is

"contentsList.horizontal.more" = "totall";

to-be

"contentsListHorizontalMore" = "totall";

2

Answers


  1. First get all lines from your string. CompactMap your lines breaking it up into two components separated by the equal sign. Get the first component otherwise return nil. Get all ranges of the regex (w).(w). Replace the match range by the first + second group capitalized. This will remove the period. Return a collection of one element (snake case) + the other components joined by the separator equal sign. Now that you have all lines you just need to join them by the new line character:


    let string = """
    "contentsList.horizontal.more" = "totall";
    
    "whatever.vertical.less" = "summ";
    """
    

    let pattern = #"(w).(w)"#
    let lines = string.split(omittingEmptySubsequences: false,
                             whereSeparator: .isNewline)
    let result: [String] = lines.compactMap {
        let comps = $0.components(separatedBy: " = ")
        guard var first = comps.first else { return nil }
        let regex = try! NSRegularExpression(pattern: pattern)
        let matches = regex.matches(in: first, range: NSRange(first.startIndex..., in: first))
        let allRanges: [[Range<String.Index>]] = matches.map { match in
            (0..<match.numberOfRanges).compactMap { (index: Int) -> Range<String.Index>? in
                Range(match.range(at: index), in: first)
            }
        }
        for ranges in allRanges.reversed() {
            first.replaceSubrange(ranges[0], with: first[ranges[1]] + first[ranges[2]].uppercased())
        }
        return (CollectionOfOne(first) + comps.dropFirst())
            .joined(separator: " = ")
    }
    let finalString = result.joined(separator: "n")
    print(finalString)
    

    This will print

    "contentsListHorizontalMore" = "totall";

    "whateverVerticalLess" = "summ";

    Login or Signup to reply.
  2. You could subclass NSRegularExpression and override replacementString to be able to modify the string represented by the template parameter.

    class CapitalizeRegex: NSRegularExpression {
        override func replacementString(for result: NSTextCheckingResult, in string: String, offset: Int, template templ: String) -> String {
            guard result.numberOfRanges == 2,
                  let range = Range(result.range(at: 1), in: string) else { return "" }
            return string[range].capitalized
        }
    } 
    

    Then search for a dot followed by a word and capture the latter. The $1 pattern will capitalize the word

    let string = #"contentsList.horizontal.more" = "totall";"#
    
    let regex = try! CapitalizeRegex(pattern: #".(bw+b)"#)
    let result = regex.stringByReplacingMatches(in: string,
                                                range: NSRange(string.startIndex..., in: string),
                                                withTemplate: "$1")
    print(result)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search