Skip to content

Commit

Permalink
feat: optional url and key transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
Apehum committed Sep 23, 2024
1 parent 79c4794 commit 0938add
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 28 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Version
group=su.plo.crowdin
version=1.0.2-SNAPSHOT
version=1.1.0-SNAPSHOT

# Gradle args
org.gradle.jvmargs=-Xmx2048M
Expand Down
24 changes: 22 additions & 2 deletions plugin/src/main/kotlin/su/plo/crowdin/CrowdinDownloadTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package su.plo.crowdin
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.io.File
import java.net.URI

open class CrowdinDownloadTask : DefaultTask() {

Expand All @@ -16,7 +17,22 @@ open class CrowdinDownloadTask : DefaultTask() {
val languagesDir = File(project.buildDir, "generated/sources/crowdin/${params.resourceDir}")
languagesDir.mkdirs()

val translations = CrowdinLib.downloadRawTranslations(params.projectId, params.sourceFileName).get()
val url = when {
params.projectId != null -> URI.create("https://crowdin.com/backend/download/project/${params.projectId}.zip").toURL()
params.url != null -> params.url!!
else -> throw IllegalStateException("projectId and url can't be null")
}

val translations = CrowdinLib.downloadRawTranslations(
url,
params.sourceFileName,
params.keyTransformer ?: if (params.url != null) {
Crowdin.GITHUB_LOCALE_KEY_TRANSFORMER
} else {
Crowdin.DEFAULT_KEY_TRANSFORMER
}
).get()

if (translations.isEmpty()) {
if (params.createList) {
File(languagesDir, "list").writeText(params.sourceLanguage)
Expand All @@ -26,7 +42,11 @@ open class CrowdinDownloadTask : DefaultTask() {
}
if (params.createList) {
File(languagesDir, "list")
.writeText("${params.sourceLanguage}\n${translations.keys.filter { it != params.sourceLanguage }.joinToString("\n")}")
.writeText(
"${params.sourceLanguage}\n${
translations.keys.filter { it != params.sourceLanguage }.joinToString("\n")
}"
)
}

translations.forEach { (languageName, languageBytes) ->
Expand Down
7 changes: 6 additions & 1 deletion plugin/src/main/kotlin/su/plo/crowdin/CrowdinParams.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package su.plo.crowdin

import java.net.URL

open class CrowdinParams {

lateinit var projectId: String
var projectId: String? = null
var url: URL? = null
var keyTransformer: Crowdin.KeyTransformer? = null

var resourceDir = "languages"
var sourceFileName: String? = null

Expand Down
27 changes: 20 additions & 7 deletions src/main/kotlin/su/plo/crowdin/Crowdin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ package su.plo.crowdin

import com.google.common.cache.Cache
import com.google.common.cache.CacheBuilder
import su.plo.crowdin.Crowdin.KeyTransformer
import java.io.IOException
import java.net.URL
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
import java.util.zip.ZipInputStream

internal class Crowdin(
private val projectId: String
class Crowdin(
private val url: URL,
private val keyTransformer: KeyTransformer = DEFAULT_KEY_TRANSFORMER,
) {

@Throws(IOException::class)
fun downloadRawTranslations(fileName: String? = null): Map<String, ByteArray> {
val url = URL("https://crowdin.com/backend/download/project/$projectId.zip")

return CACHE.get(url) {
val connection = url.openConnection()
connection.connectTimeout = 3_000
Expand All @@ -32,9 +32,13 @@ internal class Crowdin(
?.let { entry.key.endsWith(it) }
?: JSON_PATTERN.matcher(entry.key).matches()
}
.map { it.key.substringBefore("/") to it.value }
.filter { CROWDIN_CODE_TO_MC_CODE.containsKey(it.first) }
.associate { CROWDIN_CODE_TO_MC_CODE[it.first]!! to it.second }
.map { keyTransformer.transform(it.key) to it.value }
.filter { it.first != null }
.associate { it.first!! to it.second }
}

fun interface KeyTransformer {
fun transform(key: String): String?
}

companion object {
Expand All @@ -45,6 +49,7 @@ internal class Crowdin(
.build();

private val JSON_PATTERN = Pattern.compile("^([a-z]{2}(-[A-Z]{2})?)/(.+\\.json)$")

// https://github.com/gbl/CrowdinTranslate/blob/a9a8b6fcbffd60b511e6c7514630129cf3866db7/src/main/java/de/guntram/mcmod/crowdintranslate/CrowdinTranslate.java#L27
private val MC_CODE_TO_CROWDIN_CODE: Map<String, String> = HashMap<String, String>().also {
it["af_za"] = "af"
Expand Down Expand Up @@ -173,5 +178,13 @@ internal class Crowdin(
MC_CODE_TO_CROWDIN_CODE
.map { it.value to it.key }
.toMap()

val GITHUB_LOCALE_KEY_TRANSFORMER: KeyTransformer = KeyTransformer {
it.split("/").getOrNull(1)?.lowercase()
}

val DEFAULT_KEY_TRANSFORMER: KeyTransformer = KeyTransformer {
CROWDIN_CODE_TO_MC_CODE[it.substringBefore("/")]
}
}
}
26 changes: 24 additions & 2 deletions src/main/kotlin/su/plo/crowdin/CrowdinLib.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package su.plo.crowdin
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.future
import java.net.URL
import java.util.concurrent.CompletableFuture

object CrowdinLib {
Expand All @@ -20,9 +21,30 @@ object CrowdinLib {
*/
fun downloadRawTranslations(
crowdinProjectId: String,
fileName: String? = null
fileName: String? = null,
keyTransformer: Crowdin.KeyTransformer = Crowdin.DEFAULT_KEY_TRANSFORMER,
): CompletableFuture<Map<String, ByteArray>> =
CoroutineScope(Dispatchers.Default).future {
Crowdin(crowdinProjectId).downloadRawTranslations(fileName)
Crowdin(URL("https://crowdin.com/backend/download/project/$crowdinProjectId.zip"), keyTransformer).downloadRawTranslations(fileName)
}

/**
* Downloads and returns map of raw files.
*
* Map contains [String] as a key and [ByteArray] as value.
*
* Map [String] key is a [minecraft language code](https://minecraft.fandom.com/wiki/Language).
*
* @param url The url to archive with translations.
* @param fileName The crowdin filename. Use this if you want to use specific translation.
* By default, **FIRST** json from the file list will be used.
*/
fun downloadRawTranslations(
url: URL,
fileName: String? = null,
keyTransformer: Crowdin.KeyTransformer = Crowdin.GITHUB_LOCALE_KEY_TRANSFORMER,
): CompletableFuture<Map<String, ByteArray>> =
CoroutineScope(Dispatchers.Default).future {
Crowdin(url, keyTransformer).downloadRawTranslations(fileName)
}
}
20 changes: 5 additions & 15 deletions src/test/kotlin/LibTest.kt
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.assertDoesNotThrow
import su.plo.crowdin.CrowdinLib
import java.util.concurrent.ExecutionException
import java.net.URI
import kotlin.test.Test
import kotlin.test.assertEquals

internal class LibTest {

@Test
fun download() {
val toml = CrowdinLib.downloadRawTranslations(
"pv-crowdin-test",
"test.toml"
).get()
assertEquals(toml.size, 1)
}

@Test
fun downloadInvalidProject() {
assertThrows<ExecutionException> {
assertDoesNotThrow {
CrowdinLib.downloadRawTranslations(
"pv-crowdin-test1",
"test.toml"
URI.create("https://github.com/plasmoapp/plasmo-voice-crowdin/archive/refs/heads/addons.zip").toURL(),
"server/discs.toml"
).get()
}
}
Expand Down

0 comments on commit 0938add

Please sign in to comment.