// // Definition.swift // // // Created by Thibaut Schmitt on 04/01/2022. // import Foundation class Definition { let name: String var tags = [String]() var comment: String? var translations = [String: String]() var reference: String? var isPlurals = false var isValid: Bool { name.isEmpty == false && translations.isEmpty == false } init(name: String) { self.name = name } static func match(_ line: String) -> Definition? { guard line.range(of: "\\[(.*?)]$", options: .regularExpression, range: nil, locale: nil) != nil else { return nil } let definitionName = line .replacingOccurrences(of: ["[", "]"], with: "") .removeLeadingTrailingWhitespace() return Definition(name: definitionName) } func hasOneOrMoreMatchingTags(inputTags: [String]) -> Bool { if Set(inputTags).intersection(Set(self.tags)).isEmpty { return false } return true } // MARK: - private func getStringParameters(input: String) -> (inputParameters: [String], translationArguments: [String])? { var methodsParameters = [String]() let printfPlaceholderRegex = try! NSRegularExpression(pattern: "%(?:\\d+\\$)?[+-]?(?:[ 0]|'.{1})?-?\\d*(?:\\.\\d+)?[blcdeEufFgGosxX@]*") printfPlaceholderRegex.enumerateMatches(in: input, options: [], range: NSRange(location: 0, length: input.count)) { match, _, stop in guard let match = match else { return } if let range = Range(match.range, in: input), let last = input[range].last { switch last { case "d", "u": methodsParameters.append("Int") case "f", "F": methodsParameters.append("Double") case "@", "s", "c": methodsParameters.append("String") case "%": // if you need to print %, you have to add %% break default: break } } } if methodsParameters.isEmpty { return nil } var inputParameters = [String]() var translationArguments = [String]() for (index, paramType) in methodsParameters.enumerated() { let paramName = "arg\(index)" translationArguments.append(paramName) inputParameters.append("\(paramName): \(paramType)") } return (inputParameters: inputParameters, translationArguments: translationArguments) } private func getBaseProperty(lang: String, translation: String, isStatic: Bool) -> String { """ /// Translation in \(lang) : /// \(translation) \(isStatic ? "static ": "")var \(name): String { NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "") } """ } private func getBaseMethod(lang: String, translation: String, isStatic: Bool, inputParameters: [String], translationArguments: [String]) -> String { """ /// Translation in \(lang) : /// \(translation) \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) } """ } func getNSLocalizedStringProperty(forLang lang: String) -> String { guard let translation = translations[lang] else { let error = StringiumError.langNotDefined(lang, name, reference != nil) print(error.description) Stringium.exit(withError: error) } // Generate property let property = getBaseProperty(lang: lang, translation: translation, isStatic: false) // Generate method var method = "" if let parameters = self.getStringParameters(input: translation) { method = getBaseMethod(lang: lang, translation: translation, isStatic: false, inputParameters: parameters.inputParameters, translationArguments: parameters.translationArguments) } return property + method } func getNSLocalizedStringStaticProperty(forLang lang: String) -> String { guard let translation = translations[lang] else { let error = StringiumError.langNotDefined(lang, name, reference != nil) print(error.description) Stringium.exit(withError: error) } // Generate property let property = getBaseProperty(lang: lang, translation: translation, isStatic: true) // Generate method var method = "" if let parameters = self.getStringParameters(input: translation) { method = getBaseMethod(lang: lang, translation: translation, isStatic: true, inputParameters: parameters.inputParameters, translationArguments: parameters.translationArguments) } return property + method } // MARK: - Raw strings func getProperty(forLang lang: String) -> String { guard let translation = translations[lang] else { let error = StringiumError.langNotDefined(lang, name, reference != nil) print(error.description) Stringium.exit(withError: error) } return """ /// Translation in \(lang) : /// \(translation) var \(name): String { "\(translation)" } """ } func getStaticProperty(forLang lang: String) -> String { guard let translation = translations[lang] else { let error = StringiumError.langNotDefined(lang, name, reference != nil) print(error.description) Stringium.exit(withError: error) } return """ /// Translation in \(lang) : /// \(translation) static var \(name): String { "\(translation)" } """ } }