diff --git a/Sources/Code/StringsFileUpdater.swift b/Sources/Code/StringsFileUpdater.swift index 097c8e2..3d87226 100644 --- a/Sources/Code/StringsFileUpdater.swift +++ b/Sources/Code/StringsFileUpdater.swift @@ -274,7 +274,7 @@ public class StringsFileUpdater { translator.translate(sourceValue, callback: { translatedValue in if !translatedValue.isEmpty { - updatedTargetTranslations[updatedTargetTranslationIndex] = (key, translatedValue, comment) + updatedTargetTranslations[updatedTargetTranslationIndex] = (key, translatedValue.asStringLiteral, comment) translatedValuesCount += 1 } @@ -405,5 +405,20 @@ extension String { } return false } + + /// Unescapes any special characters to make String valid String Literal. + /// + /// Source: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html (to be cont.) + /// Continued: #//apple_ref/doc/uid/TP40014097-CH7-ID295 + var asStringLiteral: String { + let charactersToEscape = ["\\", "\""] // important: backslash must be first entry + var escapedString = self + + charactersToEscape.forEach { character in + escapedString = escapedString.stringByReplacingOccurrencesOfString(character, withString: "\\\(character)") + } + + return escapedString + } } \ No newline at end of file diff --git a/Tests/Assets/StringsFiles/de.lproj/Localizable.strings b/Tests/Assets/StringsFiles/de.lproj/Localizable.strings index 2d390b3..f2ab285 100644 --- a/Tests/Assets/StringsFiles/de.lproj/Localizable.strings +++ b/Tests/Assets/StringsFiles/de.lproj/Localizable.strings @@ -4,3 +4,5 @@ /* A string where value only available in English. */ "menu.cars" = ""; + +"TEST.KEY.UNESCAPED_DOUBLE_QUOTES" = ""; diff --git a/Tests/Assets/StringsFiles/en.lproj/Localizable.strings b/Tests/Assets/StringsFiles/en.lproj/Localizable.strings index 059b789..c344e36 100644 --- a/Tests/Assets/StringsFiles/en.lproj/Localizable.strings +++ b/Tests/Assets/StringsFiles/en.lproj/Localizable.strings @@ -6,4 +6,6 @@ "menu.cars" = "Cars"; /* A string where key only available in English. */ -"menu.bicycles" = "Bicycles"; \ No newline at end of file +"menu.bicycles" = "Bicycles"; + +"TEST.KEY.UNESCAPED_DOUBLE_QUOTES" = "She said: 'Stop!'"; \ No newline at end of file diff --git a/Tests/Assets/StringsFiles/ja.lproj/Localizable.strings b/Tests/Assets/StringsFiles/ja.lproj/Localizable.strings index adad354..a21a971 100644 --- a/Tests/Assets/StringsFiles/ja.lproj/Localizable.strings +++ b/Tests/Assets/StringsFiles/ja.lproj/Localizable.strings @@ -4,3 +4,5 @@ /* A string where value only available in English. */ "menu.cars" = ""; + +"TEST.KEY.UNESCAPED_DOUBLE_QUOTES" = ""; diff --git a/Tests/Assets/StringsFiles/zh-Hans.lproj/Localizable.strings b/Tests/Assets/StringsFiles/zh-Hans.lproj/Localizable.strings index 25ecf58..7b555f5 100644 --- a/Tests/Assets/StringsFiles/zh-Hans.lproj/Localizable.strings +++ b/Tests/Assets/StringsFiles/zh-Hans.lproj/Localizable.strings @@ -4,3 +4,5 @@ /* A string where value only available in English. */ "menu.cars" = ""; + +"TEST.KEY.UNESCAPED_DOUBLE_QUOTES" = ""; diff --git a/Tests/Code/StringsFileUpdaterTests.swift b/Tests/Code/StringsFileUpdaterTests.swift index 619881a..7e43ce1 100644 --- a/Tests/Code/StringsFileUpdaterTests.swift +++ b/Tests/Code/StringsFileUpdaterTests.swift @@ -272,14 +272,19 @@ class StringsFileUpdaterTests: XCTestCase { // test before state (update if failing) - XCTAssertEqual(translations.first!.key, "Test key") - XCTAssertEqual(translations.first!.value, "Test value (\(locale))") - XCTAssertEqual(translations.first!.comment, " A string already localized in all languages. ") + XCTAssertEqual(translations[0].key, "Test key") + XCTAssertEqual(translations[0].value, "Test value (\(locale))") + XCTAssertEqual(translations[0].comment, " A string already localized in all languages. ") - XCTAssertEqual(translations.last!.key, "menu.cars") - XCTAssertEqual(translations.last!.value.utf16.count, 0) - XCTAssertEqual(translations.last!.value, "") - XCTAssertEqual(translations.last!.comment, " A string where value only available in English. ") + XCTAssertEqual(translations[1].key, "menu.cars") + XCTAssertEqual(translations[1].value.utf16.count, 0) + XCTAssertEqual(translations[1].value, "") + XCTAssertEqual(translations[1].comment, " A string where value only available in English. ") + + XCTAssertEqual(translations[2].key, "TEST.KEY.UNESCAPED_DOUBLE_QUOTES") + XCTAssertEqual(translations[2].value.utf16.count, 0) + XCTAssertEqual(translations[2].value, "") + XCTAssertEqual(translations[2].comment, nil) // run tested method @@ -287,11 +292,11 @@ class StringsFileUpdaterTests: XCTestCase { translations = stringsFileUpdater.findTranslationsInLines(stringsFileUpdater.linesInFile) - XCTAssertEqual(changedValuesCount, 2) + XCTAssertEqual(changedValuesCount, 3) // test after state (update if failing) - XCTAssertEqual(translations.count, 3) + XCTAssertEqual(translations.count, 4) XCTAssertEqual(translations[0].key, "Test key") XCTAssertEqual(translations[0].value, "Test value (\(locale))") @@ -316,6 +321,12 @@ class StringsFileUpdaterTests: XCTestCase { "ja": "自転車", "zh-Hans": "自行车" ] + + let expectedTranslatedSheSaidStopValues: [String: String] = [ + "de": "Sie sagte: \\\"Stop!\\\"", // BartyCrouch is expected to escape double quotes + "ja": "彼女は言った: '停止'!", + "zh-Hans": "她说: '停止' !" + ] // test with create keys options for locale in ["de", "ja", "zh-Hans"] { @@ -339,7 +350,7 @@ class StringsFileUpdaterTests: XCTestCase { // test before state (update if failing) - XCTAssertEqual(translations.count, 2) + XCTAssertEqual(translations.count, 3) XCTAssertEqual(translations[0].key, "Test key") XCTAssertEqual(translations[0].value, "Test value (\(locale))") @@ -356,11 +367,11 @@ class StringsFileUpdaterTests: XCTestCase { translations = stringsFileUpdater.findTranslationsInLines(stringsFileUpdater.linesInFile) - XCTAssertEqual(changedValuesCount, 2) + XCTAssertEqual(changedValuesCount, 3) // test after state (update if failing) - XCTAssertEqual(translations.count, 3) + XCTAssertEqual(translations.count, 4) XCTAssertEqual(translations[0].key, "Test key") XCTAssertEqual(translations[0].value, "Test value (\(locale))") @@ -375,7 +386,12 @@ class StringsFileUpdaterTests: XCTestCase { XCTAssertGreaterThan(translations[2].value.utf16.count, 0) XCTAssertEqual(translations[2].value, expectedTranslatedBicyclesValues[locale]) XCTAssertEqual(translations[2].comment, " A string where key only available in English. ") - + + XCTAssertEqual(translations[3].key, "TEST.KEY.UNESCAPED_DOUBLE_QUOTES") + XCTAssertGreaterThan(translations[2].value.utf16.count, 0) + XCTAssertEqual(translations[3].value, expectedTranslatedSheSaidStopValues[locale]) + XCTAssertEqual(translations[3].comment, nil) + // cleanup temporary file after testing do {