Skip to content

Commit

Permalink
Move name & description to lang files
Browse files Browse the repository at this point in the history
Introduce `ModNameProcessor` & `ModDescriptionProcessor`, along with a new method `LangTask.getTranslation()` which can be used to get a specific translation after the task has finished running.

Make use of this in `:data` to get the name & description from the translations into the mod metadata file.

Fixes MinecraftFreecam#172
  • Loading branch information
MattSturgeon committed Feb 8, 2024
1 parent 4d2f91c commit 2713803
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 25 deletions.
36 changes: 34 additions & 2 deletions buildSrc/src/main/kotlin/LangTask.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import org.gradle.api.DefaultTask
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.provider.Property
Expand Down Expand Up @@ -29,8 +30,10 @@ abstract class LangTask : DefaultTask() {

private val gson = GsonBuilder().setPrettyPrinting().create()
private val localeRegex = "^[a-z]{2}-[A-Z]{2}$".toRegex()
private val processors = listOf<LangProcessor>(
VariantTooltipProcessor()
private val processors = listOf(
VariantTooltipProcessor(),
ModDescriptionProcessor(),
ModNameProcessor()
)

init {
Expand All @@ -52,6 +55,35 @@ abstract class LangTask : DefaultTask() {
processed.forEach { (lang, translations) -> writeJsonFile(fileFor(lang), translations.toSortedMap()) }
}

/**
* Get the given translation, for the given language.
*
* Will fall back to using the [source language][source] if the key isn't
* found in the specified language or if language isn't specified.
*
* Should only be used **after** this task has finished executing.
* I.e. **not** during Gradle's configuration step.
*
* @param key the translation key
* @param lang the locale, e.g. en-US, en_us, or zh-CN
* @return the translation, or null if not found
*/
@JvmOverloads
fun getTranslation(key: String, lang: String = source.get()): String? {
val type = object : TypeToken<Map<String, String>>() {}.type;

val file = fileFor(lang)
val json: Map<String, String> = gson.fromJson(file.reader(), type)
val value = json[key]

// Check "source" translation if key wasn't found
return if (value == null && file != fileFor(source.get())) {
getTranslation(key)
} else {
value
}
}

private fun fileFor(lang: String): File {
val name = lang.lowercase().replace('-', '_') + ".json"
return outputDirectory.get().asFile
Expand Down
23 changes: 23 additions & 0 deletions buildSrc/src/main/kotlin/ModDescriptionProcessor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class ModDescriptionProcessor : LangProcessor {
override fun process(
modID: String,
variant: String,
translations: Map<String, String>,
fallback: Map<String, String>?
): Map<String, String> {
val map = translations.toMutableMap()
val firstID = "${modID}.description"
val secondID = "${modID}.description.${variant}"

val first = translations[firstID] ?: fallback?.get(firstID)
val second = secondID.let { translations[it] ?: fallback?.get(it) }
val full = listOfNotNull(first, second).joinToString(" ")

map[firstID] = full
map["modmenu.descriptionTranslation.${modID}"] = full
first?.let { map["modmenu.summaryTranslation.${modID}"] = it }
map.remove(secondID)

return map
}
}
22 changes: 22 additions & 0 deletions buildSrc/src/main/kotlin/ModNameProcessor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class ModNameProcessor : LangProcessor {
override fun process(
modID: String,
variant: String,
translations: Map<String, String>,
fallback: Map<String, String>?
): Map<String, String> {
val map = translations.toMutableMap()
val firstID = "${modID}.name"
val secondID = "${modID}.name.${variant}"

val first = translations[firstID] ?: fallback?.get(firstID)
val second = secondID.let { translations[it] ?: fallback?.get(it) }
val full = listOfNotNull(first, second).joinToString(" ")

map[firstID] = full
map["modmenu.nameTranslation.${modID}"] = full
map.remove(secondID)

return map
}
}
48 changes: 28 additions & 20 deletions data/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ variants.each { variant ->
kebabName += "-$variant"
}

def metadataTask = tasks.register("${name}GenMetadata", Copy) {
def metadataTask = tasks.register("${name}GenMetadata") {
def modFile
switch (platform) {
case "fabric":
Expand All @@ -40,17 +40,12 @@ variants.each { variant ->
group = "metadata"
description = "Build ${modFile} file"

// Include files under `src/platform`
from layout.projectDirectory.dir("src").dir(platform)
into layout.buildDirectory.dir("metadata/${kebabName}")

// Depend on langTask and the following properties
dependsOn langTask
inputs.properties(
mod_id: rootProject.name,
modrinth_name: project.modrinth_name,
version: project.mod_version,
authors: project.authors,
description: project.description,
modrinth_description: project.modrinth_description,
licence: project.licence,
homepage_url: project.homepage_url,
source_code_url: project.source_code_url,
Expand All @@ -62,22 +57,35 @@ variants.each { variant ->
neoforge_req: project.neoforge_req,
)

def inputDir = layout.projectDirectory.dir("src").dir(platform)
def outputDir = layout.buildDirectory.dir("metadata/${kebabName}")

// Declare task outputs so they can be used by other tasks
outputs.dir outputDir

def overrides = new TreeMap()
overrides.mod_id = inputs.properties.mod_id.toLowerCase()
overrides.name = overrides.mod_id.capitalize()
overrides.json_authors = inputs.properties.authors.split(',').collect { "\"$it\"" }.join(", ")

if (variant == "modrinth") {
overrides.name += ' ' + inputs.properties.modrinth_name
overrides.description = inputs.properties.description + ' ' + inputs.properties.modrinth_description
}

filesMatching("fabric.mod.json") {
expand inputs.properties + overrides
}

filesMatching("META-INF/mods.toml") {
expand inputs.properties + overrides
// Need to do this at execution time;
// langTask won't have built anything at configuration time...
doLast {
overrides.name = langTask.get().getTranslation("freecam.name")
overrides.description = langTask.get().getTranslation("freecam.description")

copy {
// Include files under `src/platform`
from inputDir
into outputDir

filesMatching("fabric.mod.json") {
expand inputs.properties + overrides
}

filesMatching("META-INF/mods.toml") {
expand inputs.properties + overrides
}
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions data/src/lang/en-US/mod.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
freecam.name=Freecam
freecam.name.modrinth=(Modrinth Edition)
freecam.description=A highly customizable freecam mod.
freecam.description.modrinth=Some features have been restricted to comply with Modrinth's Content Rules.
3 changes: 0 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ org.gradle.jvmargs=-Xmx4G
mod_version=1.2.3
maven_group=net.xolt.freecam
authors=hashalite,Matt Sturgeon
description=A highly customizable freecam mod.
modrinth_name=(Modrinth Edition)
modrinth_description=Some features have been restricted to comply with Modrinth's Content Rules.
licence=MIT
homepage_url=https://www.curseforge.com/minecraft/mc-mods/free-cam
source_code_url=https://github.com/MinecraftFreecam/Freecam
Expand Down

0 comments on commit 2713803

Please sign in to comment.