chore(purity): Translations

This commit is contained in:
yairm210 2025-08-11 22:42:47 +03:00
parent 6a984fe1ad
commit 8e02069121
4 changed files with 21 additions and 9 deletions

View File

@ -52,6 +52,7 @@ allprojects {
"java.util.regex.Pattern.matcher", "java.util.regex.Pattern.matcher",
"java.util.regex.Matcher.find", "java.util.regex.Matcher.find",
"java.util.regex.Matcher.replaceAll", "java.util.regex.Matcher.replaceAll",
"kotlin.collections.linkedMapOf",
) )
wellKnownReadonlyFunctions = setOf( wellKnownReadonlyFunctions = setOf(
"com.badlogic.gdx.math.Vector2.len", "com.badlogic.gdx.math.Vector2.len",

View File

@ -180,7 +180,7 @@ class City : IsPartOfGameInfoSerialization, INamed {
@Readonly fun getWorkRange(): Int = civ.gameInfo.ruleset.modOptions.constants.cityWorkRange @Readonly fun getWorkRange(): Int = civ.gameInfo.ruleset.modOptions.constants.cityWorkRange
@Readonly fun getExpandRange(): Int = civ.gameInfo.ruleset.modOptions.constants.cityExpandRange @Readonly fun getExpandRange(): Int = civ.gameInfo.ruleset.modOptions.constants.cityExpandRange
@Readonly @Suppress("purity") // the readonly connection type not respected for some reason for default value @Readonly
fun isConnectedToCapital(@Readonly connectionTypePredicate: (Set<String>) -> Boolean = { true }): Boolean { fun isConnectedToCapital(@Readonly connectionTypePredicate: (Set<String>) -> Boolean = { true }): Boolean {
val mediumTypes = civ.cache.citiesConnectedToCapitalToMediums[this] ?: return false val mediumTypes = civ.cache.citiesConnectedToCapitalToMediums[this] ?: return false
return connectionTypePredicate(mediumTypes) return connectionTypePredicate(mediumTypes)

View File

@ -1,9 +1,7 @@
package com.unciv.models.stats package com.unciv.models.stats
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import yairm210.purity.annotations.InternalState import yairm210.purity.annotations.*
import yairm210.purity.annotations.Pure
import yairm210.purity.annotations.Readonly
/** /**
* A container for the seven basic ["currencies"][Stat] in Unciv, * A container for the seven basic ["currencies"][Stat] in Unciv,
@ -170,6 +168,7 @@ open class Stats(
* *
* Example output: `+1 Production, -1 Food`. * Example output: `+1 Production, -1 Food`.
*/ */
@Readonly
override fun toString(): String { override fun toString(): String {
return this.joinToString { return this.joinToString {
(if (it.value > 0) "+" else "") + it.value.toInt().tr() + " " + it.key.toString().tr() (if (it.value > 0) "+" else "") + it.value.toInt().tr() + " " + it.key.toString().tr()
@ -265,13 +264,15 @@ open class Stats(
* - Order is not important. * - Order is not important.
* @see [isStats] * @see [isStats]
*/ */
@Pure
fun parse(string: String): Stats { fun parse(string: String): Stats {
val toReturn = Stats() val toReturn = Stats()
val statsWithBonuses = string.split(", ") val statsWithBonuses = string.split(", ")
for(statWithBonuses in statsWithBonuses) { statsWithBonuses.forEach { statWithBonuses ->
val match = statRegex.matchEntire(statWithBonuses)!! val match = statRegex.matchEntire(statWithBonuses)!!
val statName = match.groupValues[3] @Immutable val groupValues = match.groupValues
val statAmount = match.groupValues[2].toFloat() * (if (match.groupValues[1] == "-") -1 else 1) val statName = groupValues[3]
val statAmount = groupValues[2].toFloat() * (if (groupValues[1] == "-") -1 else 1)
toReturn.add(Stat.valueOf(statName), statAmount) toReturn.add(Stat.valueOf(statName), statAmount)
} }
return toReturn return toReturn

View File

@ -58,6 +58,7 @@ class Translations : LinkedHashMap<String, TranslationEntry>() {
* *
* @return the translation entry or null when not available * @return the translation entry or null when not available
*/ */
@Readonly
fun get(text: String, language: String, activeMods: HashSet<String>? = null): TranslationEntry? { fun get(text: String, language: String, activeMods: HashSet<String>? = null): TranslationEntry? {
if (activeMods != null) if (activeMods != null)
for (activeMod in activeMods) { for (activeMod in activeMods) {
@ -73,6 +74,7 @@ class Translations : LinkedHashMap<String, TranslationEntry>() {
/** /**
* @see get * @see get
*/ */
@Readonly
fun getText(text: String, language: String, activeMods: HashSet<String>? = null): String { fun getText(text: String, language: String, activeMods: HashSet<String>? = null): String {
return get(text, language, activeMods)?.get(language) ?: text return get(text, language, activeMods)?.get(language) ?: text
} }
@ -207,26 +209,30 @@ class Translations : LinkedHashMap<String, TranslationEntry>() {
debug("Loading percent complete of languages - %sms", System.currentTimeMillis() - startTime) debug("Loading percent complete of languages - %sms", System.currentTimeMillis() - startTime)
} }
@Readonly
fun getConditionalOrder(language: String): String { fun getConditionalOrder(language: String): String {
return getText(englishConditionalOrderingString, language, null) return getText(englishConditionalOrderingString, language, null)
} }
@Readonly
fun placeConditionalsAfterUnique(language: String) = fun placeConditionalsAfterUnique(language: String) =
get(conditionalUniqueOrderString, language, null)?.get(language) != "before" get(conditionalUniqueOrderString, language, null)?.get(language) != "before"
/** Returns the equivalent of a space in the given language /** Returns the equivalent of a space in the given language
* Defaults to a space if no translation is provided * Defaults to a space if no translation is provided
*/ */
@Readonly
fun getSpaceEquivalent(language: String): String { fun getSpaceEquivalent(language: String): String {
val translation = getText("\" \"", language, null) val translation = getText("\" \"", language, null)
return translation.substring(1, translation.length-1) return translation.substring(1, translation.length-1)
} }
@Readonly
fun shouldCapitalize(language: String): Boolean { fun shouldCapitalize(language: String): Boolean {
return get(shouldCapitalizeString, language, null)?.get(language)?.toBoolean() ?: true return get(shouldCapitalizeString, language, null)?.get(language)?.toBoolean() ?: true
} }
@Readonly
fun triggerNotificationEffectBeforeCause(language: String): Boolean{ fun triggerNotificationEffectBeforeCause(language: String): Boolean{
return get(effectBeforeCause, language, null)?.get(language)?.toBoolean() ?: true return get(effectBeforeCause, language, null)?.get(language)?.toBoolean() ?: true
} }
@ -318,7 +324,7 @@ object TranslationActiveModsCache {
* defaults to the input string if no translation is available, * defaults to the input string if no translation is available,
* but with placeholder or sentence brackets removed. * but with placeholder or sentence brackets removed.
*/ */
@Readonly @Suppress("purity") @Readonly
fun String.tr(hideIcons: Boolean = false, hideStats: Boolean = false): String { fun String.tr(hideIcons: Boolean = false, hideStats: Boolean = false): String {
val language: String = UncivGame.Current.settings.language val language: String = UncivGame.Current.settings.language
@ -345,6 +351,7 @@ fun String.tr(hideIcons: Boolean = false, hideStats: Boolean = false): String {
} }
@Readonly
private fun String.translateConditionals(hideIcons: Boolean, language: String): String { private fun String.translateConditionals(hideIcons: Boolean, language: String): String {
/** /**
* So conditionals can contain placeholders, such as <vs [unitFilter] units>, which themselves * So conditionals can contain placeholders, such as <vs [unitFilter] units>, which themselves
@ -404,6 +411,7 @@ private fun String.translateConditionals(hideIcons: Boolean, language: String):
return fullyTranslatedString return fullyTranslatedString
} }
@Readonly
private fun String.translatePlaceholders(language: String, hideIcons: Boolean): String { private fun String.translatePlaceholders(language: String, hideIcons: Boolean): String {
/** /**
* I'm SURE there's an easier way to do this but I can't think of it =\ * I'm SURE there's an easier way to do this but I can't think of it =\
@ -453,6 +461,7 @@ private fun String.translatePlaceholders(language: String, hideIcons: Boolean):
/** No brackets of any kind, just a single word */ /** No brackets of any kind, just a single word */
@Readonly
private fun String.translateIndividualWord(language: String, hideIcons: Boolean, hideStats: Boolean): String { private fun String.translateIndividualWord(language: String, hideIcons: Boolean, hideStats: Boolean): String {
if (Stats.isStats(this)) return Stats.parse(this).toString() if (Stats.isStats(this)) return Stats.parse(this).toString()
@ -577,6 +586,7 @@ fun Number.tr(): String {
* *
* @return locale-dependent String representation of receiver, may contain formatting like thousands separators * @return locale-dependent String representation of receiver, may contain formatting like thousands separators
*/ */
@Readonly
fun Number.tr(language: String): String { fun Number.tr(language: String): String {
return LocaleCode.getNumberFormatFromLanguage(language).format(this) return LocaleCode.getNumberFormatFromLanguage(language).format(this)
} }