diff --git a/Jenkinsfile b/Jenkinsfile index 85bdaad..34c30ee 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ library "openiumpipeline" -env.DEVELOPER_DIR="/Applications/Xcode-15.0.1.app/Contents/Developer" +env.DEVELOPER_DIR="/Applications/Xcode-15.3.0.app/Contents/Developer" //env.SIMULATOR_DEVICE_TYPES="iPad--7th-generation-" env.IS_PACKAGE_SWIFT=1 env.TARGETS_MACOS=1 diff --git a/Package.resolved b/Package.resolved index 60ab9d4..824db60 100644 --- a/Package.resolved +++ b/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/krzyzanowskim/CryptoSwift.git", "state" : { - "revision" : "db51c407d3be4a051484a141bf0bff36c43d3b1e", - "version" : "1.8.0" + "revision" : "c9c3df6ab812de32bae61fc0cd1bf6d45170ebf0", + "version" : "1.8.2" } }, { diff --git a/Sources/ResgenSwift/Generate/GenerateError.swift b/Sources/ResgenSwift/Generate/GenerateError.swift index 2ebc045..03c3c16 100644 --- a/Sources/ResgenSwift/Generate/GenerateError.swift +++ b/Sources/ResgenSwift/Generate/GenerateError.swift @@ -9,7 +9,7 @@ import Foundation enum GenerateError: Error { case fileNotExists(String) - case invalidConfigurationFile(String) + case invalidConfigurationFile(String, String) case commandError([String], String) case writeFile(String, String) @@ -18,8 +18,8 @@ enum GenerateError: Error { case .fileNotExists(let filename): return "error: [\(Generate.toolName)] File \(filename) does not exists" - case .invalidConfigurationFile(let filename): - return "error: [\(Generate.toolName)] File \(filename) is not a valid configuration file" + case .invalidConfigurationFile(let filename, let underneathErrorDescription): + return "error: [\(Generate.toolName)] File \(filename) is not a valid configuration file. Underneath error: \(underneathErrorDescription)" case .commandError(let command, let terminationStatus): let readableCommand = command diff --git a/Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift b/Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift index 2701b3f..dd94e03 100644 --- a/Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift +++ b/Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift @@ -269,14 +269,22 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible { let extensionName: String? let extensionSuffix: String? private let staticMembers: Bool? - + private let xcStrings: Bool? + var staticMembersOptions: Bool { if let staticMembers = staticMembers { return staticMembers } return false } - + + var xcStringsOptions: Bool { + if let xcStrings = xcStrings { + return xcStrings + } + return false + } + internal init(inputFile: String, outputPath: String, langs: String, @@ -284,7 +292,8 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible { extensionOutputPath: String, extensionName: String?, extensionSuffix: String?, - staticMembers: Bool?) { + staticMembers: Bool?, + xcStrings: Bool?) { self.inputFile = inputFile self.outputPath = outputPath self.langs = langs @@ -293,6 +302,7 @@ struct StringsConfiguration: Codable, CustomDebugStringConvertible { self.extensionName = extensionName self.extensionSuffix = extensionSuffix self.staticMembers = staticMembers + self.xcStrings = xcStrings } var debugDescription: String { diff --git a/Sources/ResgenSwift/Generate/Parser/ConfigurationFileParser.swift b/Sources/ResgenSwift/Generate/Parser/ConfigurationFileParser.swift index 0b0c885..4b61d31 100644 --- a/Sources/ResgenSwift/Generate/Parser/ConfigurationFileParser.swift +++ b/Sources/ResgenSwift/Generate/Parser/ConfigurationFileParser.swift @@ -16,12 +16,15 @@ class ConfigurationFileParser { Generate.exit(withError: error) } - guard let configuration = try? YAMLDecoder().decode(ConfigurationFile.self, from: data) else { - let error = GenerateError.invalidConfigurationFile(configurationFile) + do { + return try YAMLDecoder().decode(ConfigurationFile.self, from: data) + } catch { + let error = GenerateError.invalidConfigurationFile( + configurationFile, + error.localizedDescription.description + ) print(error.description) Generate.exit(withError: error) } - - return configuration } } diff --git a/Sources/ResgenSwift/Generate/Runnable/StringsConfiguration+Runnable.swift b/Sources/ResgenSwift/Generate/Runnable/StringsConfiguration+Runnable.swift index d573569..7da6a37 100644 --- a/Sources/ResgenSwift/Generate/Runnable/StringsConfiguration+Runnable.swift +++ b/Sources/ResgenSwift/Generate/Runnable/StringsConfiguration+Runnable.swift @@ -14,7 +14,7 @@ extension StringsConfiguration: Runnable { if force { args += ["-f"] } - + args += [ inputFile.prependIfRelativePath(projectDirectory), "--output-path", @@ -26,7 +26,9 @@ extension StringsConfiguration: Runnable { "--extension-output-path", extensionOutputPath.prependIfRelativePath(projectDirectory), "--static-members", - "\(staticMembersOptions)" + "\(staticMembersOptions)", + "--xc-strings", + "\(xcStringsOptions)" ] if let extensionName = extensionName { diff --git a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift index 633ec7a..ce26ffb 100644 --- a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift +++ b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift @@ -1,6 +1,6 @@ // // StringsFileGenerator.swift -// +// // // Created by Thibaut Schmitt on 04/01/2022. // @@ -9,15 +9,16 @@ import Foundation import ToolCore class StringsFileGenerator { - + // MARK: - Strings Files - + static func writeStringsFiles(sections: [Section], langs: [String], defaultLang: String, tags: [String], outputPath: String, inputFilenameWithoutExt: String) { + var stringsFilesContent = [String: String]() for lang in langs { stringsFilesContent[lang] = Self.generateStringsFileContent(lang: lang, @@ -25,11 +26,11 @@ class StringsFileGenerator { tags: tags, sections: sections) } - + // Write strings file content langs.forEach { lang in guard let fileContent = stringsFilesContent[lang] else { return } - + let stringsFilePath = "\(outputPath)/\(lang).lproj/\(inputFilenameWithoutExt).strings" let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath) do { @@ -41,7 +42,32 @@ class StringsFileGenerator { } } } - + + static func writeXcStringsFiles(sections: [Section], + langs: [String], + defaultLang: String, + tags: [String], + outputPath: String, + inputFilenameWithoutExt: String) { + + let fileContent: String = Self.generateXcStringsFileContent( + langs: langs, + defaultLang: defaultLang, + tags: tags, + sections: sections + ) + + let stringsFilePath = "\(outputPath)/\(inputFilenameWithoutExt).xcstrings" + let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath) + do { + try fileContent.write(to: stringsFilePathURL, atomically: false, encoding: .utf8) + } catch let error { + let error = StringiumError.writeFile(error.localizedDescription, stringsFilePath) + print(error.description) + Stringium.exit(withError: error) + } + } + static func generateStringsFileContent(lang: String, defaultLang: String, tags inputTags: [String], @@ -53,13 +79,13 @@ class StringsFileGenerator { * Language: \(lang) */\n """ - + sections.forEach { section in // Check that at least one string will be generated guard section.hasOneOrMoreMatchingTags(tags: inputTags) else { return // Go to next section } - + stringsFileContent += "\n/********** \(section.name) **********/\n\n" section.definitions.forEach { definition in var skipDefinition = false // Set to true if not matching tag @@ -69,16 +95,16 @@ class StringsFileGenerator { skipDefinition = true return nil } - + // If tags contains `noTranslationTag` => get default lang if definition.tags.contains(Stringium.noTranslationTag) { return definition.translations[defaultLang] } - + // Else: get specific lang return definition.translations[lang] }() - + if let translation = translationOpt { stringsFileContent += "\"\(definition.name)\" = \"\(translation)\";\n\n" } else if skipDefinition == false { @@ -88,12 +114,123 @@ class StringsFileGenerator { } } } - + return stringsFileContent } - + + // MARK: - XcStrings Generation + + static func generateXcStringsFileContent(langs: [String], + defaultLang: String, + tags inputTags: [String], + sections: [Section]) -> String { + let rootObject = generateRootObject(langs: langs, defaultLang: defaultLang, tags: inputTags, sections: sections) + let file = generateXcStringsFileContentFromRootObject(rootObject: rootObject) + + return file + } + + static func generateXcStringsFileContentFromRootObject(rootObject: Root) -> String { + do { + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted] + + let json = try encoder.encode(rootObject) + + if let jsonString = String(data: json, encoding: .utf8) { + return jsonString + } + + } catch { + debugPrint("Failed to encode: \(error)") + } + + return "" + } + + static func generateRootObject(langs: [String], + defaultLang: String, + tags inputTags: [String], + sections: [Section]) -> Root { + + var xcStringDefinitionTab: [XCStringDefinition] = [] + + sections.forEach { section in + // Check that at least one string will be generated + guard section.hasOneOrMoreMatchingTags(tags: inputTags) else { + return // Go to next section + } + + section.definitions.forEach { definition in + var skipDefinition = false + var isNoTranslation = false + + var localizationTab: [XCStringLocalization] = [] + + if definition.hasOneOrMoreMatchingTags(inputTags: inputTags) == false { + skipDefinition = true + } + + if definition.tags.contains(Stringium.noTranslationTag) { + isNoTranslation = true + } + + if !skipDefinition { + if isNoTranslation { + // Search for langs in yaml + for lang in langs { + if let value = definition.translations[defaultLang], !value.isEmpty { + let localization = XCStringLocalization( + lang: lang, + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit(state: "translated", value: value) + ) + ) + localizationTab.append(localization) + } + } + } else { + // Search for langs in twine + for (lang, value) in definition.translations where !value.isEmpty { + + let localization = XCStringLocalization( + lang: lang, + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit(state: "translated", value: value) + ) + ) + + localizationTab.append(localization) + } + } + + let xcStringDefinition = XCStringDefinition( + title: definition.name, + content: XCStringDefinitionContent( + comment: definition.comment, + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: localizationTab + ) + ) + ) + + xcStringDefinitionTab.append(xcStringDefinition) + } + } + } + + let xcStringContainer = XCStringDefinitionContainer(strings: xcStringDefinitionTab) + + return Root( + sourceLanguage: defaultLang, + strings: xcStringContainer, + version: "1.0" + ) + } + // MARK: - Extension file - + static func writeExtensionFiles(sections: [Section], defaultLang lang: String, tags: [String], @@ -110,7 +247,7 @@ class StringsFileGenerator { inputFilename: inputFilename, extensionName: extensionName, extensionSuffix: extensionSuffix) - + // Write content let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath) do { @@ -121,9 +258,9 @@ class StringsFileGenerator { Stringium.exit(withError: error) } } - + // MARK: - Extension content - + static func getExtensionContent(sections: [Section], defaultLang lang: String, tags: [String], @@ -139,31 +276,31 @@ class StringsFileGenerator { ] .joined(separator: "\n") } - + // MARK: - Extension part - + private static func getHeader(stringsFilename: String, extensionClassname: String) -> String { """ // Generated by ResgenSwift.Strings.\(Stringium.toolName) \(ResgenSwiftVersion) - + import UIKit - + fileprivate let kStringsFileName = "\(stringsFilename)" - + extension \(extensionClassname) { """ } - + private static func getEnumKey(sections: [Section], tags: [String], extensionClassname: String, extensionSuffix: String) -> String { var enumDefinition = "\n enum Key\(extensionSuffix.uppercasedFirst()): String {\n" - + // Enum sections.forEach { section in // Check that at least one string will be generated guard section.hasOneOrMoreMatchingTags(tags: tags) else { return // Go to next section } - + section.definitions.forEach { definition in guard definition.hasOneOrMoreMatchingTags(inputTags: tags) == true else { return // Go to next definition @@ -172,7 +309,7 @@ class StringsFileGenerator { enumDefinition += " case \(definition.name) = \"\(definition.name)\"\n" } } - + // KeyPath accessors enumDefinition += "\n" enumDefinition += " var keyPath: KeyPath<\(extensionClassname), String> {\n" @@ -182,7 +319,7 @@ class StringsFileGenerator { guard section.hasOneOrMoreMatchingTags(tags: tags) else { return // Go to next section } - + section.definitions.forEach { definition in guard definition.hasOneOrMoreMatchingTags(inputTags: tags) == true else { return // Go to next definition @@ -194,23 +331,23 @@ class StringsFileGenerator { enumDefinition += " }\n" // Switch enumDefinition += " }\n" // var keyPath enumDefinition += " }" // Enum - + return enumDefinition } - + private static func getProperties(sections: [Section], defaultLang lang: String, tags: [String], staticVar: Bool) -> String { sections.compactMap { section in // Check that at least one string will be generated guard section.hasOneOrMoreMatchingTags(tags: tags) else { return nil // Go to next section } - + var res = "\n // MARK: - \(section.name)\n" res += section.definitions.compactMap { definition in guard definition.hasOneOrMoreMatchingTags(inputTags: tags) == true else { return nil // Go to next definition } - + if staticVar { return "\n\(definition.getNSLocalizedStringStaticProperty(forLang: lang))" } @@ -221,11 +358,11 @@ class StringsFileGenerator { } .joined(separator: "\n") } - + private static func getFooter() -> String { """ } - + """ } } diff --git a/Sources/ResgenSwift/Strings/Model/Definition.swift b/Sources/ResgenSwift/Strings/Model/Definition.swift index 6bb8cb7..b059383 100644 --- a/Sources/ResgenSwift/Strings/Model/Definition.swift +++ b/Sources/ResgenSwift/Strings/Model/Definition.swift @@ -84,22 +84,29 @@ class Definition { return (inputParameters: inputParameters, translationArguments: translationArguments) } - private func getBaseProperty(lang: String, translation: String, isStatic: Bool) -> String { + private func getBaseProperty(lang: String, translation: String, isStatic: Bool, comment: String?) -> String { """ /// Translation in \(lang) : /// \(translation) + /// + /// Comment : + /// \(comment?.isEmpty == false ? comment! : "No comment") \(isStatic ? "static ": "")var \(name): String { - NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "") + NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment ?? "")") } """ + } - private func getBaseMethod(lang: String, translation: String, isStatic: Bool, inputParameters: [String], translationArguments: [String]) -> String { + private func getBaseMethod(lang: String, translation: String, isStatic: Bool, inputParameters: [String], translationArguments: [String], comment: String?) -> String { + """ - - + /// Translation in \(lang) : /// \(translation) + /// + /// Comment : + /// \(comment?.isEmpty == false ? comment! : "No comment") \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) } @@ -114,8 +121,13 @@ class Definition { } // Generate property - let property = getBaseProperty(lang: lang, translation: translation, isStatic: false) - + let property = getBaseProperty( + lang: lang, + translation: translation, + isStatic: false, + comment: self.comment + ) + // Generate method var method = "" if let parameters = self.getStringParameters(input: translation) { @@ -123,7 +135,8 @@ class Definition { translation: translation, isStatic: false, inputParameters: parameters.inputParameters, - translationArguments: parameters.translationArguments) + translationArguments: parameters.translationArguments, + comment: self.comment) } return property + method @@ -137,7 +150,12 @@ class Definition { } // Generate property - let property = getBaseProperty(lang: lang, translation: translation, isStatic: true) + let property = getBaseProperty( + lang: lang, + translation: translation, + isStatic: true, + comment: self.comment + ) // Generate method var method = "" @@ -146,7 +164,8 @@ class Definition { translation: translation, isStatic: true, inputParameters: parameters.inputParameters, - translationArguments: parameters.translationArguments) + translationArguments: parameters.translationArguments, + comment: self.comment) } return property + method @@ -160,10 +179,14 @@ class Definition { print(error.description) Stringium.exit(withError: error) } - + return """ /// Translation in \(lang) : /// \(translation) + /// + /// Comment : + /// \(comment?.isEmpty == false ? comment! : "No comment") + var \(name): String { "\(translation)" } @@ -180,6 +203,9 @@ class Definition { return """ /// Translation in \(lang) : /// \(translation) + /// + /// Comment : + /// \(comment?.isEmpty == false ? comment! : "No comment") static var \(name): String { "\(translation)" } diff --git a/Sources/ResgenSwift/Strings/Model/XcString.swift b/Sources/ResgenSwift/Strings/Model/XcString.swift new file mode 100644 index 0000000..6c784d1 --- /dev/null +++ b/Sources/ResgenSwift/Strings/Model/XcString.swift @@ -0,0 +1,109 @@ +// +// XcString.swift +// +// +// Created by Quentin Bandera on 12/04/2024. +// + +import SwiftUI + +struct DynamicKey: CodingKey { + var intValue: Int? + init?(intValue: Int) { + self.intValue = intValue + self.stringValue = "\(intValue)" + } + + var stringValue: String + init?(stringValue: String) { + self.stringValue = stringValue + } +} + +struct Root: Codable, Equatable { + let sourceLanguage: String + let strings: XCStringDefinitionContainer + let version: String +} + +struct XCStringDefinitionContainer: Codable, Equatable { + let strings: [XCStringDefinition] + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: DynamicKey.self) + + for str in strings { + if let codingKey = DynamicKey(stringValue: str.title) { + try container.encode(str.content, forKey: codingKey) + } + } + } + + static func == (lhs: XCStringDefinitionContainer, rhs: XCStringDefinitionContainer) -> Bool { + return lhs.strings.sorted(by: { + $0.title < $1.title + }) == rhs.strings.sorted(by: { $0.title < $1.title }) + } +} + +struct XCStringDefinition: Codable, Equatable { + let title: String // json key -> custom encoding methods + let content: XCStringDefinitionContent +} + +struct XCStringDefinitionContent: Codable, Equatable { + let comment: String? + let extractionState: String + var localizations: XCStringLocalizationContainer + + init(comment: String? = nil, extractionState: String, localizations: XCStringLocalizationContainer) { + self.comment = comment + self.extractionState = extractionState + self.localizations = localizations + } +} + +struct XCStringLocalizationContainer: Codable, Equatable { + let localizations: [XCStringLocalization] + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: DynamicKey.self) + + for loca in localizations { + if let codingKey = DynamicKey(stringValue: loca.lang) { + try container.encode(loca.content, forKey: codingKey) + } + } + } + + static func == (lhs: XCStringLocalizationContainer, rhs: XCStringLocalizationContainer) -> Bool { + return lhs.localizations.count == rhs.localizations.count && lhs.localizations.sorted(by: { $0.lang < $1.lang }) == rhs.localizations.sorted(by: { $0.lang < $1.lang }) + } +} + +struct XCStringLocalization: Codable, Equatable { + let lang: String // json key -> custom encoding method + let content: XCStringLocalizationLangContent +} + +struct XCStringLocalizationLangContent: Codable, Equatable { + let stringUnit: DefaultStringUnit +} + +//enum VarationOrStringUnit: Encodable { +// case variations([Varation]) +// case stringUnit: (DefaultStringUnit) +// +// func encode(to encoder: any Encoder) throws { +// if let varations { +// +// } else if let { +// +// } +// } +//} + +struct DefaultStringUnit: Codable, Equatable { + let state: String + let value: String +} diff --git a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift index 1e3897e..a27ebfe 100644 --- a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift +++ b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift @@ -43,13 +43,26 @@ struct Stringium: ParsableCommand { let sections = TwineFileParser.parse(options.inputFile) // Generate strings files - StringsFileGenerator.writeStringsFiles(sections: sections, - langs: options.langs, - defaultLang: options.defaultLang, - tags: options.tags, - outputPath: options.stringsFileOutputPath, - inputFilenameWithoutExt: options.inputFilenameWithoutExt) - + print(options.xcStrings) + if !options.xcStrings { + print("[\(Self.toolName)] Will generate strings") + + StringsFileGenerator.writeStringsFiles(sections: sections, + langs: options.langs, + defaultLang: options.defaultLang, + tags: options.tags, + outputPath: options.stringsFileOutputPath, + inputFilenameWithoutExt: options.inputFilenameWithoutExt) + } else { + print("[\(Self.toolName)] Will generate xcStrings") + StringsFileGenerator.writeXcStringsFiles(sections: sections, + langs: options.langs, + defaultLang: options.defaultLang, + tags: options.tags, + outputPath: options.stringsFileOutputPath, + inputFilenameWithoutExt: options.inputFilenameWithoutExt) + } + // Generate extension StringsFileGenerator.writeExtensionFiles(sections: sections, defaultLang: options.defaultLang, @@ -59,7 +72,7 @@ struct Stringium: ParsableCommand { extensionName: options.extensionName, extensionFilePath: options.extensionFilePath, extensionSuffix: options.extensionSuffix) - + print("[\(Self.toolName)] Strings generated") } diff --git a/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift b/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift index 1fd1d53..7c9c7a8 100644 --- a/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift +++ b/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift @@ -11,8 +11,8 @@ import ArgumentParser struct StringiumOptions: ParsableArguments { @Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation") var forceGeneration = false - - @Argument(help: "Input files where strings ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() }) + + @Argument(help: "Input files where strings are defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() }) var inputFile: String @Option(name: .customLong("output-path"), help: "Path where to strings file.", transform: { $0.replaceTiltWithHomeDirectoryPath() }) @@ -32,7 +32,10 @@ struct StringiumOptions: ParsableArguments { @Option(help: "Tell if it will generate static properties or not") var staticMembers: Bool = false - + + @Option(help: "Tell if it will generate xcStrings file or not") + var xcStrings: Bool = false + @Option(help: "Extension name. If not specified, it will generate an String extension.") var extensionName: String = Stringium.defaultExtensionName diff --git a/Tests/ResgenSwiftTests/Colors/ParsedColorTests.swift b/Tests/ResgenSwiftTests/Colors/ParsedColorTests.swift index cd9e45e..c0620cf 100644 --- a/Tests/ResgenSwiftTests/Colors/ParsedColorTests.swift +++ b/Tests/ResgenSwiftTests/Colors/ParsedColorTests.swift @@ -91,7 +91,7 @@ final class ParsedColorTests: XCTestCase { // When let contentJson = color.contentsJSON() guard let data = contentJson.data(using: .utf8), - let parsedJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { + let parsedJson = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { XCTFail("Cannot convert `contentJSON` string to Data") return } diff --git a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift index f61087a..c25b3ff 100644 --- a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift +++ b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift @@ -100,24 +100,33 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "This is a comment") } """ let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "This is a comment") } """ let expectEnUs = """ /// Translation in en-us : /// This is the english us translation + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "This is a comment") } """ @@ -125,7 +134,118 @@ final class DefinitionTests: XCTestCase { XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) } - + + func testGeneratedNSLocalizedStringPropertyWithEmptyComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.comment = "" + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getNSLocalizedStringProperty(forLang: "fr") + let propertyEn = definition.getNSLocalizedStringProperty(forLang: "en") + let propertyEnUs = definition.getNSLocalizedStringProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "") + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "") + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "") + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + + func testGeneratedNSLocalizedStringPropertyWithNoComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getNSLocalizedStringProperty(forLang: "fr") + let propertyEn = definition.getNSLocalizedStringProperty(forLang: "en") + let propertyEnUs = definition.getNSLocalizedStringProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "") + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "") + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "") + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + + // MARK: - getNSLocalizedStringStaticProperty + func testGeneratedNSLocalizedStringStaticProperty() { // Given let definition = Definition(name: "definition_name") @@ -146,24 +266,33 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// This is a comment static var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "This is a comment") } """ let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// This is a comment static var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "This is a comment") } """ let expectEnUs = """ /// Translation in en-us : /// This is the english us translation + /// + /// Comment : + /// This is a comment static var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "This is a comment") } """ @@ -171,7 +300,116 @@ final class DefinitionTests: XCTestCase { XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) } - + + func testGeneratedNSLocalizedStringStaticPropertyWithEmptyComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.comment = "" + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getNSLocalizedStringStaticProperty(forLang: "fr") + let propertyEn = definition.getNSLocalizedStringStaticProperty(forLang: "en") + let propertyEnUs = definition.getNSLocalizedStringStaticProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + static var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "") + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + static var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "") + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + static var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "") + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + + func testGeneratedNSLocalizedStringStaticPropertyWithNoComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getNSLocalizedStringStaticProperty(forLang: "fr") + let propertyEn = definition.getNSLocalizedStringStaticProperty(forLang: "en") + let propertyEnUs = definition.getNSLocalizedStringStaticProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + static var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "C'est la traduction francaise", comment: "") + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + static var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english translation", comment: "") + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + static var definition_name: String { + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "") + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + func testGeneratedNSLocalizedStringPropertyWithOneArgument() { // Given let definition = Definition(name: "definition_name") @@ -188,17 +426,23 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// Welcome "%@" ! + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" !", comment: "This is a comment") } /// Translation in fr : /// Welcome "%@" ! + /// + /// Comment : + /// This is a comment func definition_name(arg0: String) -> String { String(format: self.definition_name, arg0) } """ - + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) } @@ -218,12 +462,18 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// Welcome "%@" ! Your age is %d :) Your weight is %f ;-) + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" ! Your age is %d :) Your weight is %f ;-)", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Welcome \"%@\" ! Your age is %d :) Your weight is %f ;-)", comment: "This is a comment") } /// Translation in fr : /// Welcome "%@" ! Your age is %d :) Your weight is %f ;-) + /// + /// Comment : + /// This is a comment func definition_name(arg0: String, arg1: Int, arg2: Double) -> String { String(format: self.definition_name, arg0, arg1, arg2) } @@ -249,12 +499,18 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// Vous %%: %1$@ %2$@ Age: %3$d + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Vous %%: %1$@ %2$@ Age: %3$d", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "Vous %%: %1$@ %2$@ Age: %3$d", comment: "This is a comment") } /// Translation in fr : /// Vous %%: %1$@ %2$@ Age: %3$d + /// + /// Comment : + /// This is a comment func definition_name(arg0: String, arg1: String, arg2: Int) -> String { String(format: self.definition_name, arg0, arg1, arg2) } @@ -263,12 +519,18 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// You %%: %2$@ %1$@ Age: %3$d + /// + /// Comment : + /// This is a comment var definition_name: String { - NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "") + NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "You %%: %2$@ %1$@ Age: %3$d", comment: "This is a comment") } /// Translation in en : /// You %%: %2$@ %1$@ Age: %3$d + /// + /// Comment : + /// This is a comment func definition_name(arg0: String, arg1: String, arg2: Int) -> String { String(format: self.definition_name, arg0, arg1, arg2) } @@ -300,6 +562,9 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// This is a comment var definition_name: String { "C'est la traduction francaise" } @@ -308,6 +573,9 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// This is a comment var definition_name: String { "This is the english translation" } @@ -316,6 +584,9 @@ final class DefinitionTests: XCTestCase { let expectEnUs = """ /// Translation in en-us : /// This is the english us translation + /// + /// Comment : + /// This is a comment var definition_name: String { "This is the english us translation" } @@ -325,7 +596,118 @@ final class DefinitionTests: XCTestCase { XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) } - + + func testGeneratedRawPropertyWithEmptyComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.comment = "" + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getProperty(forLang: "fr") + let propertyEn = definition.getProperty(forLang: "en") + let propertyEnUs = definition.getProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + var definition_name: String { + "This is the english us translation" + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + + func testGeneratedRawPropertyWithNoComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getProperty(forLang: "fr") + let propertyEn = definition.getProperty(forLang: "en") + let propertyEnUs = definition.getProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + var definition_name: String { + "This is the english us translation" + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + + // MARK: - Raw static properties + func testGeneratedRawStaticProperty() { // Given let definition = Definition(name: "definition_name") @@ -346,6 +728,9 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// This is a comment static var definition_name: String { "C'est la traduction francaise" } @@ -354,7 +739,10 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation - static var definition_name: String { + /// + /// Comment : + /// This is a comment + static var definition_name: String { "This is the english translation" } """ @@ -362,6 +750,9 @@ final class DefinitionTests: XCTestCase { let expectEnUs = """ /// Translation in en-us : /// This is the english us translation + /// + /// Comment : + /// This is a comment static var definition_name: String { "This is the english us translation" } @@ -371,4 +762,113 @@ final class DefinitionTests: XCTestCase { XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) } + + func testGeneratedRawStaticPropertyWithEmptyComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.comment = "" + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getStaticProperty(forLang: "fr") + let propertyEn = definition.getStaticProperty(forLang: "en") + let propertyEnUs = definition.getStaticProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + static var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + static var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + static var definition_name: String { + "This is the english us translation" + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } + + func testGeneratedRawStaticPropertyWithNoComment() { + // Given + let definition = Definition(name: "definition_name") + definition.tags = ["ios","iosonly","notranslation"] + definition.translations = [ + "fr": "C'est la traduction francaise", + "en": "This is the english translation", + "en-us": "This is the english us translation" + ] + + // When + let propertyFr = definition.getStaticProperty(forLang: "fr") + let propertyEn = definition.getStaticProperty(forLang: "en") + let propertyEnUs = definition.getStaticProperty(forLang: "en-us") + + // Expect + let expectFr = """ + /// Translation in fr : + /// C'est la traduction francaise + /// + /// Comment : + /// No comment + static var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + /// + /// Comment : + /// No comment + static var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + /// + /// Comment : + /// No comment + static var definition_name: String { + "This is the english us translation" + } + """ + + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(propertyEn.adaptForXCTest(), expectEn.adaptForXCTest()) + XCTAssertEqual(propertyEnUs.adaptForXCTest(), expectEnUs.adaptForXCTest()) + } } diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 764e5af..dec6627 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -1,6 +1,6 @@ // // StringsFileGeneratorTests.swift -// +// // // Created by Thibaut Schmitt on 06/09/2022. // @@ -12,14 +12,17 @@ import ToolCore @testable import ResgenSwift final class StringsFileGeneratorTests: XCTestCase { - - private func getDefinition(name: String, translations: [String: String], tags: [String]) -> Definition { + + private func getDefinition(name: String, translations: [String: String], tags: [String], comment: String? = nil) -> Definition { let definition = Definition(name: name) definition.tags = tags definition.translations = translations + definition.comment = comment return definition } - + + // MARK: - Strings File Content + func testGenerateStringsFileContent() { // Given let sectionOne = Section(name: "section_one") @@ -33,7 +36,7 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section One - Definition Two"], tags: ["ios","iosonly"]) ] - + let sectionTwo = Section(name: "section_two") sectionTwo.definitions = [ getDefinition(name: "s2_def_one", @@ -44,7 +47,7 @@ final class StringsFileGeneratorTests: XCTestCase { translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] - + // When let stringsFileContentFr = StringsFileGenerator.generateStringsFileContent(lang: "fr", defaultLang: "fr", @@ -54,7 +57,7 @@ final class StringsFileGeneratorTests: XCTestCase { defaultLang: "fr", tags: ["ios", "iosonly", "notranslation"], sections: [sectionOne, sectionTwo]) - + // Expect let expectFr = """ /** @@ -62,44 +65,845 @@ final class StringsFileGeneratorTests: XCTestCase { * Generated by ResgenSwift \(ResgenSwiftVersion) * Language: fr */ - + /********** section_one **********/ - + "s1_def_one" = "Section Un - Definition Un"; - + "s1_def_two" = "Section Un - Definition Deux"; - + /********** section_two **********/ - + "s2_def_one" = "Section Deux - Definition Un"; "s2_def_two" = "Section Deux - Definition Deux"; """ - + let expectEn = """ /** * Apple Strings File * Generated by ResgenSwift \(ResgenSwiftVersion) * Language: en */ - + /********** section_one **********/ - + "s1_def_one" = "Section One - Definition One"; - + "s1_def_two" = "Section One - Definition Two"; - + /********** section_two **********/ - + "s2_def_one" = "Section Two - Definition One"; "s2_def_two" = "Section Deux - Definition Deux"; """ - + XCTAssertEqual(stringsFileContentFr.adaptForXCTest(), expectFr.adaptForXCTest()) XCTAssertEqual(stringsFileContentEn.adaptForXCTest(), expectEn.adaptForXCTest()) } - + + func testGenerateStringsFileContentWithComment() { + // Given + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "Section Un - Definition Un", + "en": "Section One - Definition One"], + tags: ["ios","iosonly"], + comment: "This is a comment"), + getDefinition(name: "s1_def_two", + translations: ["fr": "Section Un - Definition Deux", + "en": "Section One - Definition Two"], + tags: ["ios","iosonly"], + comment: "This is a comment") + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "Section Deux - Definition Un", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"], + comment: "This is a comment"), + getDefinition(name: "s2_def_two", + translations: ["fr": "Section Deux - Definition Deux"], + tags: ["notranslation"], + comment: "This is a comment") + ] + + // When + let stringsFileContentFr = StringsFileGenerator.generateStringsFileContent(lang: "fr", + defaultLang: "fr", + tags: ["ios", "iosonly", "notranslation"], + sections: [sectionOne, sectionTwo]) + let stringsFileContentEn = StringsFileGenerator.generateStringsFileContent(lang: "en", + defaultLang: "fr", + tags: ["ios", "iosonly", "notranslation"], + sections: [sectionOne, sectionTwo]) + + // Expect + let expectFr = """ + /** + * Apple Strings File + * Generated by ResgenSwift \(ResgenSwiftVersion) + * Language: fr + */ + + /********** section_one **********/ + + "s1_def_one" = "Section Un - Definition Un"; + + "s1_def_two" = "Section Un - Definition Deux"; + + /********** section_two **********/ + + "s2_def_one" = "Section Deux - Definition Un"; + + "s2_def_two" = "Section Deux - Definition Deux"; + """ + + let expectEn = """ + /** + * Apple Strings File + * Generated by ResgenSwift \(ResgenSwiftVersion) + * Language: en + */ + + /********** section_one **********/ + + "s1_def_one" = "Section One - Definition One"; + + "s1_def_two" = "Section One - Definition Two"; + + /********** section_two **********/ + + "s2_def_one" = "Section Two - Definition One"; + + "s2_def_two" = "Section Deux - Definition Deux"; + """ + + XCTAssertEqual(stringsFileContentFr.adaptForXCTest(), expectFr.adaptForXCTest()) + XCTAssertEqual(stringsFileContentEn.adaptForXCTest(), expectEn.adaptForXCTest()) + } + + // MARK: - XcString File Content + + func testGenerateXcStringsRootObject() { + // Given + + // [[section_one]] + // [s1_def_one] + // fr = Section Un - Definition Un + // en = Section One - Definition One + // tags = ios,iosonly + // comments = + // [s1_def_two] + // fr = Section Un - Definition Deux + // en = Section One - Definition Two + // tags = ios,iosonly + // comments = + // + // [[section_two] + // [s2_def_one] + // fr = Section Deux - Definition Un + // en = Section Two - Definition One + // tags = ios,iosonly + // comments = + // [s2_def_two] + // fr = Section Deux - Definition deux + // en = Section Two - Definition Two + // tags = notranslation + // comments = + + + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "Section Un - Definition Un", + "en": "Section One - Definition One"], + tags: ["ios","iosonly"]), + getDefinition(name: "s1_def_two", + translations: ["fr": "Section Un - Definition Deux", + "en": "Section One - Definition Two"], + tags: ["ios","iosonly"]) + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "Section Deux - Definition Un", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"]), + getDefinition(name: "s2_def_two", + translations: ["fr": "Section Deux - Definition Deux", + "en": "Section Two - Definition Two"], + tags: ["notranslation"]) + ] + + // When + let rootObject = StringsFileGenerator.generateRootObject( + langs: ["fr", "en"], + defaultLang: "en", + tags: ["ios", "iosonly", "notranslation"], + sections: [sectionOne, sectionTwo] + ) + + // Expect + let expect = + Root( + sourceLanguage: "en", + strings: XCStringDefinitionContainer( + strings: [ + XCStringDefinition( + title: "s1_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section One - Definition One" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Un - Definition Un" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s1_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section One - Definition Two" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Un - Definition Deux" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s2_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition One" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Deux - Definition Un" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s2_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition Two" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition Two" + ) + ) + ) + ] + ) + ) + ) + ] + ), + version: "1.0" + ) + + XCTAssertEqual(rootObject, expect) + } + + func testGenerateXcStringsRootObjectWithEmptyTranslations() { + // Given + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "", + "en": "Section One - Definition One"], + tags: ["ios","iosonly"]), + getDefinition(name: "s1_def_two", + translations: ["fr": "", + "en": "Section One - Definition Two"], + tags: ["ios","iosonly"]) + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"]), + getDefinition(name: "s2_def_two", + translations: ["en": "Section Two - Definition Two"], + tags: ["notranslation"]) + ] + + // When + let rootObject = StringsFileGenerator.generateRootObject( + langs: ["fr", "en"], + defaultLang: "en", + tags: ["ios", "iosonly", "notranslation"], + sections: [sectionOne, sectionTwo] + ) + + // [[section_one]] + // [s1_def_one] + // fr = + // en = Section One - Definition One + // tags = ios,iosonly + // comments = + // [s1_def_two] + // fr = + // en = Section One - Definition Two + // tags = ios,iosonly + // comments = + // + // [[section_two] + // [s2_def_one] + // fr = + // en = Section Two - Definition One + // tags = ios,iosonly + // comments = + // [s2_def_two] + // en = Section Two - Definition Two + // tags = notranslation + // comments = + + // Expect + let expect = + Root( + sourceLanguage: "en", + strings: XCStringDefinitionContainer( + strings: [ + XCStringDefinition( + title: "s1_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section One - Definition One" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s1_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section One - Definition Two" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s2_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition One" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s2_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition Two" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition Two" + ) + ) + ) + ] + ) + ) + ) + ] + ), + version: "1.0" + ) + + XCTAssertEqual(rootObject, expect) + } + + func testGenerateXcStringsRootObjectWithNoTranslations() { + // Given + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "", + "en": ""], + tags: ["ios","iosonly"]), + getDefinition(name: "s1_def_two", + translations: ["fr": "", + "en": ""], + tags: ["ios","iosonly"]) + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "", + "en": ""], + tags: ["ios","iosonly"]), + getDefinition(name: "s2_def_two", + translations: ["fr": "", + "en": ""], + tags: ["notranslation"]) + ] + + // When + let rootObject = StringsFileGenerator.generateRootObject( + langs: ["fr", "en"], + defaultLang: "en", + tags: ["ios", "iosonly", "notranslation"], + sections: [sectionOne, sectionTwo] + ) + + // [[section_one]] + // [s1_def_one] + // fr = + // en = + // tags = ios,iosonly + // comments = + // [s1_def_two] + // fr = + // en = + // tags = ios,iosonly + // comments = + // + // [[section_two] + // [s2_def_one] + // fr = + // en = + // tags = ios,iosonly + // comments = + // [s2_def_two] + // fr = + // en = + // tags = ios,iosonly + // comments = + + // Expect + let expect = + Root( + sourceLanguage: "en", + strings: XCStringDefinitionContainer( + strings: [ + XCStringDefinition( + title: "s1_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [] + ) + ) + ), + XCStringDefinition( + title: "s1_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [] + ) + ) + ), + XCStringDefinition( + title: "s2_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [] + ) + ) + ), + XCStringDefinition( + title: "s2_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [] + ) + ) + ) + ] + ), + version: "1.0" + ) + + XCTAssertEqual(rootObject, expect) + } + + func testGenerateXcStringsRootObjectWithComments() { + // Given + + // [[section_one]] + // [s1_def_one] + // fr = Section Un - Definition Un + // en = Section One - Definition One + // tags = ios,iosonly + // comments = Comment 1 + // [s1_def_two] + // fr = Section Un - Definition Deux + // en = Section One - Definition Two + // tags = ios,iosonly + // comments = Comment 2 + // + // [[section_two] + // [s2_def_one] + // fr = Section Deux - Definition Un + // en = Section Two - Definition One + // tags = ios,iosonly + // comments = + // [s2_def_two] + // fr = Section Deux - Definition deux + // en = Section Two - Definition Two + // tags = notranslation + // comments = + + + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "Section Un - Definition Un", + "en": "Section One - Definition One"], + tags: ["ios","iosonly"], + comment: "Comment 1"), + getDefinition(name: "s1_def_two", + translations: ["fr": "Section Un - Definition Deux", + "en": "Section One - Definition Two"], + tags: ["ios","iosonly"], + comment: "Comment 2") + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "Section Deux - Definition Un", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"]), + getDefinition(name: "s2_def_two", + translations: ["fr": "Section Deux - Definition Deux"], + tags: ["notranslation"]) + ] + + // When + let rootObject = StringsFileGenerator.generateRootObject( + langs: ["fr", "en"], + defaultLang: "fr", + tags: ["ios", "iosonly", "notranslation"], + sections: [sectionOne, sectionTwo] + ) + + // Expect + let expect = + Root( + sourceLanguage: "fr", + strings: XCStringDefinitionContainer( + strings: [ + XCStringDefinition( + title: "s1_def_one", + content: XCStringDefinitionContent( + comment: "Comment 1", + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section One - Definition One" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Un - Definition Un" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s1_def_two", + content: XCStringDefinitionContent( + comment: "Comment 2", + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section One - Definition Two" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Un - Definition Deux" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s2_def_one", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Two - Definition One" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Deux - Definition Un" + ) + ) + ) + ] + ) + ) + ), + XCStringDefinition( + title: "s2_def_two", + content: XCStringDefinitionContent( + extractionState: "manual", + localizations: XCStringLocalizationContainer( + localizations: [ + XCStringLocalization( + lang: "en", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Deux - Definition Deux" + ) + ) + ), + XCStringLocalization( + lang: "fr", + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit( + state: "translated", + value: "Section Deux - Definition Deux" + ) + ) + ) + ] + ) + ) + ) + ] + ), + version: "1.0" + ) + + // """ + // { + // "sourceLanguage" : "en", + // "strings" : { + // "s1_def_one" : { + // "extractionState" : "manual", + // "localizations" : { + // "en" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section One - Definition One" + // } + // }, + // "fr" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section Un - Definition Un" + // } + // } + // } + // }, + // "s1_def_two" : { + // "extractionState" : "manual", + // "localizations" : { + // "en" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section One - Definition Two" + // } + // }, + // "fr" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section Un - Definition Deux" + // } + // } + // } + // }, + // "s2_def_one" : { + // "extractionState" : "manual", + // "localizations" : { + // "en" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section Two - Definition One" + // } + // }, + // "fr" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section Deux - Definition Une" + // } + // } + // } + // }, + // "s2_def_two" : { + // "extractionState" : "manual", + // "localizations" : { + // "en" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section Two - Definition Two" + // } + // }, + // "fr" : { + // "stringUnit" : { + // "state" : "translated", + // "value" : "Section Deux - Definition Deux" + // } + // } + // } + // } + // }, + // "version" : "1.0" + // } + // """ + XCTAssertEqual(rootObject, expect) + } + + // MARK: - Extension Content func testGeneratedExtensionContent() { // Given let sectionOne = Section(name: "section_one") @@ -113,7 +917,7 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section One - Definition Two"], tags: ["ios","iosonly"]) ] - + let sectionTwo = Section(name: "section_two") sectionTwo.definitions = [ getDefinition(name: "s2_def_one", @@ -124,7 +928,7 @@ final class StringsFileGeneratorTests: XCTestCase { translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] - + // When let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo], defaultLang: "fr", @@ -133,23 +937,23 @@ final class StringsFileGeneratorTests: XCTestCase { inputFilename: "myInputFilename", extensionName: "GenStrings", extensionSuffix: "strings") - + // Expect let expect = """ // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion) - + import UIKit - + fileprivate let kStringsFileName = "myInputFilename" - + extension GenStrings { - + enum KeyStrings: String { case s1_def_one = "s1_def_one" case s1_def_two = "s1_def_two" case s2_def_one = "s2_def_one" case s2_def_two = "s2_def_two" - + var keyPath: KeyPath { switch self { case .s1_def_one: return \\GenStrings.s1_def_one @@ -159,43 +963,168 @@ final class StringsFileGeneratorTests: XCTestCase { } } } - + // MARK: - section_one - + /// Translation in fr : /// Section Un - Definition Un + /// + /// Comment : + /// No comment var s1_def_one: String { NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "") } - + /// Translation in fr : /// Section Un - Definition Deux + /// + /// Comment : + /// No comment var s1_def_two: String { NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "") } - + // MARK: - section_two - + /// Translation in fr : /// Section Deux - Definition Un + /// + /// Comment : + /// No comment var s2_def_one: String { NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "") } - + /// Translation in fr : /// Section Deux - Definition Deux + /// + /// Comment : + /// No comment var s2_def_two: String { NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "") } } """ - + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) } - + + func testGeneratedExtensionContentWithComment() { + // Given + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "Section Un - Definition Un", + "en": "Section One - Definition One"], + tags: ["ios","iosonly"], + comment: "This is a comment"), + getDefinition(name: "s1_def_two", + translations: ["fr": "Section Un - Definition Deux", + "en": "Section One - Definition Two"], + tags: ["ios","iosonly"], + comment: "This is a comment") + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "Section Deux - Definition Un", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"], + comment: "This is a comment"), + getDefinition(name: "s2_def_two", + translations: ["fr": "Section Deux - Definition Deux"], + tags: ["notranslation"], + comment: "This is a comment") + ] + + // When + let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo], + defaultLang: "fr", + tags: ["ios", "iosonly", "notranslation"], + staticVar: false, + inputFilename: "myInputFilename", + extensionName: "GenStrings", + extensionSuffix: "strings") + + // Expect + let expect = """ + // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion) + + import UIKit + + fileprivate let kStringsFileName = "myInputFilename" + + extension GenStrings { + + enum KeyStrings: String { + case s1_def_one = "s1_def_one" + case s1_def_two = "s1_def_two" + case s2_def_one = "s2_def_one" + case s2_def_two = "s2_def_two" + + var keyPath: KeyPath { + switch self { + case .s1_def_one: return \\GenStrings.s1_def_one + case .s1_def_two: return \\GenStrings.s1_def_two + case .s2_def_one: return \\GenStrings.s2_def_one + case .s2_def_two: return \\GenStrings.s2_def_two + } + } + } + + // MARK: - section_one + + /// Translation in fr : + /// Section Un - Definition Un + /// + /// Comment : + /// This is a comment + var s1_def_one: String { + NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "This is a comment") + } + + /// Translation in fr : + /// Section Un - Definition Deux + /// + /// Comment : + /// This is a comment + var s1_def_two: String { + NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "This is a comment") + } + + // MARK: - section_two + + /// Translation in fr : + /// Section Deux - Definition Un + /// + /// Comment : + /// This is a comment + var s2_def_one: String { + NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "This is a comment") + } + + /// Translation in fr : + /// Section Deux - Definition Deux + /// + /// Comment : + /// This is a comment + var s2_def_two: String { + NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "This is a comment") + } + } + """ + + if extensionContent != expect { + print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) + } + XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) + } + + // MARK: - Extension Content Static func testGeneratedExtensionContentWithStaticVar() { // Given let sectionOne = Section(name: "section_one") @@ -209,7 +1138,7 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section One - Definition Two"], tags: ["ios","iosonly"]) ] - + let sectionTwo = Section(name: "section_two") sectionTwo.definitions = [ getDefinition(name: "s2_def_one", @@ -220,7 +1149,7 @@ final class StringsFileGeneratorTests: XCTestCase { translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] - + // When let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo], defaultLang: "fr", @@ -229,23 +1158,23 @@ final class StringsFileGeneratorTests: XCTestCase { inputFilename: "myInputFilename", extensionName: "GenStrings", extensionSuffix: "strings") - + // Expect let expect = """ // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion) - + import UIKit - + fileprivate let kStringsFileName = "myInputFilename" - + extension GenStrings { - + enum KeyStrings: String { case s1_def_one = "s1_def_one" case s1_def_two = "s1_def_two" case s2_def_one = "s2_def_one" case s2_def_two = "s2_def_two" - + var keyPath: KeyPath { switch self { case .s1_def_one: return \\GenStrings.s1_def_one @@ -255,37 +1184,161 @@ final class StringsFileGeneratorTests: XCTestCase { } } } - + // MARK: - section_one - + /// Translation in fr : /// Section Un - Definition Un + /// + /// Comment : + /// No comment static var s1_def_one: String { NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "") } - + /// Translation in fr : /// Section Un - Definition Deux + /// + /// Comment : + /// No comment static var s1_def_two: String { NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "") } - + // MARK: - section_two - + /// Translation in fr : /// Section Deux - Definition Un + /// + /// Comment : + /// No comment static var s2_def_one: String { NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "") } - + /// Translation in fr : /// Section Deux - Definition Deux + /// + /// Comment : + /// No comment static var s2_def_two: String { NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "") } } """ - + + if extensionContent != expect { + print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) + } + XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) + } + + func testGeneratedExtensionContentWithStaticVarWithComment() { + // Given + let sectionOne = Section(name: "section_one") + sectionOne.definitions = [ + getDefinition(name: "s1_def_one", + translations: ["fr": "Section Un - Definition Un", + "en": "Section One - Definition One"], + tags: ["ios","iosonly"], + comment: "This is a comment"), + getDefinition(name: "s1_def_two", + translations: ["fr": "Section Un - Definition Deux", + "en": "Section One - Definition Two"], + tags: ["ios","iosonly"], + comment: "This is a comment") + ] + + let sectionTwo = Section(name: "section_two") + sectionTwo.definitions = [ + getDefinition(name: "s2_def_one", + translations: ["fr": "Section Deux - Definition Un", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"], + comment: "This is a comment"), + getDefinition(name: "s2_def_two", + translations: ["fr": "Section Deux - Definition Deux"], + tags: ["notranslation"], + comment: "This is a comment") + ] + + // When + let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo], + defaultLang: "fr", + tags: ["ios", "iosonly", "notranslation"], + staticVar: true, + inputFilename: "myInputFilename", + extensionName: "GenStrings", + extensionSuffix: "strings") + + // Expect + let expect = """ + // Generated by ResgenSwift.Strings.Stringium \(ResgenSwiftVersion) + + import UIKit + + fileprivate let kStringsFileName = "myInputFilename" + + extension GenStrings { + + enum KeyStrings: String { + case s1_def_one = "s1_def_one" + case s1_def_two = "s1_def_two" + case s2_def_one = "s2_def_one" + case s2_def_two = "s2_def_two" + + var keyPath: KeyPath { + switch self { + case .s1_def_one: return \\GenStrings.s1_def_one + case .s1_def_two: return \\GenStrings.s1_def_two + case .s2_def_one: return \\GenStrings.s2_def_one + case .s2_def_two: return \\GenStrings.s2_def_two + } + } + } + + // MARK: - section_one + + /// Translation in fr : + /// Section Un - Definition Un + /// + /// Comment : + /// This is a comment + static var s1_def_one: String { + NSLocalizedString("s1_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Un", comment: "This is a comment") + } + + /// Translation in fr : + /// Section Un - Definition Deux + /// + /// Comment : + /// This is a comment + static var s1_def_two: String { + NSLocalizedString("s1_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Un - Definition Deux", comment: "This is a comment") + } + + // MARK: - section_two + + /// Translation in fr : + /// Section Deux - Definition Un + /// + /// Comment : + /// This is a comment + static var s2_def_one: String { + NSLocalizedString("s2_def_one", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Un", comment: "This is a comment") + } + + /// Translation in fr : + /// Section Deux - Definition Deux + /// + /// Comment : + /// This is a comment + static var s2_def_two: String { + NSLocalizedString("s2_def_two", tableName: kStringsFileName, bundle: Bundle.main, value: "Section Deux - Definition Deux", comment: "This is a comment") + } + } + """ + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) }