Translation refactoring - part 2 (Tutorials) (#2114)

* Make TranslationFileReader as object class

* Generate strings from Tutorials.json

* Simplified storage and loading of the tutorials

* Transfer existing translations
This commit is contained in:
Jack Rainy
2020-03-12 16:38:57 +02:00
committed by GitHub
parent c7e8dfb8fb
commit dd438f16c8
35 changed files with 670 additions and 3196 deletions

View File

@ -81,7 +81,7 @@ class UncivGame(
if (rewriteTranslationFiles) { // Yes, also when running from the Jar. Sue me.
translations.readAllLanguagesTranslation()
TranslationFileReader().writeNewTranslationFiles(translations)
TranslationFileReader.writeNewTranslationFiles(translations)
} else {
translations.tryReadTranslationForCurrentLanguage()
}

View File

@ -5,11 +5,12 @@ import com.unciv.JsonParser
import com.unciv.models.ruleset.Nation
import java.nio.charset.Charset
import kotlin.collections.set
import com.badlogic.gdx.utils.Array
class TranslationFileReader{
object TranslationFileReader {
private val percentagesFileLocation = "jsons/translations/completionPercentages.properties"
val templateFileLocation = "jsons/translations/template.properties"
private const val percentagesFileLocation = "jsons/translations/completionPercentages.properties"
const val templateFileLocation = "jsons/translations/template.properties"
private val charset = Charset.forName("UTF-8").name()
fun read(translationFile: String): LinkedHashMap<String, String> {
@ -34,6 +35,8 @@ class TranslationFileReader{
linesFromTemplates.addAll(templateFile.reader().readLines())
linesFromTemplates.add("\n#################### Lines from Nations.json ####################\n")
linesFromTemplates.addAll(generateNationsStrings())
linesFromTemplates.add("\n#################### Lines from Tutorials.json ####################\n")
linesFromTemplates.addAll(generateTutorialsStrings())
val stringBuilder = StringBuilder()
for(line in linesFromTemplates){
@ -113,4 +116,16 @@ class TranslationFileReader{
return strings
}
fun generateTutorialsStrings(): Collection<String> {
val tutorials = JsonParser().getFromJson(LinkedHashMap<String, Array<String>>().javaClass, "jsons/Tutorials.json")
val strings = mutableSetOf<String>() // using set to avoid duplicates
for (tutorial in tutorials) {
for (str in tutorial.value)
if (str != "") strings.add("$str = ")
}
return strings
}
}

View File

@ -41,8 +41,7 @@ class Translations : LinkedHashMap<String, TranslationEntry>(){
val languageTranslations:HashMap<String,String>
try { // On some devices we get a weird UnsupportedEncodingException
// which is super odd because everyone should support UTF-8
languageTranslations = TranslationFileReader()
.read(translationFileName)
languageTranslations = TranslationFileReader.read(translationFileName)
}catch (ex:Exception){
return
}
@ -111,7 +110,7 @@ class Translations : LinkedHashMap<String, TranslationEntry>(){
fun loadPercentageCompleteOfLanguages(){
val startTime = System.currentTimeMillis()
percentCompleteOfLanguages = TranslationFileReader().readLanguagePercentages()
percentCompleteOfLanguages = TranslationFileReader.readLanguagePercentages()
val translationFilesTime = System.currentTimeMillis() - startTime
println("Loading percent complete of languages - "+translationFilesTime+"ms")
@ -121,8 +120,9 @@ class Translations : LinkedHashMap<String, TranslationEntry>(){
val percentComplete = HashMap<String,Int>()
val translationStart = System.currentTimeMillis()
var allTranslations = TranslationFileReader().generateNationsStrings().size
Gdx.files.internal(TranslationFileReader().templateFileLocation)
var allTranslations = TranslationFileReader.generateNationsStrings().size
allTranslations += TranslationFileReader.generateTutorialsStrings().size
Gdx.files.internal(TranslationFileReader.templateFileLocation)
.reader().forEachLine { if(it.contains(" = ")) allTranslations+=1 }
for(language in getLanguagesWithTranslationFile()){

View File

@ -2,11 +2,9 @@ package com.unciv.ui
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.unciv.JsonParser
import com.unciv.UncivGame
import com.unciv.models.ruleset.Ruleset
import com.unciv.models.translations.tr
import com.unciv.ui.tutorials.TutorialMiner
import com.unciv.ui.utils.*
import java.util.*
@ -19,8 +17,6 @@ class CivilopediaScreen(ruleset: Ruleset) : CameraStageBaseScreen() {
private val entrySelectTable = Table().apply { defaults().pad(5f) }
val description = "".toLabel()
private val tutorialMiner = TutorialMiner(JsonParser())
fun select(category: String) {
entrySelectTable.clear()
for (entry in categoryToEntries[category]!!
@ -87,8 +83,8 @@ class CivilopediaScreen(ruleset: Ruleset) : CameraStageBaseScreen() {
.map { CivilopediaEntry(it.name,it.getDescription(ruleset.unitPromotions.values, true),
Table().apply { add(ImageGetter.getPromotionIcon(it.name)) }) }
categoryToEntries["Tutorials"] = tutorialMiner.getCivilopediaTutorials(UncivGame.Current.settings.language)
.map { CivilopediaEntry(it.key.value.replace("_"," "), it.value.joinToString("\n\n")) }
categoryToEntries["Tutorials"] = tutorialController.getCivilopediaTutorials()
.map { CivilopediaEntry(it.key.replace("_"," "), it.value.joinToString("\n\n") { line -> line.tr() }) }
for (category in categoryToEntries.keys) {
val button = TextButton(category.tr(), skin)

View File

@ -1,16 +1,18 @@
package com.unciv.ui.tutorials
import com.badlogic.gdx.utils.Array
import com.unciv.JsonParser
import com.unciv.UncivGame
import com.unciv.models.Tutorial
import com.unciv.ui.utils.CameraStageBaseScreen
class TutorialController(
private val tutorialMiner: TutorialMiner,
private val tutorialRender: TutorialRender
) {
class TutorialController(screen: CameraStageBaseScreen) {
private val tutorialQueue = mutableSetOf<Tutorial>()
private var isTutorialShowing = false
var allTutorialsShowedCallback: (() -> Unit)? = null
private val tutorialRender = TutorialRender(screen)
private val tutorials = JsonParser().getFromJson(LinkedHashMap<String, Array<String>>().javaClass, "jsons/Tutorials.json")
fun showTutorial(tutorial: Tutorial) {
if (!UncivGame.Current.settings.showTutorials) return
@ -26,7 +28,7 @@ class TutorialController(
allTutorialsShowedCallback?.invoke()
} else if (!isTutorialShowing) {
isTutorialShowing = true
val texts = tutorialMiner.getTutorial(tutorial, UncivGame.Current.settings.language)
val texts = getTutorial(tutorial)
tutorialRender.showTutorial(TutorialForRender(tutorial, texts)) {
tutorialQueue.remove(tutorial)
isTutorialShowing = false
@ -40,4 +42,13 @@ class TutorialController(
}
}
}
fun getCivilopediaTutorials(): Map<String, Array<String>> {
return tutorials.filter { Tutorial.findByName(it.key)!!.isCivilopedia }
}
private fun getTutorial(tutorial: Tutorial): Array<String> {
return tutorials[tutorial.value] ?: Array()
}
}

View File

@ -1,40 +0,0 @@
package com.unciv.ui.tutorials
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.utils.Array
import com.unciv.JsonParser
import com.unciv.models.Tutorial
class TutorialMiner(private val jsonParser: JsonParser) {
companion object {
private const val TUTORIALS_PATH = "jsons/Tutorials/Tutorials_%s.json"
}
fun getCivilopediaTutorials(language: String): Map<Tutorial, List<String>> =
getAllTutorials(language).filter { it.key.isCivilopedia }
fun getTutorial(tutorial: Tutorial, language: String): List<String> {
val tutors = getAllTutorials(language)[tutorial]
if (tutors != null) {
return tutors
} else {
return emptyList()
}
}
private fun getAllTutorials(language: String): Map<Tutorial, List<String>> {
val path = TUTORIALS_PATH.format(language)
if (!Gdx.files.internal(path).exists()) return emptyMap()
// ...Yes. Disgusting. I wish I didn't have to do this.
val x = LinkedHashMap<String, Array<Array<String>>>()
val tutorials: LinkedHashMap<String, Array<Array<String>>> = jsonParser.getFromJson(x.javaClass, path)
val tutorialMap = mutableMapOf<Tutorial, List<String>>()
for (tutorial in tutorials) {
tutorialMap[Tutorial.findByName(tutorial.key)!!] = tutorial.value.map { it.joinToString("\n") }
}
return tutorialMap
}
}

View File

@ -2,6 +2,7 @@ package com.unciv.ui.tutorials
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Array
import com.unciv.models.Tutorial
import com.unciv.models.translations.tr
import com.unciv.ui.utils.CameraStageBaseScreen
@ -9,7 +10,7 @@ import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.Popup
import com.unciv.ui.utils.onClick
data class TutorialForRender(val tutorial: Tutorial, val texts: List<String>)
data class TutorialForRender(val tutorial: Tutorial, val texts: Array<String>)
class TutorialRender(private val screen: CameraStageBaseScreen) {
@ -17,7 +18,7 @@ class TutorialRender(private val screen: CameraStageBaseScreen) {
showDialog(tutorial.tutorial.name, tutorial.texts, closeAction)
}
private fun showDialog(tutorialName: String, texts: List<String>, closeAction: () -> Unit) {
private fun showDialog(tutorialName: String, texts: Array<String>, closeAction: () -> Unit) {
val text = texts.firstOrNull()
if (text == null) {
closeAction()
@ -33,7 +34,8 @@ class TutorialRender(private val screen: CameraStageBaseScreen) {
val button = TextButton("Close".tr(), CameraStageBaseScreen.skin)
button.onClick {
tutorialPopup.remove()
showDialog(tutorialName, texts - text, closeAction)
texts.removeIndex(0)
showDialog(tutorialName, texts, closeAction)
}
tutorialPopup.add(button).pad(10f)
tutorialPopup.open()

View File

@ -11,14 +11,11 @@ import com.badlogic.gdx.scenes.scene2d.*
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.JsonParser
import com.unciv.UncivGame
import com.unciv.models.Tutorial
import com.unciv.models.UncivSound
import com.unciv.models.translations.tr
import com.unciv.ui.tutorials.TutorialController
import com.unciv.ui.tutorials.TutorialMiner
import com.unciv.ui.tutorials.TutorialRender
import kotlin.concurrent.thread
open class CameraStageBaseScreen : Screen {
@ -26,9 +23,7 @@ open class CameraStageBaseScreen : Screen {
var game: UncivGame = UncivGame.Current
var stage: Stage
val tutorialController by lazy {
TutorialController(TutorialMiner(JsonParser()), TutorialRender(this))
}
protected val tutorialController by lazy { TutorialController(this) }
init {
val width:Float
@ -66,9 +61,7 @@ open class CameraStageBaseScreen : Screen {
override fun dispose() {}
fun displayTutorial(tutorial: Tutorial) {
tutorialController.showTutorial(tutorial)
}
fun displayTutorial(tutorial: Tutorial) = tutorialController.showTutorial(tutorial)
companion object {
var skin = Skin(Gdx.files.internal("skin/flat-earth-ui.json"))
@ -90,7 +83,7 @@ open class CameraStageBaseScreen : Screen {
/** It returns the assigned [InputListener] */
fun onBackButtonClicked(action:()->Unit): InputListener {
var listener = object : InputListener(){
val listener = object : InputListener(){
override fun keyDown(event: InputEvent?, keycode: Int): Boolean {
if(keycode == Input.Keys.BACK){
action()

View File

@ -30,9 +30,6 @@ class Fonts {
charSet.addAll(defaultText.asIterable())
if (language != "") {
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.translations.entries) {
for (lang in entry.value) {
if (lang.key == language) charSet.addAll(lang.value.asIterable())

View File

@ -517,7 +517,7 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
// remove current listener for the "BACK" button to avoid showing the dialog twice
stage.removeListener( backButtonListener )
var promptWindow = Popup(this)
val promptWindow = Popup(this)
promptWindow.addGoodSizedLabel("Do you want to exit the game?".tr())
promptWindow.row()
promptWindow.addButton("Yes"){game.exitEvent?.invoke()}