Skip to content

Commit

Permalink
Validate number of format placeholders as well
Browse files Browse the repository at this point in the history
  • Loading branch information
octylFractal committed Jul 12, 2020
1 parent 3a36862 commit 69b5cf5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
43 changes: 36 additions & 7 deletions buildSrc/src/main/kotlin/TranslationFileCheck.kt
Expand Up @@ -2,18 +2,27 @@ import groovy.json.JsonSlurper
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileType
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.work.ChangeType
import org.gradle.work.Incremental
import org.gradle.work.InputChanges
import java.io.File
import java.text.MessageFormat

@Suppress("UnstableApiUsage")
abstract class TranslationFileCheck : DefaultTask() {

@get: [
PathSensitive(PathSensitivity.NONE)
InputFile
]
abstract val sourceFile: RegularFileProperty

@get:[
Incremental
PathSensitive(PathSensitivity.NONE)
Expand All @@ -23,21 +32,41 @@ abstract class TranslationFileCheck : DefaultTask() {

@TaskAction
fun checkTranslationFiles(inputChanges: InputChanges) {
val sourceEntries = loadMessageFormats(sourceFile.asFile.get())

inputChanges.getFileChanges(translationFiles)
.asSequence()
.filter { it.fileType != FileType.DIRECTORY }
.filter { it.changeType != ChangeType.REMOVED }
.forEach { change ->
@Suppress("UNCHECKED_CAST")
val entries = JsonSlurper().parse(change.file) as Map<String, String>
for ((key, value) in entries) {
try {
MessageFormat(value)
} catch (e: IllegalArgumentException) {
error("Entry '$key' in ${change.file} is an invalid translation file: ${e.message}")
val compareEntries = loadMessageFormats(change.file)
for ((key, format) in compareEntries) {
val sourceFormat = sourceEntries[key]
?: error("Entry '$key' in ${change.file} has no matching format in the source")
val expectedFormatsSize = sourceFormat.formats.size
val actualFormatsSize = format.formats.size
check(expectedFormatsSize == actualFormatsSize) {
"Entry '$key' in ${change.file} has $actualFormatsSize formats instead of $expectedFormatsSize\n" +
"Literal expected: ${sourceFormat.toPattern()}\n" +
"Literal actual: ${format.toPattern()}"
}
}
}
}

private fun loadMessageFormats(file: File): Map<String, MessageFormat> =
entries(file)
.filterValues { it.isNotEmpty() }
.mapValues { (_, value) -> value.replace("'", "''") }
.mapValues { (key, value) ->
try {
MessageFormat(value)
} catch (e: IllegalArgumentException) {
error("Entry '$key' in $file is an invalid translation file: ${e.message}")
}
}

@Suppress("UNCHECKED_CAST")
private fun entries(file: File) = JsonSlurper().parse(file) as Map<String, String>

}
1 change: 1 addition & 0 deletions worldedit-core/build.gradle.kts
Expand Up @@ -130,6 +130,7 @@ if (project.hasProperty(crowdinApiKey) && !gradle.startParameter.isOffline) {
// allow checking of the source file even without the API key
val checkTranslationFiles by tasks.registering(TranslationFileCheck::class) {
dependsOn(processResources)
sourceFile.set(i18nSource)
translationFiles.from(fileTree(processResources.map { it.destinationDir }) {
include("**/lang/**/*.json")
})
Expand Down

0 comments on commit 69b5cf5

Please sign in to comment.