From 0bd6c3c2d49161fe36f48249a7d8fe1cc6f8b898 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Thu, 11 Apr 2024 10:16:28 +0200 Subject: [PATCH 01/11] Correction des commentaires des strings --- .../Strings/Model/Definition.swift | 112 ++++- .../Strings/DefinitionTests.swift | 418 +++++++++++++++++- .../Strings/StringsFileGeneratorTests.swift | 305 ++++++++++++- 3 files changed, 792 insertions(+), 43 deletions(-) diff --git a/Sources/ResgenSwift/Strings/Model/Definition.swift b/Sources/ResgenSwift/Strings/Model/Definition.swift index 6bb8cb7..4daaafa 100644 --- a/Sources/ResgenSwift/Strings/Model/Definition.swift +++ b/Sources/ResgenSwift/Strings/Model/Definition.swift @@ -84,26 +84,56 @@ class Definition { 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 getBaseProperty(lang: String, translation: String, isStatic: Bool, comment: String?) -> String { + + if let comment, !comment.isEmpty { + return + """ + /// Translation in \(lang) : + /// \(translation) + /// \(comment) + \(isStatic ? "static ": "")var \(name): String { + NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment)") + } + """ + } + + return + """ + /// 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: ", "))) - } - """ + private func getBaseMethod(lang: String, translation: String, isStatic: Bool, inputParameters: [String], translationArguments: [String], comment: String?) -> String { + + if let comment, !comment.isEmpty { + return + """ + + + /// Translation in \(lang) : + /// \(translation) + /// \(comment) + \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { + String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) + } + """ + } + + return + """ + + + /// 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 { @@ -114,8 +144,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 +158,8 @@ class Definition { translation: translation, isStatic: false, inputParameters: parameters.inputParameters, - translationArguments: parameters.translationArguments) + translationArguments: parameters.translationArguments, + comment: self.comment) } return property + method @@ -137,7 +173,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 +187,8 @@ class Definition { translation: translation, isStatic: true, inputParameters: parameters.inputParameters, - translationArguments: parameters.translationArguments) + translationArguments: parameters.translationArguments, + comment: self.comment) } return property + method @@ -160,7 +202,18 @@ class Definition { print(error.description) Stringium.exit(withError: error) } - + + if let comment, !comment.isEmpty { + return """ + /// Translation in \(lang) : + /// \(translation) + /// \(comment) + var \(name): String { + "\(translation)" + } + """ + } + return """ /// Translation in \(lang) : /// \(translation) @@ -177,6 +230,17 @@ class Definition { Stringium.exit(withError: error) } + if let comment, !comment.isEmpty { + return """ + /// Translation in \(lang) : + /// \(translation) + /// \(comment) + static var \(name): String { + "\(translation)" + } + """ + } + return """ /// Translation in \(lang) : /// \(translation) diff --git a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift index f61087a..bcd0d81 100644 --- a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift +++ b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift @@ -100,24 +100,27 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// 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 + /// 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 + /// 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 +128,100 @@ 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 + 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 + 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 + 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 + 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 + 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 + 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 +242,27 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// 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 + /// 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 + /// 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 +270,98 @@ 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 + 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 + 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 + 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 + 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 + 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 + 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 +378,19 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// Welcome "%@" ! + /// 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 "%@" ! + /// This is a comment func definition_name(arg0: String) -> String { String(format: self.definition_name, arg0) } """ - + XCTAssertEqual(propertyFr.adaptForXCTest(), expectFr.adaptForXCTest()) } @@ -218,12 +410,14 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// Welcome "%@" ! Your age is %d :) Your weight is %f ;-) + /// 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 ;-) + /// This is a comment func definition_name(arg0: String, arg1: Int, arg2: Double) -> String { String(format: self.definition_name, arg0, arg1, arg2) } @@ -249,12 +443,14 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// Vous %%: %1$@ %2$@ Age: %3$d + /// 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 + /// This is a comment func definition_name(arg0: String, arg1: String, arg2: Int) -> String { String(format: self.definition_name, arg0, arg1, arg2) } @@ -263,12 +459,14 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// You %%: %2$@ %1$@ Age: %3$d + /// 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 + /// This is a comment func definition_name(arg0: String, arg1: String, arg2: Int) -> String { String(format: self.definition_name, arg0, arg1, arg2) } @@ -300,6 +498,7 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// This is a comment var definition_name: String { "C'est la traduction francaise" } @@ -308,6 +507,7 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// This is a comment var definition_name: String { "This is the english translation" } @@ -316,6 +516,7 @@ final class DefinitionTests: XCTestCase { let expectEnUs = """ /// Translation in en-us : /// This is the english us translation + /// This is a comment var definition_name: String { "This is the english us translation" } @@ -325,7 +526,100 @@ 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 + var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + 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 + var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + 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 +640,7 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// This is a comment static var definition_name: String { "C'est la traduction francaise" } @@ -354,7 +649,8 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation - static var definition_name: String { + /// This is a comment + static var definition_name: String { "This is the english translation" } """ @@ -362,6 +658,7 @@ final class DefinitionTests: XCTestCase { let expectEnUs = """ /// Translation in en-us : /// This is the english us translation + /// This is a comment static var definition_name: String { "This is the english us translation" } @@ -371,4 +668,95 @@ 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 + static var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + static var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + 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 + static var definition_name: String { + "C'est la traduction francaise" + } + """ + + let expectEn = """ + /// Translation in en : + /// This is the english translation + static var definition_name: String { + "This is the english translation" + } + """ + + let expectEnUs = """ + /// Translation in en-us : + /// This is the english us translation + 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..7df4438 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -13,13 +13,16 @@ import ToolCore 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") @@ -99,7 +102,92 @@ final class StringsFileGeneratorTests: XCTestCase { 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: - Extension Content func testGeneratedExtensionContent() { // Given let sectionOne = Section(name: "section_one") @@ -195,7 +283,112 @@ final class StringsFileGeneratorTests: XCTestCase { } 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 + /// 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 + /// 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 + /// 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 + /// 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") @@ -291,5 +484,109 @@ final class StringsFileGeneratorTests: XCTestCase { } 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 + /// 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 + /// 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 + /// 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 + /// 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)) + } + XCTAssertEqual(extensionContent.adaptForXCTest(), expect.adaptForXCTest()) + } } -- 2.39.5 From d21ad9d1ea58bf82c076ac32085dcdd2816cd042 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Thu, 11 Apr 2024 10:19:10 +0200 Subject: [PATCH 02/11] Update JenkinsFile Xcode version --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 -- 2.39.5 From 55264d61ad973b3cfa60793fb191380d8d7d25d3 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Thu, 11 Apr 2024 11:18:57 +0200 Subject: [PATCH 03/11] Modification de l'affichage des commentaires --- .../Strings/Model/Definition.swift | 9 +++++ .../Strings/DefinitionTests.swift | 40 +++++++++++++++++++ .../Strings/StringsFileGeneratorTests.swift | 16 ++++++++ 3 files changed, 65 insertions(+) diff --git a/Sources/ResgenSwift/Strings/Model/Definition.swift b/Sources/ResgenSwift/Strings/Model/Definition.swift index 4daaafa..380bde0 100644 --- a/Sources/ResgenSwift/Strings/Model/Definition.swift +++ b/Sources/ResgenSwift/Strings/Model/Definition.swift @@ -91,6 +91,8 @@ class Definition { """ /// Translation in \(lang) : /// \(translation) + /// + /// Comment : /// \(comment) \(isStatic ? "static ": "")var \(name): String { NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment)") @@ -117,6 +119,8 @@ class Definition { /// Translation in \(lang) : /// \(translation) + /// + /// Comment : /// \(comment) \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) @@ -207,7 +211,10 @@ class Definition { return """ /// Translation in \(lang) : /// \(translation) + /// + /// Comment : /// \(comment) + var \(name): String { "\(translation)" } @@ -234,6 +241,8 @@ class Definition { return """ /// Translation in \(lang) : /// \(translation) + /// + /// Comment : /// \(comment) static var \(name): String { "\(translation)" diff --git a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift index bcd0d81..9d477a3 100644 --- a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift +++ b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift @@ -100,6 +100,8 @@ 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: "This is a comment") @@ -109,6 +111,8 @@ final class DefinitionTests: XCTestCase { 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: "This is a comment") @@ -118,6 +122,8 @@ 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 { NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "This is a comment") @@ -242,6 +248,8 @@ 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: "This is a comment") @@ -251,6 +259,8 @@ final class DefinitionTests: XCTestCase { 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: "This is a comment") @@ -260,6 +270,8 @@ 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 { NSLocalizedString("definition_name", tableName: kStringsFileName, bundle: Bundle.main, value: "This is the english us translation", comment: "This is a comment") @@ -378,6 +390,8 @@ 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: "This is a comment") @@ -385,6 +399,8 @@ final class DefinitionTests: XCTestCase { /// Translation in fr : /// Welcome "%@" ! + /// + /// Comment : /// This is a comment func definition_name(arg0: String) -> String { String(format: self.definition_name, arg0) @@ -410,6 +426,8 @@ 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: "This is a comment") @@ -417,6 +435,8 @@ final class DefinitionTests: XCTestCase { /// 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) @@ -443,6 +463,8 @@ 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: "This is a comment") @@ -450,6 +472,8 @@ final class DefinitionTests: XCTestCase { /// 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) @@ -459,6 +483,8 @@ 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: "This is a comment") @@ -466,6 +492,8 @@ final class DefinitionTests: XCTestCase { /// 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) @@ -498,6 +526,8 @@ 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" @@ -507,6 +537,8 @@ 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" @@ -516,6 +548,8 @@ 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" @@ -640,6 +674,8 @@ 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" @@ -649,6 +685,8 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : /// This is a comment static var definition_name: String { "This is the english translation" @@ -658,6 +696,8 @@ 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" diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 7df4438..747d14e 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -352,6 +352,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -359,6 +361,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -368,6 +372,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -375,6 +381,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -553,6 +561,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -560,6 +570,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -569,6 +581,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") @@ -576,6 +590,8 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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") -- 2.39.5 From 5d4e4619334b35018f7fa0e4cd7cc1570a12950f Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Thu, 11 Apr 2024 14:20:54 +0200 Subject: [PATCH 04/11] =?UTF-8?q?Affichage=20du=20commentaire=20m=C3=AAme?= =?UTF-8?q?=20si=20nil=20ou=20empty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Strings/Model/Definition.swift | 94 +++++-------------- .../Strings/DefinitionTests.swift | 72 ++++++++++++++ .../Strings/StringsFileGeneratorTests.swift | 24 +++++ 3 files changed, 120 insertions(+), 70 deletions(-) diff --git a/Sources/ResgenSwift/Strings/Model/Definition.swift b/Sources/ResgenSwift/Strings/Model/Definition.swift index 380bde0..d985e34 100644 --- a/Sources/ResgenSwift/Strings/Model/Definition.swift +++ b/Sources/ResgenSwift/Strings/Model/Definition.swift @@ -86,58 +86,32 @@ class Definition { private func getBaseProperty(lang: String, translation: String, isStatic: Bool, comment: String?) -> String { - if let comment, !comment.isEmpty { - return - """ - /// Translation in \(lang) : - /// \(translation) - /// - /// Comment : - /// \(comment) - \(isStatic ? "static ": "")var \(name): String { - NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment)") - } - """ - } + """ + /// Translation in \(lang) : + /// \(translation) + /// + /// Comment : + /// \((comment ?? "").isEmpty ? "No comment" : comment!) + \(isStatic ? "static ": "")var \(name): String { + NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment ?? "")") + } + """ - return - """ - /// 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], comment: String?) -> String { - if let comment, !comment.isEmpty { - return - """ + """ - - /// Translation in \(lang) : - /// \(translation) - /// - /// Comment : - /// \(comment) - \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { - String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) - } - """ - } - - return - """ - - - /// Translation in \(lang) : - /// \(translation) - \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { - String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) - } - """ + /// Translation in \(lang) : + /// \(translation) + /// + /// Comment : + /// \((comment ?? "").isEmpty ? "No comment" : comment!) + \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { + String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) + } + """ } func getNSLocalizedStringProperty(forLang lang: String) -> String { @@ -207,27 +181,17 @@ class Definition { Stringium.exit(withError: error) } - if let comment, !comment.isEmpty { - return """ + return """ /// Translation in \(lang) : /// \(translation) /// /// Comment : - /// \(comment) + /// \((comment ?? "").isEmpty ? "No comment" : comment!) var \(name): String { "\(translation)" } """ - } - - return """ - /// Translation in \(lang) : - /// \(translation) - var \(name): String { - "\(translation)" - } - """ } func getStaticProperty(forLang lang: String) -> String { @@ -237,22 +201,12 @@ class Definition { Stringium.exit(withError: error) } - if let comment, !comment.isEmpty { - return """ + return """ /// Translation in \(lang) : /// \(translation) /// /// Comment : - /// \(comment) - static var \(name): String { - "\(translation)" - } - """ - } - - return """ - /// Translation in \(lang) : - /// \(translation) + /// \((comment ?? "").isEmpty ? "No comment" : comment!) static var \(name): String { "\(translation)" } diff --git a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift index 9d477a3..c25b3ff 100644 --- a/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift +++ b/Tests/ResgenSwiftTests/Strings/DefinitionTests.swift @@ -155,6 +155,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -163,6 +166,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -171,6 +177,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -200,6 +209,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -208,6 +220,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -216,6 +231,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -303,6 +321,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -311,6 +332,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -319,6 +343,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -348,6 +375,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -356,6 +386,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -364,6 +397,9 @@ final class DefinitionTests: XCTestCase { 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: "") } @@ -581,6 +617,9 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// No comment var definition_name: String { "C'est la traduction francaise" } @@ -589,6 +628,9 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// No comment var definition_name: String { "This is the english translation" } @@ -597,6 +639,9 @@ final class DefinitionTests: XCTestCase { 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" } @@ -626,6 +671,9 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// No comment var definition_name: String { "C'est la traduction francaise" } @@ -634,6 +682,9 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// No comment var definition_name: String { "This is the english translation" } @@ -642,6 +693,9 @@ final class DefinitionTests: XCTestCase { 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" } @@ -729,6 +783,9 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// No comment static var definition_name: String { "C'est la traduction francaise" } @@ -737,6 +794,9 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// No comment static var definition_name: String { "This is the english translation" } @@ -745,6 +805,9 @@ final class DefinitionTests: XCTestCase { 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" } @@ -774,6 +837,9 @@ final class DefinitionTests: XCTestCase { let expectFr = """ /// Translation in fr : /// C'est la traduction francaise + /// + /// Comment : + /// No comment static var definition_name: String { "C'est la traduction francaise" } @@ -782,6 +848,9 @@ final class DefinitionTests: XCTestCase { let expectEn = """ /// Translation in en : /// This is the english translation + /// + /// Comment : + /// No comment static var definition_name: String { "This is the english translation" } @@ -790,6 +859,9 @@ final class DefinitionTests: XCTestCase { 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" } diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 747d14e..2456d44 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -252,12 +252,18 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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: "") } @@ -266,12 +272,18 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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: "") } @@ -461,12 +473,18 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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: "") } @@ -475,12 +493,18 @@ final class StringsFileGeneratorTests: XCTestCase { /// 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: "") } -- 2.39.5 From 1d7fc7634075513564075b2a120f1be8f339396a Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Thu, 11 Apr 2024 15:49:07 +0200 Subject: [PATCH 05/11] Changed the condition for moe visibility --- Sources/ResgenSwift/Strings/Model/Definition.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Sources/ResgenSwift/Strings/Model/Definition.swift b/Sources/ResgenSwift/Strings/Model/Definition.swift index d985e34..b059383 100644 --- a/Sources/ResgenSwift/Strings/Model/Definition.swift +++ b/Sources/ResgenSwift/Strings/Model/Definition.swift @@ -85,13 +85,12 @@ class Definition { } private func getBaseProperty(lang: String, translation: String, isStatic: Bool, comment: String?) -> String { - """ /// Translation in \(lang) : /// \(translation) /// /// Comment : - /// \((comment ?? "").isEmpty ? "No comment" : comment!) + /// \(comment?.isEmpty == false ? comment! : "No comment") \(isStatic ? "static ": "")var \(name): String { NSLocalizedString("\(name)", tableName: kStringsFileName, bundle: Bundle.main, value: "\(translation)", comment: "\(comment ?? "")") } @@ -107,7 +106,7 @@ class Definition { /// \(translation) /// /// Comment : - /// \((comment ?? "").isEmpty ? "No comment" : comment!) + /// \(comment?.isEmpty == false ? comment! : "No comment") \(isStatic ? "static ": "")func \(name)(\(inputParameters.joined(separator: ", "))) -> String { String(format: \(isStatic ? "Self" : "self").\(name), \(translationArguments.joined(separator: ", "))) } @@ -186,7 +185,7 @@ class Definition { /// \(translation) /// /// Comment : - /// \((comment ?? "").isEmpty ? "No comment" : comment!) + /// \(comment?.isEmpty == false ? comment! : "No comment") var \(name): String { "\(translation)" @@ -206,7 +205,7 @@ class Definition { /// \(translation) /// /// Comment : - /// \((comment ?? "").isEmpty ? "No comment" : comment!) + /// \(comment?.isEmpty == false ? comment! : "No comment") static var \(name): String { "\(translation)" } -- 2.39.5 From 0d651b810fa1a963aedb23b29a9d52579c980f68 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Fri, 12 Apr 2024 16:09:54 +0200 Subject: [PATCH 06/11] =?UTF-8?q?Premi=C3=A8re=20impl=C3=A9mentation=20des?= =?UTF-8?q?=20xcstrings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Generator/StringsFileGenerator.swift | 200 +++++++--- .../ResgenSwift/Strings/Model/XcString.swift | 93 +++++ .../Strings/Stringium/Stringium.swift | 5 +- .../Strings/Stringium/StringiumOptions.swift | 5 +- .../Strings/StringsFileGeneratorTests.swift | 356 +++++++++++++++--- 5 files changed, 564 insertions(+), 95 deletions(-) create mode 100644 Sources/ResgenSwift/Strings/Model/XcString.swift diff --git a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift index 633ec7a..485ef63 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,28 +9,49 @@ 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, - defaultLang: defaultLang, - 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" + inputFilenameWithoutExt: String, + isXcString: Bool = false) { + + if !isXcString { + var stringsFilesContent = [String: String]() + for lang in langs { + stringsFilesContent[lang] = Self.generateStringsFileContent(lang: lang, + defaultLang: defaultLang, + 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 { + 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) + } + } + } else { + let fileContent: String = Self.generateXcStringsFileContent( + langs: langs, + defaultLang: defaultLang, + tags: tags, + sections: sections + ) + + let stringsFilePath = "\(outputPath)/Localizable.xcstrings" let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath) do { try fileContent.write(to: stringsFilePathURL, atomically: false, encoding: .utf8) @@ -41,7 +62,7 @@ class StringsFileGenerator { } } } - + static func generateStringsFileContent(lang: String, defaultLang: String, tags inputTags: [String], @@ -53,13 +74,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 +90,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 +109,101 @@ 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 localizationTab: [XCStringLocalization] = [] + + if definition.hasOneOrMoreMatchingTags(inputTags: inputTags) == false { + skipDefinition = true + } + + if !skipDefinition { + + for (lang, value) in definition.translations { + let localization = XCStringLocalization( + lang: lang, + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit(state: "translated", value: value) + ) + ) + + localizationTab.append(localization) + } + + let xcStringDefinition = XCStringDefinition( + title: definition.name, + content: XCStringDefinitionContent( + 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 +220,7 @@ class StringsFileGenerator { inputFilename: inputFilename, extensionName: extensionName, extensionSuffix: extensionSuffix) - + // Write content let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath) do { @@ -121,9 +231,9 @@ class StringsFileGenerator { Stringium.exit(withError: error) } } - + // MARK: - Extension content - + static func getExtensionContent(sections: [Section], defaultLang lang: String, tags: [String], @@ -139,31 +249,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 +282,7 @@ class StringsFileGenerator { enumDefinition += " case \(definition.name) = \"\(definition.name)\"\n" } } - + // KeyPath accessors enumDefinition += "\n" enumDefinition += " var keyPath: KeyPath<\(extensionClassname), String> {\n" @@ -182,7 +292,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 +304,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 +331,11 @@ class StringsFileGenerator { } .joined(separator: "\n") } - + private static func getFooter() -> String { """ } - + """ } } diff --git a/Sources/ResgenSwift/Strings/Model/XcString.swift b/Sources/ResgenSwift/Strings/Model/XcString.swift new file mode 100644 index 0000000..acee405 --- /dev/null +++ b/Sources/ResgenSwift/Strings/Model/XcString.swift @@ -0,0 +1,93 @@ +// +// 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) + } + } + } +} + +struct XCStringDefinition: Codable, Equatable { + let title: String // json key -> custom encoding methods + let content: XCStringDefinitionContent +} + +struct XCStringDefinitionContent: Codable, Equatable { + let extractionState: String + var localizations: XCStringLocalizationContainer + +} + +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) + } + } + } +} + +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..ad3db0a 100644 --- a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift +++ b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift @@ -48,8 +48,9 @@ struct Stringium: ParsableCommand { defaultLang: options.defaultLang, tags: options.tags, outputPath: options.stringsFileOutputPath, - inputFilenameWithoutExt: options.inputFilenameWithoutExt) - + inputFilenameWithoutExt: options.inputFilenameWithoutExt, + isXcString: options.isXcstring) + // Generate extension StringsFileGenerator.writeExtensionFiles(sections: sections, defaultLang: options.defaultLang, diff --git a/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift b/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift index 1fd1d53..63c2370 100644 --- a/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift +++ b/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift @@ -11,7 +11,10 @@ import ArgumentParser struct StringiumOptions: ParsableArguments { @Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation") var forceGeneration = false - + + @Flag(name: [.customShort("x"), .customLong("xcstrings")], help: "Generate xcstrings catalog") + var isXcstring = false + @Argument(help: "Input files where strings ared defined.", transform: { $0.replaceTiltWithHomeDirectoryPath() }) var inputFile: String diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 2456d44..eb55ee4 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,7 +12,7 @@ import ToolCore @testable import ResgenSwift final class StringsFileGeneratorTests: XCTestCase { - + private func getDefinition(name: String, translations: [String: String], tags: [String], comment: String? = nil) -> Definition { let definition = Definition(name: name) definition.tags = tags @@ -36,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", @@ -47,7 +47,7 @@ final class StringsFileGeneratorTests: XCTestCase { translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] - + // When let stringsFileContentFr = StringsFileGenerator.generateStringsFileContent(lang: "fr", defaultLang: "fr", @@ -57,7 +57,7 @@ final class StringsFileGeneratorTests: XCTestCase { defaultLang: "fr", tags: ["ios", "iosonly", "notranslation"], sections: [sectionOne, sectionTwo]) - + // Expect let expectFr = """ /** @@ -65,40 +65,40 @@ 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()) } @@ -187,6 +187,268 @@ final class StringsFileGeneratorTests: XCTestCase { XCTAssertEqual(stringsFileContentEn.adaptForXCTest(), expectEn.adaptForXCTest()) } + // MARK: - XcString File Content + + func testGenerateXcStringsRootObject() { + // 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"]), + 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"], + 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 = 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 = ios,iosonly + // 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" + ) + ) + ), + 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 Two - 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 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 @@ -201,7 +463,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", @@ -212,7 +474,7 @@ final class StringsFileGeneratorTests: XCTestCase { translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] - + // When let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo], defaultLang: "fr", @@ -221,23 +483,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 @@ -247,9 +509,9 @@ final class StringsFileGeneratorTests: XCTestCase { } } } - + // MARK: - section_one - + /// Translation in fr : /// Section Un - Definition Un /// @@ -258,7 +520,7 @@ final class StringsFileGeneratorTests: XCTestCase { 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 /// @@ -267,9 +529,9 @@ final class StringsFileGeneratorTests: XCTestCase { 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 /// @@ -278,7 +540,7 @@ final class StringsFileGeneratorTests: XCTestCase { 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 /// @@ -289,7 +551,7 @@ final class StringsFileGeneratorTests: XCTestCase { } } """ - + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } @@ -422,7 +684,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", @@ -433,7 +695,7 @@ final class StringsFileGeneratorTests: XCTestCase { translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] - + // When let extensionContent = StringsFileGenerator.getExtensionContent(sections: [sectionOne, sectionTwo], defaultLang: "fr", @@ -442,23 +704,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 @@ -468,9 +730,9 @@ final class StringsFileGeneratorTests: XCTestCase { } } } - + // MARK: - section_one - + /// Translation in fr : /// Section Un - Definition Un /// @@ -479,7 +741,7 @@ final class StringsFileGeneratorTests: XCTestCase { 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 /// @@ -488,9 +750,9 @@ final class StringsFileGeneratorTests: XCTestCase { 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 /// @@ -499,7 +761,7 @@ final class StringsFileGeneratorTests: XCTestCase { 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 /// @@ -510,7 +772,7 @@ final class StringsFileGeneratorTests: XCTestCase { } } """ - + if extensionContent != expect { print(prettyFirstDifferenceBetweenStrings(s1: extensionContent, s2: expect)) } -- 2.39.5 From 6c3f3a8982bdfd8ccc80d524a6209315bac1950d Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Fri, 12 Apr 2024 16:25:10 +0200 Subject: [PATCH 07/11] Correction du test testGenerateXcStringsRootObject --- .../Generator/StringsFileGenerator.swift | 1 - .../Strings/StringsFileGeneratorTests.swift | 265 ++++++++++++++++++ 2 files changed, 265 insertions(+), 1 deletion(-) diff --git a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift index 485ef63..b6786c5 100644 --- a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift +++ b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift @@ -166,7 +166,6 @@ class StringsFileGenerator { } if !skipDefinition { - for (lang, value) in definition.translations { let localization = XCStringLocalization( lang: lang, diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index eb55ee4..8910bd6 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -191,6 +191,32 @@ final class StringsFileGeneratorTests: XCTestCase { 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 = ios,iosonly + // comments = + + let sectionOne = Section(name: "section_one") sectionOne.definitions = [ getDefinition(name: "s1_def_one", @@ -209,6 +235,245 @@ final class StringsFileGeneratorTests: XCTestCase { 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 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" + // } + // """ + debugPrint(rootObject) + debugPrint(expect) + + 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": "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": "", + "en": "Section Two - Definition One"], + tags: ["ios","iosonly"]), getDefinition(name: "s2_def_two", translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) -- 2.39.5 From ba07005b13e2ca341e22e2621bc5fd06b44ff361 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Fri, 12 Apr 2024 16:45:09 +0200 Subject: [PATCH 08/11] Fix equatable properties for arrays --- Sources/ResgenSwift/Strings/Model/XcString.swift | 9 ++++++++- .../Strings/StringsFileGeneratorTests.swift | 3 --- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Sources/ResgenSwift/Strings/Model/XcString.swift b/Sources/ResgenSwift/Strings/Model/XcString.swift index acee405..c80ad7a 100644 --- a/Sources/ResgenSwift/Strings/Model/XcString.swift +++ b/Sources/ResgenSwift/Strings/Model/XcString.swift @@ -38,6 +38,10 @@ struct XCStringDefinitionContainer: Codable, Equatable { } } } + + static func == (lhs: XCStringDefinitionContainer, rhs: XCStringDefinitionContainer) -> Bool { + return lhs.strings.count == rhs.strings.count && lhs.strings.sorted(by: { $0.title < $1.title }) == rhs.strings.sorted(by: { $0.title < $1.title }) + } } struct XCStringDefinition: Codable, Equatable { @@ -48,7 +52,6 @@ struct XCStringDefinition: Codable, Equatable { struct XCStringDefinitionContent: Codable, Equatable { let extractionState: String var localizations: XCStringLocalizationContainer - } struct XCStringLocalizationContainer: Codable, Equatable { @@ -63,6 +66,10 @@ struct XCStringLocalizationContainer: Codable, Equatable { } } } + + 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 { diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 8910bd6..6c4d758 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -448,9 +448,6 @@ final class StringsFileGeneratorTests: XCTestCase { // "version" : "1.0" // } // """ - debugPrint(rootObject) - debugPrint(expect) - XCTAssertEqual(rootObject, expect) } -- 2.39.5 From 209ba49e3f802d31e9830af4176c6859b35ed9a0 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Fri, 12 Apr 2024 17:15:15 +0200 Subject: [PATCH 09/11] Gestion des commentaires --- .../Generator/StringsFileGenerator.swift | 4 +- .../ResgenSwift/Strings/Model/XcString.swift | 7 + .../Strings/StringsFileGeneratorTests.swift | 285 +++++++++++++++++- 3 files changed, 288 insertions(+), 8 deletions(-) diff --git a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift index b6786c5..c067387 100644 --- a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift +++ b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift @@ -166,7 +166,8 @@ class StringsFileGenerator { } if !skipDefinition { - for (lang, value) in definition.translations { + for (lang, value) in definition.translations where !value.isEmpty { + let localization = XCStringLocalization( lang: lang, content: XCStringLocalizationLangContent( @@ -180,6 +181,7 @@ class StringsFileGenerator { let xcStringDefinition = XCStringDefinition( title: definition.name, content: XCStringDefinitionContent( + comment: definition.comment, extractionState: "manual", localizations: XCStringLocalizationContainer( localizations: localizationTab diff --git a/Sources/ResgenSwift/Strings/Model/XcString.swift b/Sources/ResgenSwift/Strings/Model/XcString.swift index c80ad7a..b30396c 100644 --- a/Sources/ResgenSwift/Strings/Model/XcString.swift +++ b/Sources/ResgenSwift/Strings/Model/XcString.swift @@ -50,8 +50,15 @@ struct XCStringDefinition: Codable, Equatable { } 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 { diff --git a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 6c4d758..3520710 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -460,7 +460,7 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section One - Definition One"], tags: ["ios","iosonly"]), getDefinition(name: "s1_def_two", - translations: ["fr": "Section Un - Definition Deux", + translations: ["fr": "", "en": "Section One - Definition Two"], tags: ["ios","iosonly"]) ] @@ -472,7 +472,8 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section Two - Definition One"], tags: ["ios","iosonly"]), getDefinition(name: "s2_def_two", - translations: ["fr": "Section Deux - Definition Deux"], + translations: ["fr": "Section Deux - Definition Deux", + "en": "Section Two - Definition Two"], tags: ["notranslation"]) ] @@ -486,19 +487,19 @@ final class StringsFileGeneratorTests: XCTestCase { // [[section_one]] // [s1_def_one] - // fr = Section Un - Definition Un + // fr = // en = Section One - Definition One // tags = ios,iosonly // comments = // [s1_def_two] - // fr = Section Un - Definition Deux + // fr = // en = Section One - Definition Two // tags = ios,iosonly // comments = // // [[section_two] // [s2_def_one] - // fr = Section Deux - Definition Un + // fr = // en = Section Two - Definition One // tags = ios,iosonly // comments = @@ -517,6 +518,276 @@ final class StringsFileGeneratorTests: XCTestCase { 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 Deux - Definition Deux" + ) + ) + ) + ] + ) + ) + ) + ] + ), + 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 = ios,iosonly + // 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", + "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( + comment: "Comment 1", extractionState: "manual", localizations: XCStringLocalizationContainer( localizations: [ @@ -545,6 +816,7 @@ final class StringsFileGeneratorTests: XCTestCase { XCStringDefinition( title: "s1_def_two", content: XCStringDefinitionContent( + comment: "Comment 2", extractionState: "manual", localizations: XCStringLocalizationContainer( localizations: [ @@ -590,7 +862,7 @@ final class StringsFileGeneratorTests: XCTestCase { content: XCStringLocalizationLangContent( stringUnit: DefaultStringUnit( state: "translated", - value: "Section Two - Definition Un" + value: "Section Deux - Definition Un" ) ) ) @@ -707,7 +979,6 @@ final class StringsFileGeneratorTests: XCTestCase { // "version" : "1.0" // } // """ - XCTAssertEqual(rootObject, expect) } -- 2.39.5 From 27f86f5c4d967417b0f77d4f333308cdb509277b Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Mon, 15 Apr 2024 16:51:18 +0200 Subject: [PATCH 10/11] Correction de l'option pour le fichier xcstrings --- Package.resolved | 4 +- .../Generate/Model/ConfigurationFile.swift | 16 ++++- .../StringsConfiguration+Runnable.swift | 6 +- .../Generator/StringsFileGenerator.swift | 69 ++++++++++--------- .../ResgenSwift/Strings/Model/XcString.swift | 4 +- .../Strings/Stringium/Stringium.swift | 47 ++++++++----- .../Strings/Stringium/StringiumOptions.swift | 10 +-- 7 files changed, 94 insertions(+), 62 deletions(-) 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/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/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 c067387..cba1761 100644 --- a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift +++ b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift @@ -17,41 +17,21 @@ class StringsFileGenerator { defaultLang: String, tags: [String], outputPath: String, - inputFilenameWithoutExt: String, - isXcString: Bool = false) { + inputFilenameWithoutExt: String) { - if !isXcString { - var stringsFilesContent = [String: String]() - for lang in langs { - stringsFilesContent[lang] = Self.generateStringsFileContent(lang: lang, - defaultLang: defaultLang, - tags: tags, - sections: sections) - } + var stringsFilesContent = [String: String]() + for lang in langs { + stringsFilesContent[lang] = Self.generateStringsFileContent(lang: lang, + defaultLang: defaultLang, + tags: tags, + sections: sections) + } - // Write strings file content - langs.forEach { lang in - guard let fileContent = stringsFilesContent[lang] else { return } + // 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 { - 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) - } - } - } else { - let fileContent: String = Self.generateXcStringsFileContent( - langs: langs, - defaultLang: defaultLang, - tags: tags, - sections: sections - ) - - let stringsFilePath = "\(outputPath)/Localizable.xcstrings" + let stringsFilePath = "\(outputPath)/\(lang).lproj/\(inputFilenameWithoutExt).strings" let stringsFilePathURL = URL(fileURLWithPath: stringsFilePath) do { try fileContent.write(to: stringsFilePathURL, atomically: false, encoding: .utf8) @@ -63,6 +43,31 @@ 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], diff --git a/Sources/ResgenSwift/Strings/Model/XcString.swift b/Sources/ResgenSwift/Strings/Model/XcString.swift index b30396c..6c784d1 100644 --- a/Sources/ResgenSwift/Strings/Model/XcString.swift +++ b/Sources/ResgenSwift/Strings/Model/XcString.swift @@ -40,7 +40,9 @@ struct XCStringDefinitionContainer: Codable, Equatable { } static func == (lhs: XCStringDefinitionContainer, rhs: XCStringDefinitionContainer) -> Bool { - return lhs.strings.count == rhs.strings.count && lhs.strings.sorted(by: { $0.title < $1.title }) == rhs.strings.sorted(by: { $0.title < $1.title }) + return lhs.strings.sorted(by: { + $0.title < $1.title + }) == rhs.strings.sorted(by: { $0.title < $1.title }) } } diff --git a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift index ad3db0a..5ac0ecf 100644 --- a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift +++ b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift @@ -43,24 +43,37 @@ 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, - isXcString: options.isXcstring) + 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) + + // Generate extension + StringsFileGenerator.writeExtensionFiles(sections: sections, + defaultLang: options.defaultLang, + tags: options.tags, + staticVar: options.staticMembers, + inputFilename: options.inputFilenameWithoutExt, + extensionName: options.extensionName, + extensionFilePath: options.extensionFilePath, + extensionSuffix: options.extensionSuffix) + + } 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, - tags: options.tags, - staticVar: options.staticMembers, - inputFilename: options.inputFilenameWithoutExt, - 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 63c2370..7c9c7a8 100644 --- a/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift +++ b/Sources/ResgenSwift/Strings/Stringium/StringiumOptions.swift @@ -12,10 +12,7 @@ struct StringiumOptions: ParsableArguments { @Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation") var forceGeneration = false - @Flag(name: [.customShort("x"), .customLong("xcstrings")], help: "Generate xcstrings catalog") - var isXcstring = 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() }) @@ -35,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 -- 2.39.5 From fb2ddb2227120d63e61b792a391a08e2015d9de3 Mon Sep 17 00:00:00 2001 From: Quentin Bandera Date: Wed, 17 Apr 2024 09:44:09 +0200 Subject: [PATCH 11/11] =?UTF-8?q?DEVTOOLS-181=20G=C3=A9rer=20le=20tag=20no?= =?UTF-8?q?Translation=20pour=20les=20xcstrings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ResgenSwift/Generate/GenerateError.swift | 6 +- .../Parser/ConfigurationFileParser.swift | 11 ++- .../Generator/StringsFileGenerator.swift | 35 +++++-- .../Strings/Stringium/Stringium.swift | 21 ++-- .../Colors/ParsedColorTests.swift | 2 +- .../Strings/StringsFileGeneratorTests.swift | 99 ++----------------- 6 files changed, 59 insertions(+), 115 deletions(-) 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/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/Strings/Generator/StringsFileGenerator.swift b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift index cba1761..ce26ffb 100644 --- a/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift +++ b/Sources/ResgenSwift/Strings/Generator/StringsFileGenerator.swift @@ -163,6 +163,7 @@ class StringsFileGenerator { section.definitions.forEach { definition in var skipDefinition = false + var isNoTranslation = false var localizationTab: [XCStringLocalization] = [] @@ -170,17 +171,37 @@ class StringsFileGenerator { skipDefinition = true } + if definition.tags.contains(Stringium.noTranslationTag) { + isNoTranslation = true + } + if !skipDefinition { - for (lang, value) in definition.translations where !value.isEmpty { + 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) + let localization = XCStringLocalization( + lang: lang, + content: XCStringLocalizationLangContent( + stringUnit: DefaultStringUnit(state: "translated", value: value) + ) ) - ) - localizationTab.append(localization) + localizationTab.append(localization) + } } let xcStringDefinition = XCStringDefinition( diff --git a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift index 5ac0ecf..a27ebfe 100644 --- a/Sources/ResgenSwift/Strings/Stringium/Stringium.swift +++ b/Sources/ResgenSwift/Strings/Stringium/Stringium.swift @@ -53,17 +53,6 @@ struct Stringium: ParsableCommand { tags: options.tags, outputPath: options.stringsFileOutputPath, inputFilenameWithoutExt: options.inputFilenameWithoutExt) - - // Generate extension - StringsFileGenerator.writeExtensionFiles(sections: sections, - defaultLang: options.defaultLang, - tags: options.tags, - staticVar: options.staticMembers, - inputFilename: options.inputFilenameWithoutExt, - extensionName: options.extensionName, - extensionFilePath: options.extensionFilePath, - extensionSuffix: options.extensionSuffix) - } else { print("[\(Self.toolName)] Will generate xcStrings") StringsFileGenerator.writeXcStringsFiles(sections: sections, @@ -74,6 +63,16 @@ struct Stringium: ParsableCommand { inputFilenameWithoutExt: options.inputFilenameWithoutExt) } + // Generate extension + StringsFileGenerator.writeExtensionFiles(sections: sections, + defaultLang: options.defaultLang, + tags: options.tags, + staticVar: options.staticMembers, + inputFilename: options.inputFilenameWithoutExt, + extensionName: options.extensionName, + extensionFilePath: options.extensionFilePath, + extensionSuffix: options.extensionSuffix) + print("[\(Self.toolName)] Strings generated") } 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/StringsFileGeneratorTests.swift b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift index 3520710..dec6627 100644 --- a/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift +++ b/Tests/ResgenSwiftTests/Strings/StringsFileGeneratorTests.swift @@ -213,7 +213,7 @@ final class StringsFileGeneratorTests: XCTestCase { // [s2_def_two] // fr = Section Deux - Definition deux // en = Section Two - Definition Two - // tags = ios,iosonly + // tags = notranslation // comments = @@ -359,7 +359,7 @@ final class StringsFileGeneratorTests: XCTestCase { content: XCStringLocalizationLangContent( stringUnit: DefaultStringUnit( state: "translated", - value: "Section Deux - Definition Deux" + value: "Section Two - Definition Two" ) ) ) @@ -372,82 +372,6 @@ final class StringsFileGeneratorTests: XCTestCase { 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) } @@ -472,8 +396,7 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section Two - Definition One"], tags: ["ios","iosonly"]), getDefinition(name: "s2_def_two", - translations: ["fr": "Section Deux - Definition Deux", - "en": "Section Two - Definition Two"], + translations: ["en": "Section Two - Definition Two"], tags: ["notranslation"]) ] @@ -504,9 +427,8 @@ final class StringsFileGeneratorTests: XCTestCase { // tags = ios,iosonly // comments = // [s2_def_two] - // fr = Section Deux - Definition deux // en = Section Two - Definition Two - // tags = ios,iosonly + // tags = notranslation // comments = // Expect @@ -592,7 +514,7 @@ final class StringsFileGeneratorTests: XCTestCase { content: XCStringLocalizationLangContent( stringUnit: DefaultStringUnit( state: "translated", - value: "Section Deux - Definition Deux" + value: "Section Two - Definition Two" ) ) ) @@ -740,7 +662,7 @@ final class StringsFileGeneratorTests: XCTestCase { // [s2_def_two] // fr = Section Deux - Definition deux // en = Section Two - Definition Two - // tags = ios,iosonly + // tags = notranslation // comments = @@ -765,15 +687,14 @@ final class StringsFileGeneratorTests: XCTestCase { "en": "Section Two - Definition One"], tags: ["ios","iosonly"]), getDefinition(name: "s2_def_two", - translations: ["fr": "Section Deux - Definition Deux", - "en": "Section Two - Definition Two"], + translations: ["fr": "Section Deux - Definition Deux"], tags: ["notranslation"]) ] // When let rootObject = StringsFileGenerator.generateRootObject( langs: ["fr", "en"], - defaultLang: "en", + defaultLang: "fr", tags: ["ios", "iosonly", "notranslation"], sections: [sectionOne, sectionTwo] ) @@ -781,7 +702,7 @@ final class StringsFileGeneratorTests: XCTestCase { // Expect let expect = Root( - sourceLanguage: "en", + sourceLanguage: "fr", strings: XCStringDefinitionContainer( strings: [ XCStringDefinition( @@ -881,7 +802,7 @@ final class StringsFileGeneratorTests: XCTestCase { content: XCStringLocalizationLangContent( stringUnit: DefaultStringUnit( state: "translated", - value: "Section Two - Definition Two" + value: "Section Deux - Definition Deux" ) ) ), -- 2.39.5