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:
parent
77d00f35bb
commit
3627d4e6e2
64 changed files with 347 additions and 325 deletions
|
@ -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()
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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){
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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.*
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.unciv.models.stats
|
||||
|
||||
import com.unciv.models.ruleset.tr
|
||||
import com.unciv.models.translations.tr
|
||||
|
||||
|
||||
open class Stats() {
|
||||
|
|
14
core/src/com/unciv/models/translations/TranslationEntry.kt
Normal file
14
core/src/com/unciv/models/translations/TranslationEntry.kt
Normal 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,"[]")
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
||||
}
|
199
core/src/com/unciv/models/translations/Translations.kt
Normal file
199
core/src/com/unciv/models/translations/Translations.kt
Normal 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
|
||||
}
|
|
@ -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.*
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.*
|
||||
|
||||
|
|
|
@ -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.*
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue