Skip to content

Commit

Permalink
Add parametrized constructors to the tasks related to i18n
Browse files Browse the repository at this point in the history
This requires Gradle 4.8, where the parametrized constructors were introduced. (see https://docs.gradle.org/4.8/release-notes.html#create-tasks-with-constructor-arguments)
Also the main action of the tasks is not put in a `doFirst{}` or `doLast{}` block but into a method annotated with `@TaskAction`.
  • Loading branch information
floscher committed Jun 9, 2018
1 parent 9a0ebe5 commit ed8968a
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 132 deletions.
30 changes: 18 additions & 12 deletions src/main/kotlin/SourceSetSetup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,26 @@ fun SourceSet.setup(project: Project, sdsf: SourceDirectorySetFactory) {
project.tasks.create(
if (name=="main") "shortenPoFiles" else "shorten${name.capitalize()}PoFiles",
ShortenPoFiles::class.java,
{ it.sourceSet = i18nSourceSet }
i18nSourceSet
)

val poCompileTask = project.tasks.create(getCompileTaskName("po"), PoCompile::class.java, {
it.sourceSet = i18nSourceSet
})
val moCompileTask = project.tasks.create(getCompileTaskName("mo"), MoCompile::class.java, {
it.sourceSet = i18nSourceSet
it.poCompile = poCompileTask
})
val langCompileTask = project.tasks.create(getCompileTaskName("lang"), LangCompile::class.java, {
it.sourceSet = i18nSourceSet
it.moCompile = moCompileTask
})
val poCompileTask = project.tasks.create(
getCompileTaskName("po"),
PoCompile::class.java,
i18nSourceSet
)
val moCompileTask = project.tasks.create(
getCompileTaskName("mo"),
MoCompile::class.java,
poCompileTask,
i18nSourceSet
)
val langCompileTask = project.tasks.create(
getCompileTaskName("lang"),
LangCompile::class.java,
moCompileTask,
i18nSourceSet
)
if ("main" == name) {
project.extensions.josm.manifest.langCompileTask = langCompileTask
}
Expand Down
45 changes: 22 additions & 23 deletions src/main/kotlin/task/LangCompile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,25 @@ import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Sync
import org.gradle.api.tasks.TaskAction
import org.openstreetmap.josm.gradle.plugin.i18n.I18nSourceSet
import java.io.File
import javax.inject.Inject

/**
* This is not really a compilation task, it's only named like that analogous to [MoCompile] and [PoCompile].
*
* It copies (more precisely it [Sync]s) the *.lang files to `$buildDir/i18n/lang/$sourceSetName/data`
*/
open class LangCompile : Sync() {

open class LangCompile
/**
* @property sourceSet
* The source set from which all *.lang files are synced to the destination
*/
@Internal
lateinit var sourceSet: I18nSourceSet

/**
* @property moCompile
* The task for compiling *.mo files to *.lang files. These outputs are then used as inputs for this task.
*/
@Internal
lateinit var moCompile: MoCompile
@Inject
constructor(@Internal val moCompile: MoCompile, @Internal val sourceSet: I18nSourceSet): Sync() {

@Input
val subdirectory = "data"
Expand All @@ -44,21 +42,22 @@ open class LangCompile : Sync() {
project.afterEvaluate {
from(moCompile)
from(sourceSet.lang)
}
}

doFirst {
logger.lifecycle("Copy *.lang files to ${destinationDir.absolutePath}/$subdirectory")
val langs = HashSet<String>()
source.files.forEach {
logger.lifecycle(
" ${it.path}" +
if (langs.add(it.nameWithoutExtension)) {
""
} else {
" (will overwrite existing file!)"
}
)
}
}
@TaskAction
fun action() {
logger.lifecycle("Copy *.lang files to ${destinationDir.absolutePath}/$subdirectory")
val langs = HashSet<String>()
source.files.forEach {
logger.lifecycle(
" ${it.path}" +
if (langs.add(it.nameWithoutExtension)) {
""
} else {
" (will overwrite existing file!)"
}
)
}
}
}
69 changes: 38 additions & 31 deletions src/main/kotlin/task/MoCompile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.openstreetmap.josm.gradle.plugin.task

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.openstreetmap.josm.gradle.plugin.config.I18nConfig
import org.openstreetmap.josm.gradle.plugin.i18n.I18nSourceSet
import org.openstreetmap.josm.gradle.plugin.i18n.io.LangWriter
Expand All @@ -10,58 +11,64 @@ import org.openstreetmap.josm.gradle.plugin.i18n.io.MsgId
import org.openstreetmap.josm.gradle.plugin.i18n.io.MsgStr
import org.openstreetmap.josm.gradle.plugin.josm
import java.io.File
import javax.inject.Inject

/**
* This task "compiles" several *.mo files to *.lang files.
* For the language specified in [I18nConfig.mainLanguage], only the "msgid" is used (the text which will be translated).
* For the other languages, the "msgstr" is used (the text which is already translated to this language).
*/
open class MoCompile : DefaultTask() {
open class MoCompile
/**
* The task for compiling *.po files to *.mo files. Its outputs are used as inputs for this task.
* @property poCompile
* The task for compiling *.po files to *.mo files. Its outputs are used as inputs for this task
* @property sourceSet
* The [I18nSourceSet] for which the *.mo files will be compiled
*/
@Internal
lateinit var poCompile: PoCompile
@Inject
constructor(
@Internal val poCompile: PoCompile,
@Internal val sourceSet: I18nSourceSet
): DefaultTask() {

/**
* The [I18nSourceSet] for which the *.mo files will be compiled.
*/
@Internal
lateinit var sourceSet: I18nSourceSet
lateinit var outDir: File

init {
project.afterEvaluate {
val outDir = File(project.buildDir, "i18n/mo/" + sourceSet.name)
outDir = File(project.buildDir, "i18n/mo/" + sourceSet.name)

inputs.files(poCompile)
inputs.files(sourceSet.mo.asFileTree.files)
inputs.files(sourceSet.mo)
outputs.dir(outDir)

description = "Compile the *.mo gettext files of source set `${sourceSet.name}` to the *.lang format used by JOSM"
}
}

doFirst {
outDir.mkdirs()
val inputFiles = inputs.files.asFileTree.files
@TaskAction
fun action() {
outDir.mkdirs()
val inputFiles = inputs.files.asFileTree.files

if (inputFiles.isEmpty()) {
this.logger.lifecycle("No *.mo files found for this source set '{}'.", sourceSet.name)
if (inputFiles.isEmpty()) {
this.logger.lifecycle("No *.mo files found for this source set '{}'.", sourceSet.name)
} else {
logger.lifecycle("Reading the *.mo files…")
project.fileTree(outDir)
.filter { it.isFile && it.name.endsWith(".lang") }
.forEach { it.delete() }
val langMap = mutableMapOf<String, Map<MsgId, MsgStr>>()
inputFiles.forEach {
logger.lifecycle(" ${it.absolutePath}" + if (langMap.containsKey(it.nameWithoutExtension)) {
" (will overwrite existing file!)"
} else {
logger.lifecycle("Reading the *.mo files…")
project.fileTree(outDir).filter { it.isFile && it.name.endsWith(".lang") }.forEach { it.delete() }
val langMap = mutableMapOf<String, Map<MsgId, MsgStr>>()
inputFiles.forEach {
logger.lifecycle(" ${it.absolutePath}" + if (langMap.containsKey(it.nameWithoutExtension)) {
" (will overwrite existing file!)"
} else {
""
})
langMap[it.nameWithoutExtension] = MoReader(it.toURI().toURL()).readFile()
}

logger.lifecycle("Writing the *.lang files into ${outDir.absolutePath}")
LangWriter().writeLangFile(outDir, langMap, project.extensions.josm.i18n.mainLanguage)
}
""
})
langMap[it.nameWithoutExtension] = MoReader(it.toURI().toURL()).readFile()
}

logger.lifecycle("Writing the *.lang files into ${outDir.absolutePath}")
LangWriter().writeLangFile(outDir, langMap, project.extensions.josm.i18n.mainLanguage)
}
}
}
75 changes: 43 additions & 32 deletions src/main/kotlin/task/PoCompile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,77 @@ package org.openstreetmap.josm.gradle.plugin.task

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.openstreetmap.josm.gradle.plugin.i18n.I18nSourceSet
import java.io.File
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.util.concurrent.TimeUnit
import javax.inject.Inject

/**
* Compile *.po files (textual gettext files) to *.mo files (binary gettext files).
*
* This task requires the command line tool `msgfmt` (part of GNU gettext) to work properly! If the tool is not
* installed, it will only issue a warning (not fail), but translations from *.po files won't be available.
*/
open class PoCompile: DefaultTask() {

open class PoCompile
/**
* @property sourceSet
* The source set, for which all *.po files will be compiled to *.mo files.
*/
@Internal
lateinit var sourceSet: I18nSourceSet
@Inject
constructor(@Internal val sourceSet: I18nSourceSet): DefaultTask() {

private lateinit var outDir: File

init {
project.afterEvaluate {
val outDir = File(project.buildDir, "i18n/po/" + sourceSet.name)
outDir = File(project.buildDir, "i18n/po/" + sourceSet.name)

inputs.files(sourceSet.po)
outputs.dir(outDir)

description = "Compile the *.po text files of source set `${sourceSet.name}` to the binary *.mo files"
}
}

doFirst {
outDir.mkdirs();
@TaskAction
fun action() {
outDir.mkdirs();

if (sourceSet.po.isEmpty) {
this.logger.lifecycle("No *.po files found for this source set '{}'.", sourceSet.name)
return@doFirst
}
project.fileTree(outDir).filter { it.isFile && it.name.endsWith(".mo") }.forEach { it.delete() }
sourceSet.po.asFileTree.forEach {
val commandLine = listOf(
"msgfmt",
"--output-file=" + File(outDir, it.nameWithoutExtension + ".mo").absolutePath,
"--statistics",
it.absolutePath
)
this.logger.lifecycle(commandLine.joinToString(" "))
try {
val process: Process = ProcessBuilder(commandLine).redirectErrorStream(true).start()
if (process.waitFor(2, TimeUnit.MINUTES)) {
this.logger.lifecycle(" > " + process.inputStream.bufferedReader(StandardCharsets.UTF_8).readText())
} else {
logger.warn("WARNING: msgfmt takes longer than 2 minutes to convert ${it.absolutePath} . Aborting now!")
}
} catch (e: IOException) {
logger.warn("Failed to convert *.po file to *.mo file. Probably xgettext is not installed on your machine!")
if (sourceSet.po.isEmpty) {
this.logger.lifecycle("No *.po files found for this source set '{}'.", sourceSet.name)
} else {
project.fileTree(outDir)
.filter { it.isFile && it.name.endsWith(".mo") }
.forEach { it.delete() }
sourceSet.po.asFileTree.forEach {
val commandLine = listOf(
"msgfmt",
"--output-file=" + File(outDir, it.nameWithoutExtension + ".mo").absolutePath,
"--statistics",
it.absolutePath
)
this.logger.lifecycle(commandLine.joinToString(" "))
try {
val process: Process = ProcessBuilder(commandLine).redirectErrorStream(true).start()
if (process.waitFor(2, TimeUnit.MINUTES)) {
this.logger.lifecycle(" > " + process.inputStream.bufferedReader(StandardCharsets.UTF_8).readText())
} else {
val sourceFilePath = it.absolutePath
logger.warn("WARNING: msgfmt takes longer than 2 minutes to convert $sourceFilePath . Aborting now!")
project.gradle.buildFinished {
project.logger.error(
"WARNING: Not all i18n files have been built! Some *.po files could not be converted to *.mo files!\nWARNING: Maybe the program xgettext is not installed on your machine! It is required for processing *.po files."
)
logger.warn("WARNING: Gradle wasn't able to convert $sourceFilePath to a *.mo file in less than two minutes! I18n is incomplete!")
}
}
} catch (e: IOException) {
logger.warn("Failed to convert *.po file to *.mo file. Probably xgettext is not installed on your machine!")
project.gradle.buildFinished {
project.logger.error(
"WARNING: Not all i18n files have been built! Some *.po files could not be converted to *.mo files!\nWARNING: Maybe the program xgettext is not installed on your machine! It is required for processing *.po files."
)
}
}
}
}
Expand Down
Loading

0 comments on commit ed8968a

Please sign in to comment.