Now load only necessary translations

Since loading all the translation files was taking around 2.5 seconds on my phone, and I assume much longer on older phones, we now only load the translations of the currently selected file, and if we need to find the translation percentage of all the files we deal with that separately. Down to around 200-300 ms on my phone =)
Also Translations is no longer part of the Ruleset, instead meing located in UncivGame
This commit is contained in:
Yair Morgenstern 2019-12-18 23:32:31 +02:00
parent 77d00f35bb
commit 3627d4e6e2
64 changed files with 347 additions and 325 deletions

View file

@ -14,6 +14,7 @@ import com.unciv.logic.map.MapParameters
import com.unciv.models.metadata.GameParameters
import com.unciv.models.metadata.GameSettings
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.translations.Translations
import com.unciv.ui.LanguagePickerScreen
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
@ -38,10 +39,13 @@ class UncivGame(val version: String) : Game() {
var music : Music? =null
val musicLocation = "music/thatched-villagers.mp3"
var isInitialized=false
var isInitialized = false
var rewriteTranslationFiles = false
lateinit var ruleset:Ruleset
val translations = Translations()
override fun create() {
Gdx.input.setCatchKey(Input.Keys.BACK, true)
if (Gdx.app.type != Application.ApplicationType.Desktop)
@ -58,6 +62,14 @@ class UncivGame(val version: String) : Game() {
thread {
ruleset = Ruleset(true)
if(rewriteTranslationFiles) { // Yes, also when running from the Jar. Sue me.
translations.readAllLanguagesTranslation()
translations.writeNewTranslationFiles()
}
else{
translations.tryReadTranslationForCurrentLanguage()
}
if (settings.userId == "") { // assign permanent user id
settings.userId = UUID.randomUUID().toString()
settings.save()

View file

@ -12,7 +12,7 @@ import com.unciv.logic.map.MapUnit
import com.unciv.logic.trade.*
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import kotlin.math.min
class NextTurnAutomation{

View file

@ -6,7 +6,7 @@ import com.unciv.logic.automation.ConstructionAutomation
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.PopupAlert
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.withItem
import com.unciv.ui.utils.withoutItem

View file

@ -19,6 +19,7 @@ import com.unciv.models.ruleset.tech.TechEra
import com.unciv.models.ruleset.tile.ResourceSupplyList
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

View file

@ -7,7 +7,7 @@ import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tile.*
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stats
import kotlin.math.abs

View file

@ -4,7 +4,7 @@ import com.unciv.Constants
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
class TradeLogic(val ourCivilization:CivilizationInfo, val otherCivilization: CivilizationInfo){

View file

@ -1,6 +1,6 @@
package com.unciv.logic.trade
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
data class TradeOffer(var name:String, var type: TradeType,
/** 0 for offers that are immediate (e.g. gold transfer) */ var duration:Int, var amount:Int=1) {

View file

@ -7,6 +7,7 @@ import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.stats.NamedStats
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.models.translations.tr
import kotlin.math.pow
class Building : NamedStats(), IConstruction{

View file

@ -1,6 +1,5 @@
package com.unciv.models.ruleset
import com.badlogic.gdx.Application
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.utils.Json
import com.unciv.models.ruleset.tech.TechColumn
@ -11,9 +10,6 @@ import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.models.ruleset.unit.Promotion
import com.unciv.models.stats.INamed
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap
import kotlin.collections.set
class Ruleset {
@ -27,7 +23,6 @@ class Ruleset {
val Nations = LinkedHashMap<String, Nation>()
val PolicyBranches = LinkedHashMap<String, PolicyBranch>()
val Difficulties = LinkedHashMap<String, Difficulty>()
val Translations = Translations()
fun <T> getFromJson(tClass: Class<T>, filePath:String): T {
val jsonText = Gdx.files.internal(filePath).readString(Charsets.UTF_8.name())
@ -52,7 +47,6 @@ class Ruleset {
newRuleset.Terrains.putAll(Terrains)
newRuleset.TileImprovements.putAll(TileImprovements)
newRuleset.TileResources.putAll(TileResources)
newRuleset.Translations.putAll(Translations)
newRuleset.UnitPromotions.putAll(UnitPromotions)
newRuleset.Units.putAll(Units)
return newRuleset
@ -107,79 +101,7 @@ class Ruleset {
val gameBasicsLoadTime = System.currentTimeMillis() - gameBasicsStartTime
println("Loading game basics - "+gameBasicsLoadTime+"ms")
// Apparently you can't iterate over the files in a directory when running out of a .jar...
// https://www.badlogicgames.com/forum/viewtopic.php?f=11&t=27250
// which means we need to list everything manually =/
val translationStart = System.currentTimeMillis()
readTranslationsFromProperties()
// readTranslationsFromJson()
if(Gdx.app.type==Application.ApplicationType.Desktop) // Yes, also when running from the Jar. Sue me.
writeNewTranslationFiles()
val translationFilesTime = System.currentTimeMillis() - translationStart
println("Loading translation files - "+translationFilesTime+"ms")
}
private fun writeNewTranslationFiles() {
for (language in Translations.getLanguages()) {
val languageHashmap = HashMap<String, String>()
for (translation in Translations.values) {
if (translation.containsKey(language))
languageHashmap[translation.entry] = translation[language]!!
}
TranslationFileReader().writeByTemplate(language, languageHashmap)
}
}
private fun readTranslationsFromProperties() {
val languages = ArrayList<String>()
// So apparently the Locales don't work for everyone, which is horrendous
// So for those players, which seem to be Android-y, we try to see what files exist directly...yeah =/
try{
for(file in Gdx.files.internal("jsons/translationsByLanguage").list())
languages.add(file.nameWithoutExtension())
}
catch (ex:Exception){} // Iterating on internal files will not work when running from a .jar
languages.addAll(Locale.getAvailableLocales() // And this should work for Desktop, meaning from a .jar
.map { it.getDisplayName(Locale.ENGLISH) }) // Maybe THIS is the problem, that the DISPLAY locale wasn't english
// and then languages were displayed according to the player's locale... *sweatdrop*
// These should probably ve renamed
languages.add("Simplified_Chinese")
languages.add("Traditional_Chinese")
for (language in languages.distinct()) {
val translationFileName = "jsons/translationsByLanguage/$language.properties"
if (!Gdx.files.internal(translationFileName).exists()) continue
val languageTranslations = TranslationFileReader().read(translationFileName,Translations.keys)
for (translation in languageTranslations) {
if (!Translations.containsKey(translation.key))
Translations[translation.key] = TranslationEntry(translation.key)
Translations[translation.key]!![language] = translation.value
}
}
}
private fun readTranslationsFromJson() {
val translationFileNames = listOf("Buildings","Diplomacy,Trade,Nations",
"NewGame,SaveGame,LoadGame,Options", "Notifications","Other","Policies","Techs",
"Terrains,Resources,Improvements","Units,Promotions")
for (fileName in translationFileNames) {
val file = Gdx.files.internal("jsons/Translations/$fileName.json")
if (file.exists()) {
Translations.add(file.readString(Charsets.UTF_8.name()))
}
}
}
}

View file

@ -1,164 +0,0 @@
package com.unciv.models.ruleset
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.utils.JsonReader
import com.unciv.UncivGame
class TranslationEntry(val entry: String) : HashMap<String, String>() {
/** For memory performance on .tr(), which was atrociously memory-expensive */
var entryWithShortenedSquareBrackets =""
init {
if(entry.contains('['))
entryWithShortenedSquareBrackets=entry.replace(squareBraceRegex,"[]")
}
}
class Translations : LinkedHashMap<String, TranslationEntry>(){
fun add(json:String){
val jsonValue = JsonReader().parse(json)!!
var currentEntry = jsonValue.child
while(currentEntry!=null){
val currentEntryName = currentEntry.name!!
val translationEntry = TranslationEntry(currentEntryName)
this[currentEntryName]=translationEntry
var currentLanguage = currentEntry.child
while(currentLanguage!=null){
translationEntry[currentLanguage.name!!]=currentLanguage.asString()
currentLanguage = currentLanguage.next
}
currentEntry = currentEntry.next
}
}
fun get(text:String,language:String): String {
if(!hasTranslation(text,language)) return text
return get(text)!![language]!!
}
fun hasTranslation(text:String,language:String): Boolean {
return containsKey(text) && get(text)!!.containsKey(language)
}
fun getLanguages(): List<String> {
val toReturn = mutableListOf<String>()
for(entry in values)
for(languageName in entry.keys)
if(!toReturn.contains(languageName)) toReturn.add(languageName)
toReturn.remove("Japanese") // These were for tests but were never actually seriously translated
toReturn.remove("Thai")
return toReturn
}
companion object {
fun translateBonusOrPenalty(unique:String): String {
val regexResult = Regex("""(Bonus|Penalty) vs (.*) (\d*)%""").matchEntire(unique)
if(regexResult==null) return unique.tr()
else{
var separatorCharacter = " "
if (UncivGame.Current.settings.language=="Simplified_Chinese")separatorCharacter = ""
val start = regexResult.groups[1]!!.value+" vs ["+regexResult.groups[2]!!.value+"]"
val translatedUnique = start.tr() + separatorCharacter + regexResult.groups[3]!!.value+"%"
return translatedUnique
}
}
}
}
class TranslationFileReader(){
fun read(translationFile: String, possibleTranslationValues: MutableSet<String>): LinkedHashMap<String, String> {
val translations = LinkedHashMap<String,String>()
val text = Gdx.files.internal(translationFile)
text.reader(Charsets.UTF_8.toString()).forEachLine {
val line=it
if(!line.contains(" = ")) return@forEachLine
val splitLine = line.split(" = ")
if(splitLine[1]!="") { // the value is empty, this means this wasn't translated yet
val value = splitLine[1].replace("\\n","\n")
val key = splitLine[0].replace("\\n","\n")
translations[key] = value
}
}
return translations
}
fun writeByTemplate(language:String, translations: HashMap<String,String>){
val templateFile = Gdx.files.internal("jsons/translationsByLanguage/template.properties")
val stringBuilder = StringBuilder()
for(line in templateFile.reader().readLines()){
if(!line.contains(" = ")){ // copy as-is
stringBuilder.appendln(line)
continue
}
val translationKey = line.split(" = ")[0].replace("\\n","\n")
var translationValue = ""
if(translations.containsKey(translationKey)) translationValue = translations[translationKey]!!
else stringBuilder.appendln(" # Requires translation!")
val lineToWrite = translationKey.replace("\n","\\n") +
" = "+ translationValue.replace("\n","\\n")
stringBuilder.appendln(lineToWrite)
}
Gdx.files.local("jsons/translationsByLanguage/$language.properties")
.writeString(stringBuilder.toString(),false,Charsets.UTF_8.name())
}
}
val squareBraceRegex = Regex("\\[(.*?)\\]") // we don't need to allocate different memory for this every time we .tr()
val eitherSquareBraceRegex=Regex("\\[|\\]")
fun String.tr(): String {
// THIS IS INCREDIBLY INEFFICIENT and causes loads of memory problems!
if(contains("[")){ // Placeholders!
/**
* I'm SURE there's an easier way to do this but I can't think of it =\
* So what's all this then?
* Well, not all languages are like English. So say I want to say "work on Library has completed in Akkad",
* but in a completely different language like Japanese or German,
* It could come out "Akkad hast die worken onner Library gerfinishen" or whatever,
* basically, the order of the words in the sentence is not guaranteed.
* So to translate this, I give a sentence like "work on [building] has completed in [city]"
* and the german can put those placeholders where he wants, so "[city] hast die worken onner [building] gerfinishen"
* The string on which we call tr() will look like "work on [library] has completed in [Akkad]"
* We will find the german placeholder text, and replace the placeholders with what was filled in the text we got!
*/
val translationStringWithSquareBracketsOnly = replace(squareBraceRegex,"[]")
val translationEntry = UncivGame.Current.ruleset.Translations.values
.firstOrNull { translationStringWithSquareBracketsOnly == it.entryWithShortenedSquareBrackets }
if(translationEntry==null ||
!translationEntry.containsKey(UncivGame.Current.settings.language)){
// Translation placeholder doesn't exist for this language, default to English
return this.replace(eitherSquareBraceRegex,"")
}
val termsInMessage = squareBraceRegex.findAll(this).map { it.groups[1]!!.value }.toList()
val termsInTranslationPlaceholder = squareBraceRegex.findAll(translationEntry.entry).map { it.value }.toList()
if(termsInMessage.size!=termsInTranslationPlaceholder.size)
throw Exception("Message $this has a different number of terms than the placeholder $translationEntry!")
var languageSpecificPlaceholder = translationEntry[UncivGame.Current.settings.language]!!
for(i in termsInMessage.indices){
languageSpecificPlaceholder = languageSpecificPlaceholder.replace(termsInTranslationPlaceholder[i], termsInMessage[i].tr())
}
return languageSpecificPlaceholder.tr()
}
if(contains("{")){ // sentence
return Regex("\\{(.*?)\\}").replace(this) { it.groups[1]!!.value.tr() }
}
val translation = UncivGame.Current.ruleset.Translations.get(this, UncivGame.Current.settings.language) // single word
return translation
}

View file

@ -4,7 +4,7 @@ import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.BaseUnit
import java.util.*

View file

@ -2,7 +2,7 @@ package com.unciv.models.ruleset.tile
import com.badlogic.gdx.graphics.Color
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.NamedStats
import com.unciv.ui.utils.colorFromRGB

View file

@ -2,7 +2,7 @@ package com.unciv.models.ruleset.tile
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.NamedStats
import com.unciv.models.stats.Stats
import java.util.*

View file

@ -1,6 +1,6 @@
package com.unciv.models.ruleset.tile
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.NamedStats
import com.unciv.models.stats.Stats
import java.util.*

View file

@ -7,8 +7,8 @@ import com.unciv.logic.city.IConstruction
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Translations
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr
import com.unciv.models.stats.INamed
// This is BaseUnit because Unit is already a base Kotlin class and to avoid mixing the two up
@ -41,7 +41,7 @@ class BaseUnit : INamed, IConstruction {
fun getShortDescription(): String {
val infoList= mutableListOf<String>()
for(unique in uniques)
infoList+=Translations.translateBonusOrPenalty(unique)
infoList+= Translations.translateBonusOrPenalty(unique)
for(promotion in promotions)
infoList += promotion.tr()
if(strength!=0) infoList += "{Strength}: $strength".tr()

View file

@ -1,6 +1,6 @@
package com.unciv.models.stats
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
open class Stats() {

View file

@ -0,0 +1,14 @@
package com.unciv.models.translations
import java.util.HashMap
class TranslationEntry(val entry: String) : HashMap<String, String>() {
/** For memory performance on .tr(), which was atrociously memory-expensive */
var entryWithShortenedSquareBrackets =""
init {
if(entry.contains('['))
entryWithShortenedSquareBrackets=entry.replace(squareBraceRegex,"[]")
}
}

View file

@ -0,0 +1,44 @@
package com.unciv.models.translations
import com.badlogic.gdx.Gdx
import java.util.*
import kotlin.collections.LinkedHashMap
import kotlin.collections.set
class TranslationFileReader(){
fun read(translationFile: String): LinkedHashMap<String, String> {
val translations = LinkedHashMap<String, String>()
val text = Gdx.files.internal(translationFile)
text.reader(Charsets.UTF_8.toString()).forEachLine {
val line=it
if(!line.contains(" = ")) return@forEachLine
val splitLine = line.split(" = ")
if(splitLine[1]!="") { // the value is empty, this means this wasn't translated yet
val value = splitLine[1].replace("\\n","\n")
val key = splitLine[0].replace("\\n","\n")
translations[key] = value
}
}
return translations
}
fun writeByTemplate(language:String, translations: HashMap<String, String>){
val templateFile = Gdx.files.internal("jsons/translationsByLanguage/template.properties")
val stringBuilder = StringBuilder()
for(line in templateFile.reader().readLines()){
if(!line.contains(" = ")){ // copy as-is
stringBuilder.appendln(line)
continue
}
val translationKey = line.split(" = ")[0].replace("\\n","\n")
var translationValue = ""
if(translations.containsKey(translationKey)) translationValue = translations[translationKey]!!
else stringBuilder.appendln(" # Requires translation!")
val lineToWrite = translationKey.replace("\n","\\n") +
" = "+ translationValue.replace("\n","\\n")
stringBuilder.appendln(lineToWrite)
}
Gdx.files.local("jsons/translationsByLanguage/$language.properties")
.writeString(stringBuilder.toString(),false,Charsets.UTF_8.name())
}
}

View file

@ -0,0 +1,199 @@
package com.unciv.models.translations
import com.badlogic.gdx.Gdx
import com.unciv.UncivGame
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
class Translations : LinkedHashMap<String, TranslationEntry>(){
fun get(text:String,language:String): String {
if(!hasTranslation(text,language)) return text
return get(text)!![language]!!
}
fun hasTranslation(text:String,language:String): Boolean {
return containsKey(text) && get(text)!!.containsKey(language)
}
fun getLanguages(): List<String> {
val toReturn = mutableListOf<String>()
for(entry in values)
for(languageName in entry.keys)
if(!toReturn.contains(languageName)) toReturn.add(languageName)
toReturn.remove("Japanese") // These were for tests but were never actually seriously translated
toReturn.remove("Thai")
return toReturn
}
companion object {
fun translateBonusOrPenalty(unique:String): String {
val regexResult = Regex("""(Bonus|Penalty) vs (.*) (\d*)%""").matchEntire(unique)
if(regexResult==null) return unique.tr()
else{
var separatorCharacter = " "
if (UncivGame.Current.settings.language=="Simplified_Chinese") separatorCharacter = ""
val start = regexResult.groups[1]!!.value+" vs ["+regexResult.groups[2]!!.value+"]"
val translatedUnique = start.tr() + separatorCharacter + regexResult.groups[3]!!.value+"%"
return translatedUnique
}
}
}
fun tryReadTranslationForLanguage(language: String){
val translationStart = System.currentTimeMillis()
val translationFileName = "jsons/translationsByLanguage/$language.properties"
if (!Gdx.files.internal(translationFileName).exists()) return
val languageTranslations = TranslationFileReader()
.read(translationFileName)
for (translation in languageTranslations) {
if (!containsKey(translation.key))
this[translation.key] = TranslationEntry(translation.key)
this[translation.key]!![language] = translation.value
}
val translationFilesTime = System.currentTimeMillis() - translationStart
println("Loading translation file for $language - "+translationFilesTime+"ms")
}
fun tryReadTranslationForCurrentLanguage(){
tryReadTranslationForLanguage(UncivGame.Current.settings.language)
}
fun getLanguagesWithTranslationFile(): List<String> {
val languages = ArrayList<String>()
// So apparently the Locales don't work for everyone, which is horrendous
// So for those players, which seem to be Android-y, we try to see what files exist directly...yeah =/
try{
for(file in Gdx.files.internal("jsons/translationsByLanguage").list())
languages.add(file.nameWithoutExtension())
}
catch (ex:Exception){} // Iterating on internal files will not work when running from a .jar
languages.addAll(Locale.getAvailableLocales() // And this should work for Desktop, meaning from a .jar
.map { it.getDisplayName(Locale.ENGLISH) }) // Maybe THIS is the problem, that the DISPLAY locale wasn't english
// and then languages were displayed according to the player's locale... *sweatdrop*
// These should probably be renamed
languages.add("Simplified_Chinese")
languages.add("Traditional_Chinese")
languages.remove("template")
return languages.distinct()
.filter { Gdx.files.internal("jsons/translationsByLanguage/$it.properties").exists() }
}
fun readAllLanguagesTranslation() {
// Apparently you can't iterate over the files in a directory when running out of a .jar...
// https://www.badlogicgames.com/forum/viewtopic.php?f=11&t=27250
// which means we need to list everything manually =/
val translationStart = System.currentTimeMillis()
for (language in getLanguagesWithTranslationFile()) {
tryReadTranslationForLanguage(language)
}
val translationFilesTime = System.currentTimeMillis() - translationStart
println("Loading translation files - "+translationFilesTime+"ms")
}
fun writeNewTranslationFiles() {
for (language in getLanguages()) {
val languageHashmap = HashMap<String, String>()
for (translation in values) {
if (translation.containsKey(language))
languageHashmap[translation.entry] = translation[language]!!
}
TranslationFileReader().writeByTemplate(language, languageHashmap)
}
}
fun getPercentageCompleteOfLanguages(): HashMap<String, Int> {
val translationStart = System.currentTimeMillis()
var allTranslations = 0
Gdx.files.internal("jsons/translationsByLanguage/template.properties")
.reader().forEachLine { if(it.contains(" = ")) allTranslations+=1 }
val languageToPercentCompleted = HashMap<String,Int>()
for(language in getLanguagesWithTranslationFile()){
val translationFileName = "jsons/translationsByLanguage/$language.properties"
var translationsOfThisLanguage=0
Gdx.files.internal(translationFileName).reader()
.forEachLine { if(it.contains(" = ") && !it.endsWith(" = "))
translationsOfThisLanguage+=1 }
languageToPercentCompleted[language] = translationsOfThisLanguage*100/allTranslations
}
val translationFilesTime = System.currentTimeMillis() - translationStart
println("Loading percentage complete of languages - "+translationFilesTime+"ms")
return languageToPercentCompleted
}
}
val squareBraceRegex = Regex("\\[(.*?)\\]") // we don't need to allocate different memory for this every time we .tr()
val eitherSquareBraceRegex=Regex("\\[|\\]")
fun String.tr(): String {
// THIS IS INCREDIBLY INEFFICIENT and causes loads of memory problems!
if(contains("[")){ // Placeholders!
/**
* I'm SURE there's an easier way to do this but I can't think of it =\
* So what's all this then?
* Well, not all languages are like English. So say I want to say "work on Library has completed in Akkad",
* but in a completely different language like Japanese or German,
* It could come out "Akkad hast die worken onner Library gerfinishen" or whatever,
* basically, the order of the words in the sentence is not guaranteed.
* So to translate this, I give a sentence like "work on [building] has completed in [city]"
* and the german can put those placeholders where he wants, so "[city] hast die worken onner [building] gerfinishen"
* The string on which we call tr() will look like "work on [library] has completed in [Akkad]"
* We will find the german placeholder text, and replace the placeholders with what was filled in the text we got!
*/
val translationStringWithSquareBracketsOnly = replace(squareBraceRegex,"[]")
val translationEntry = UncivGame.Current.translations.values
.firstOrNull { translationStringWithSquareBracketsOnly == it.entryWithShortenedSquareBrackets }
if(translationEntry==null ||
!translationEntry.containsKey(UncivGame.Current.settings.language)){
// Translation placeholder doesn't exist for this language, default to English
return this.replace(eitherSquareBraceRegex,"")
}
val termsInMessage = squareBraceRegex.findAll(this).map { it.groups[1]!!.value }.toList()
val termsInTranslationPlaceholder = squareBraceRegex.findAll(translationEntry.entry).map { it.value }.toList()
if(termsInMessage.size!=termsInTranslationPlaceholder.size)
throw Exception("Message $this has a different number of terms than the placeholder $translationEntry!")
var languageSpecificPlaceholder = translationEntry[UncivGame.Current.settings.language]!!
for(i in termsInMessage.indices){
languageSpecificPlaceholder = languageSpecificPlaceholder.replace(termsInTranslationPlaceholder[i], termsInMessage[i].tr())
}
return languageSpecificPlaceholder.tr()
}
if(contains("{")){ // sentence
return Regex("\\{(.*?)\\}").replace(this) { it.groups[1]!!.value.tr() }
}
val translation = UncivGame.Current.translations
.get(this, UncivGame.Current.settings.language) // single word
return translation
}

View file

@ -4,7 +4,7 @@ import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.unciv.UncivGame
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import java.util.*

View file

@ -12,7 +12,7 @@ import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.logic.trade.Trade
import com.unciv.logic.trade.TradeOffersList
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.utils.*
import java.text.DecimalFormat

View file

@ -5,8 +5,8 @@ import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UncivGame
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.enable
@ -14,21 +14,15 @@ import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
class LanguageTable(val language:String, ruleset: Ruleset):Table(){
class LanguageTable(val language:String, val percentComplete: Int):Table(){
private val blue = ImageGetter.getBlue()
private val darkBlue = blue.cpy().lerp(Color.BLACK,0.5f)!!
val percentComplete: Int
init{
pad(10f)
defaults().pad(10f)
if(ImageGetter.imageExists("FlagIcons/$language"))
add(ImageGetter.getImage("FlagIcons/$language")).size(40f)
val translations = ruleset.Translations
val availableTranslations = translations.filter { it.value.containsKey(language) }
if(language=="English") percentComplete = 100
else percentComplete = (availableTranslations.size*100 / translations.size) - 1 //-1 so if the user encounters anything not translated he'll be like "OK that's the 1% missing"
val spaceSplitLang = language.replace("_"," ")
add("$spaceSplitLang ($percentComplete%)".toLabel())
@ -61,9 +55,10 @@ class LanguagePickerScreen: PickerScreen(){
"If you want to help translating the game into your language, \n"+
" instructions are in the Github readme! (Menu > Community > Github)",skin)).pad(10f).row()
val ruleSet = UncivGame.Current.ruleset
languageTables.addAll(ruleSet.Translations.getLanguages().map { LanguageTable(it,ruleSet) }
.sortedByDescending { it.percentComplete } )
val languageCompletionPercentage = Translations().getPercentageCompleteOfLanguages()
languageTables.addAll(languageCompletionPercentage
.map { LanguageTable(it.key,if(it.key=="English") 100 else it.value) }
.sortedByDescending { it.percentComplete} )
languageTables.forEach {
it.onClick {
@ -85,6 +80,8 @@ class LanguagePickerScreen: PickerScreen(){
fun pickLanguage(){
UncivGame.Current.settings.language = chosenLanguage
UncivGame.Current.settings.save()
UncivGame.Current.translations.tryReadTranslationForCurrentLanguage()
resetFonts()
UncivGame.Current.startNewGame()
dispose()

View file

@ -7,7 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.pickerscreens.PolicyPickerScreen

View file

@ -11,7 +11,7 @@ import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.GreatPersonManager
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stat
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable

View file

@ -11,7 +11,7 @@ import com.unciv.UncivGame
import com.unciv.logic.HexMath
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.ui.tilegroups.TileSetStrings

View file

@ -5,7 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.ui.TextField
import com.badlogic.gdx.utils.Align
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick

View file

@ -7,7 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.disable

View file

@ -10,7 +10,7 @@ import com.unciv.UncivGame
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.SpecialConstruction
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable

View file

@ -8,7 +8,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.MapSaver
import com.unciv.logic.map.TileMap
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.saves.Gzip
import com.unciv.ui.utils.*

View file

@ -9,7 +9,7 @@ import com.unciv.UncivGame
import com.unciv.logic.MapSaver
import com.unciv.logic.map.MapType
import com.unciv.logic.map.RoadStatus
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.saves.Gzip
import com.unciv.ui.utils.onClick
import com.unciv.ui.worldscreen.optionstable.DropBox

View file

@ -6,7 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.MapSaver
import com.unciv.logic.map.TileMap
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.tilegroups.TileGroup
import com.unciv.ui.tilegroups.TileSetStrings
import com.unciv.ui.utils.CameraStageBaseScreen

View file

@ -14,7 +14,7 @@ import com.unciv.models.ruleset.tile.Terrain
import com.unciv.models.ruleset.tile.TerrainType
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.tile.TileResource
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.tilegroups.TileGroup
import com.unciv.ui.tilegroups.TileSetStrings
import com.unciv.ui.utils.*

View file

@ -6,7 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.MapType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.toLabel

View file

@ -5,8 +5,8 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.models.ruleset.Nation
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.Translations
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.toLabel

View file

@ -10,7 +10,7 @@ import com.unciv.logic.GameInfo
import com.unciv.logic.GameSaver
import com.unciv.logic.GameStarter
import com.unciv.logic.civilization.PlayerType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.enable

View file

@ -11,7 +11,7 @@ import com.unciv.logic.MapSaver
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.VictoryType
import com.unciv.models.ruleset.tech.TechEra
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.metadata.GameSpeed
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.toLabel

View file

@ -11,7 +11,7 @@ import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.civilization.PlayerType
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.metadata.GameParameters
import com.unciv.models.metadata.Player
import com.unciv.ui.utils.*

View file

@ -4,7 +4,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.GreatPersonManager
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.BaseUnit
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.onClick

View file

@ -7,7 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.tile.TileImprovement
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.addSeparatorVertical
import com.unciv.ui.utils.onClick

View file

@ -2,7 +2,7 @@ package com.unciv.ui.pickerscreens
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.unciv.UncivGame
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
open class PickerScreen : CameraStageBaseScreen() {

View file

@ -7,7 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.Policy
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen

View file

@ -8,8 +8,8 @@ import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
import com.badlogic.gdx.utils.Align
import com.unciv.UncivGame
import com.unciv.logic.map.MapUnit
import com.unciv.models.ruleset.Translations
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.Promotion
import com.unciv.ui.utils.*

View file

@ -9,7 +9,7 @@ import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.TechManager
import com.unciv.models.ruleset.tech.Technology
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import java.util.*

View file

@ -10,7 +10,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.unciv.UncivGame
import com.unciv.logic.GameSaver
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.enable

View file

@ -7,7 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.utils.Json
import com.unciv.UncivGame
import com.unciv.logic.GameSaver
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.enable
import com.unciv.ui.utils.onClick

View file

@ -18,7 +18,7 @@ import com.unciv.logic.civilization.diplomacy.RelationshipLevel
import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable
import kotlin.math.roundToInt

View file

@ -6,7 +6,7 @@ import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeOffersList
import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.addSeparator

View file

@ -8,7 +8,7 @@ import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeOffersList
import com.unciv.logic.trade.TradeType
import com.unciv.logic.trade.TradeType.*
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.cityscreen.ExpanderTab
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.disable

View file

@ -6,7 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeRequest
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.enable

View file

@ -12,7 +12,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener
import com.badlogic.gdx.utils.viewport.ExtendViewport
import com.unciv.UncivGame
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import kotlin.concurrent.thread
open class CameraStageBaseScreen : Screen {

View file

@ -34,7 +34,7 @@ class Fonts {
if (Gdx.files.internal("jsons/Tutorials/Tutorials_$language.json").exists())
charSet.addAll(Gdx.files.internal("jsons/Tutorials/Tutorials_$language.json").readString().asIterable())
for (entry in UncivGame.Current.ruleset.Translations.entries) {
for (entry in UncivGame.Current.translations.entries) {
for (lang in entry.value) {
if (lang.key == language) charSet.addAll(lang.value.asIterable())
}

View file

@ -4,7 +4,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Array
import com.unciv.UncivGame
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.worldscreen.optionstable.PopupTable
import java.util.*
import kotlin.collections.ArrayList

View file

@ -5,7 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.PopupAlert
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.optionstable.PopupTable

View file

@ -7,7 +7,7 @@ import com.unciv.Constants
import com.unciv.logic.civilization.diplomacy.DiplomacyFlags
import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.trade.DiplomacyScreen
import com.unciv.ui.utils.addSeparator
import com.unciv.ui.utils.toLabel

View file

@ -15,7 +15,7 @@ import com.unciv.logic.GameSaver
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.UnitType
import com.unciv.ui.VictoryScreen
import com.unciv.ui.cityscreen.CityScreen

View file

@ -10,7 +10,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.tile.ResourceType
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.stats.Stats
import com.unciv.ui.EmpireOverviewScreen
import com.unciv.ui.utils.*

View file

@ -11,7 +11,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.battle.*
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.models.ruleset.unit.UnitType
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen

View file

@ -7,7 +7,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
open class PopupTable(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen.skin) {

View file

@ -4,7 +4,7 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color
import com.unciv.UncivGame
import com.unciv.logic.map.RoadStatus
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.CivilopediaScreen
import com.unciv.ui.VictoryScreen
import com.unciv.ui.mapeditor.MapEditorScreen

View file

@ -7,19 +7,13 @@ import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.utils.Array
import com.unciv.UncivGame
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.Translations
import com.unciv.models.translations.tr
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen
import kotlin.concurrent.thread
class Language(val language:String, ruleset: Ruleset){
val percentComplete:Int
init{
val availableTranslations = ruleset.Translations.count { it.value.containsKey(language) }
if(language=="English") percentComplete = 100
else percentComplete = (availableTranslations*100 / ruleset.Translations.size)
}
class Language(val language:String, val percentComplete:Int){
override fun toString(): String {
val spaceSplitLang = language.replace("_"," ")
return "$spaceSplitLang- $percentComplete%"
@ -275,7 +269,8 @@ class WorldScreenOptionsTable(val worldScreen:WorldScreen) : PopupTable(worldScr
val languageSelectBox = SelectBox<Language>(skin)
val languageArray = Array<Language>()
val ruleSet = worldScreen.gameInfo.ruleSet
ruleSet.Translations.getLanguages().map { Language(it, ruleSet) }
Translations().getPercentageCompleteOfLanguages()
.map { Language(it.key, if(it.key=="English") 100 else it.value) }
.sortedByDescending { it.percentComplete }
.forEach { languageArray.add(it) }
languageSelectBox.items = languageArray
@ -298,7 +293,7 @@ class WorldScreenOptionsTable(val worldScreen:WorldScreen) : PopupTable(worldScr
val missingTextSelectBox = SelectBox<String>(skin)
val missingTextArray = Array<String>()
val currentLanguage = UncivGame.Current.settings.language
ruleSet.Translations.filter { !it.value.containsKey(currentLanguage) }
UncivGame.Current.translations.filter { !it.value.containsKey(currentLanguage) }
.forEach { missingTextArray.add(it.key) }
missingTextSelectBox.items = missingTextArray
missingTextSelectBox.selected = "Untranslated texts"
@ -310,6 +305,8 @@ class WorldScreenOptionsTable(val worldScreen:WorldScreen) : PopupTable(worldScr
fun selectLanguage(){
UncivGame.Current.settings.language = selectedLanguage
UncivGame.Current.settings.save()
UncivGame.Current.translations.tryReadTranslationForCurrentLanguage()
CameraStageBaseScreen.resetFonts() // to load chinese characters if necessary
UncivGame.Current.worldScreen = WorldScreen(worldScreen.viewingCiv)
UncivGame.Current.setWorldScreen()

View file

@ -2,7 +2,7 @@ package com.unciv.ui.worldscreen.optionstable
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel

View file

@ -9,7 +9,7 @@ import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.ImprovementPickerScreen
import com.unciv.ui.pickerscreens.PromotionPickerScreen
import com.unciv.ui.worldscreen.WorldScreen

View file

@ -3,7 +3,6 @@ package com.unciv.ui.worldscreen.unit
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
import com.unciv.UncivGame
@ -11,7 +10,7 @@ import com.unciv.logic.battle.CityCombatant
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PromotionPickerScreen
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen

View file

@ -9,7 +9,7 @@ import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.tools.texturepacker.TexturePacker
import com.unciv.UncivGame
import com.unciv.models.ruleset.tr
import com.unciv.models.translations.tr
import java.io.File
import kotlin.concurrent.thread