Как завершить сборку, если в строках есть неэкранированные апострофы. xml? - PullRequest
0 голосов
/ 08 февраля 2020

У меня есть приложение Android, и для этого приложения я автоматически загружаю переводы с crowdin.com - это хорошо работает.

Некоторые языки используют апострофы, и известно, что если в ваших строках есть апострофы. xml, тогда вы должны избегать их .

Что я хочу сделать, так это провалить сборку, если в моих различных строках есть неэкранированные апострофы. xml.

В частности, я хочу найти все строки . xml в src/main/res/, и если какие-либо файлы содержат ', которому не предшествует \, выдается ошибка. Это было бы идеально для меня, поскольку я могу об этом знать, и исправить переводы у источника с переводчиками.

В качестве альтернативы я ищу замену не спасавшимся апострофам, но в автоматическом режиме как часть самой сборки.

1 Ответ

1 голос
/ 08 февраля 2020

Вот простой пример задачи gradle, выполняемой перед preBuild, которая проверяет все строки. xml находит строковые значения с неэкранированными апострофами. Если обнаружены ошибки, не удается построить. Измените зависимость, как необходимо для задачи загрузки.

(обратите внимание, что сценарий завершается неудачно при первой обнаруженной ошибке - поэтому, если в версии en и в версии es есть ошибка, то только один файл сообщается как ошибка.)

(Примечание 2, поскольку используется синтаксический анализатор XML, он обрабатывает только значения, помеченные строками, и, следовательно, также игнорирует любые нарушения в комментариях xml - это очевидно в первом тестовом примере без ошибок.)

(в модуле: app (build.gradle))

task checkUnescapedApostrophes {
    doFirst {

        println("checkUnescapedApostrophes")

        fileTree("src").matching {
            include "**/strings.xml"
        }.each {
            def stringsFile = it
            def parser = (new XmlParser()).parse(stringsFile)
            println("Processing file: "+stringsFile)
            parser.'string'.each { m ->
                def s = m.text()
                def ss = "[^\\\\]\'"
                println "[" + m.@name + "]: " + s
                if (s =~ ss) {
                    throw new GradleException(
                        "Found a string value in " + stringsFile + 
                        " have unescaped apostrophe: "+s)
                }
            }
        }
        println("strings.xml OK")
    }
}

preBuild.dependsOn(checkUnescapedApostrophes)

В случае ошибок без строк. xml (языковой стандарт по умолчанию + es):

<resources>
<!--    <string name="test">some value with '</string> -->
    <string name="test2">some with escaped \'</string>
</resources>

<resources>
    <!--    <string name="test">algún valor con apóstrofe sin escape '</string> -->
    <string name="test2">algún valor con el apóstrofe escapado \'</string>
</resources>

Построить вывод:

> Configure project :app
checkUnescapedApostrophes
Processing file: ...\app\src\main\res\values\strings.xml
[test2]: some with escaped \'
Processing file: ....\app\src\main\res\values-es\strings.xml
[test2]: algún error con el apóstrofe escapado \'    
strings.xml OK

> Task :app:checkUnescapedApostrophes UP-TO-DATE
> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:compileDebugAidl NO-SOURCE
> Task :app:compileDebugRenderscript NO-SOURCE
> Task :app:checkDebugManifest UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:prepareLintJar UP-TO-DATE
> Task :app:prepareLintJarForPublish UP-TO-DATE
> Task :app:generateDebugSources UP-TO-DATE

BUILD SUCCESSFUL in 1s
4 actionable tasks: 4 up-to-date

И в случае ошибки строк. xml (по умолчанию локальный и es)

<resources>
    <string name="test">some value with '</string>
    <string name="test2">some with escaped \'</string>
</resources>

<resources>
    <string name="test">algún valor con apóstrofe sin escape '</string>
    <string name="test2">algún valor con el apóstrofe escapado \'</string>
</resources>

(Обратите внимание, что в вышеупомянутых случаях неоткрытый apostraphe помечается в студии красным цветом с ошибкой - как и ожидалось.)

Вывод сборки:

> Configure project :app
checkUnescapedApostrophes
Processing file: ...\app\src\main\res\values\strings.xml
[test]: some value with '

FAILURE: Build failed with an exception.

* Where:
Build file '...\app\build.gradle' line: 43

* What went wrong:
A problem occurred evaluating project ':app'.
> Found a string value in ...\app\src\main\res\values\strings.xml have unescaped apostrophe: some value with '

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s

Общее примечание к gradle: при тестировании для себя и изменении build.gradle - обязательно «Перестройте проект», а не просто «Создайте проект», как любой чан Похоже, что ges не обнаруживаются в случае, если сборка ранее не удалась.


Также в качестве альтернативы, о которой вы упомянули, эта задача будет избегать не спасавшихся апострофов путем замены во всех строках. xml найдено , Это обновление на месте - здесь есть более надежный подход: { ссылка }.

task replaceUnescapedApostrophes {
    doFirst {
        ant.replaceregexp(match: "([^\\\\])'", replace: "\\1\\\\\\\\'",  byline: "true") {
            fileset(dir: 'src/', excludes: '*', includes: '**/*strings.xml')
        }
    }
}

//preBuild.dependsOn(checkUnescapedApostrophes)
preBuild.dependsOn(replaceUnescapedApostrophes)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...