diff --git a/gradle/moko.versions.toml b/gradle/moko.versions.toml index d83767d1..f4effae7 100644 --- a/gradle/moko.versions.toml +++ b/gradle/moko.versions.toml @@ -1,5 +1,5 @@ [versions] -resourcesVersion = "0.24.0-beta-5" +resourcesVersion = "0.24.0-beta-6" [libraries] resources = { module = "dev.icerock.moko:resources", version.ref = "resourcesVersion" } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/PluralResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/PluralResourceGenerator.kt index d25a58c8..b1c242c7 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/PluralResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/plural/PluralResourceGenerator.kt @@ -11,6 +11,7 @@ import dev.icerock.gradle.generator.generateKey import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.PluralMetadata import dev.icerock.gradle.utils.processXmlTextContent +import dev.icerock.gradle.utils.removeAndroidMirroringFormat import org.w3c.dom.Document import org.w3c.dom.Element import org.w3c.dom.Node @@ -79,7 +80,7 @@ internal class PluralResourceGenerator( val item: Node = itemNodes.item(j) val quantity: String = item.attributes.getNamedItem("quantity").textContent.trim() - val value: String = item.textContent + val value: String = item.textContent.removeAndroidMirroringFormat() pluralMap[quantity] = value.processXmlTextContent(strictLineBreaks) } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/StringResourceGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/StringResourceGenerator.kt index a79792c4..cf27c9df 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/StringResourceGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/resources/string/StringResourceGenerator.kt @@ -11,6 +11,7 @@ import dev.icerock.gradle.generator.generateKey import dev.icerock.gradle.generator.localization.LanguageType import dev.icerock.gradle.metadata.resource.StringMetadata import dev.icerock.gradle.utils.processXmlTextContent +import dev.icerock.gradle.utils.removeAndroidMirroringFormat import org.w3c.dom.Document import org.w3c.dom.Node import org.w3c.dom.NodeList @@ -29,7 +30,7 @@ internal class StringResourceGenerator( val language: LanguageType = LanguageType.fromFileName(file.parentFile.name) val strings: Map = loadLanguageStrings(file) strings.map { (key: KeyType, text: String) -> - key to (language to text) + key to (language to text.removeAndroidMirroringFormat()) } }.groupBy( keySelector = { it.first }, diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/StringExt.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/StringExt.kt index 803b37fa..89bc16fa 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/StringExt.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/StringExt.kt @@ -49,13 +49,26 @@ internal fun String.remove(char: String): String { internal val String.flatName: String get() = this.remove('.') +internal fun String.removeAndroidMirroringFormat(): String { + // Remove android format from string + return replace("""\'""", "'") + .replace("""\"""", "\"") +} + internal fun String.convertXmlStringToAndroidLocalization(): String { // Android resources should comply with requirements: - // https://developer.android.com/guide/topics/resources/string-resource + // https://developer.android.com/guide/topics/resources/string-resource#escaping_quotes return StringEscapeUtils .unescapeXml(this) .replace("\n", "\\n") .let { StringEscapeUtils.escapeXml11(it) } + .let { + if (it[0] == '@') { + replaceFirst("@", """\@""") + } else { + it + } + } .replace(""", "\\"") .replace("'", "\\'") } diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/pluralsGenerator/XmlPluralsToPlatformTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/pluralsGenerator/XmlPluralsToPlatformTest.kt index e0a348c7..0468e615 100644 --- a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/pluralsGenerator/XmlPluralsToPlatformTest.kt +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/pluralsGenerator/XmlPluralsToPlatformTest.kt @@ -23,7 +23,7 @@ class XmlPluralsToPlatformTest { fun simplePluralsAndroidTest(){ assertEquals( expected = """%d count of \"%s\"""", - actual ="%d count of \"%s\"".convertXmlStringToAndroidLocalization(), + actual ="""%d count of "%s"""".convertXmlStringToAndroidLocalization(), ) } diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsAndroidFormatTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsAndroidFormatTest.kt new file mode 100644 index 00000000..91289160 --- /dev/null +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsAndroidFormatTest.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2024 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.generator.stringsGenerator + +import dev.icerock.gradle.utils.convertXmlStringToAndroidLocalization +import dev.icerock.gradle.utils.removeAndroidMirroringFormat +import kotlin.test.Test +import kotlin.test.assertEquals + +class XmlStringsAndroidFormatTest { + @Test + fun quotesAndroidFormat() { + assertEquals( + expected = """Same text with symbol's @ ? somet'ing "word"""", + actual = TEXT_WITH_QUOTES.removeAndroidMirroringFormat() + ) + } + + @Test + fun quotesAndroidInOutFormat() { + assertEquals( + expected = """Same text with symbol\'s @ ? somet\'ing \"word\"""", + actual = TEXT_WITH_QUOTES + .removeAndroidMirroringFormat() + .convertXmlStringToAndroidLocalization() + ) + } + + private companion object { + private const val TEXT_WITH_QUOTES = """Same text with symbol's @ ? somet\'ing \"word"""" + + } +} diff --git a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsToPlatformTest.kt b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsToPlatformTest.kt index a60ae22a..df66f22e 100644 --- a/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsToPlatformTest.kt +++ b/resources-generator/src/test/kotlin/dev/icerock/gradle/generator/stringsGenerator/XmlStringsToPlatformTest.kt @@ -122,4 +122,12 @@ class XmlStringsToPlatformTest { actual = "\uD83D\uDE08".convertXmlStringToLocalization() ) } + + @Test + fun stringLikeAndroidLinkOnStringAndroidTest() { + assertEquals( + expected = """\@same text""", + actual = """@same text""".convertXmlStringToAndroidLocalization() + ) + } } diff --git a/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/base/strings.xml b/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/base/strings.xml index b7308d59..9fb36169 100644 --- a/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/base/strings.xml +++ b/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/base/strings.xml @@ -1,8 +1,8 @@ Hello moko-resources World - Text with + @Text with newline w/o new line - Text \n with " ' % @ * & {} "same" inch's + Text \n with " ' % @ * & {} "same\" inch\'s Text with <b>bold</b>, <i>italic</i>, <u>underline</u> diff --git a/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/ru/strings.xml b/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/ru/strings.xml index e331bdf2..24f0ad22 100644 --- a/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/ru/strings.xml +++ b/samples/compose-resources-gallery/shared/src/commonMain/moko-resources/ru/strings.xml @@ -1,6 +1,6 @@ Привет Мир moko-resources - Текст \n с " ' % @ * & {} "сколько-то" дюйм'ов + Текст \n с " ' % @ * & {} "сколько-то\" дюйм\'ов Текст с <b>жирный</b>, <i>курсив</i>, <u>подчеркивание</u>