mirror of
https://github.com/yairm210/Unciv.git
synced 2025-08-03 20:48:49 -04:00
Reworked Locale handling + deprecations + linting (#13142)
* Linting and deprecations * Trial and error for Locale factories * Reworked Locale handling * Clean up fastlane for Rusyn * Decide open question in favour of supported methods
This commit is contained in:
parent
8a1f14e683
commit
1c7a50e1c9
@ -143,7 +143,7 @@ open class FileChooser(
|
|||||||
add(fileScroll).colspan(2).fill().row()
|
add(fileScroll).colspan(2).fill().row()
|
||||||
addSeparator(height = 1f)
|
addSeparator(height = 1f)
|
||||||
fileNameCell = add().colspan(2).growX()
|
fileNameCell = add().colspan(2).growX()
|
||||||
row()
|
super.row()
|
||||||
|
|
||||||
addCloseButton(Constants.cancel) {
|
addCloseButton(Constants.cancel) {
|
||||||
reportResult(false)
|
reportResult(false)
|
||||||
|
@ -59,7 +59,7 @@ class UncivFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getModsFolder() = getLocalFile("mods")
|
fun getModsFolder() = getLocalFile("mods")
|
||||||
fun getModFolder(modName: String) = getModsFolder().child(modName)
|
fun getModFolder(modName: String): FileHandle = getModsFolder().child(modName)
|
||||||
|
|
||||||
/** The folder that holds data that the game changes while running - all the mods, maps, save files, etc */
|
/** The folder that holds data that the game changes while running - all the mods, maps, save files, etc */
|
||||||
fun getDataFolder() = getLocalFile("")
|
fun getDataFolder() = getLocalFile("")
|
||||||
@ -167,7 +167,7 @@ class UncivFiles(
|
|||||||
/**
|
/**
|
||||||
* Only use this with a [FileHandle] obtained by one of the methods of this class!
|
* Only use this with a [FileHandle] obtained by one of the methods of this class!
|
||||||
*/
|
*/
|
||||||
fun saveGame(game: GameInfo, file: FileHandle, saveCompletionCallback: (Exception?) -> Unit = { if (it != null) throw it }) {
|
private fun saveGame(game: GameInfo, file: FileHandle, saveCompletionCallback: (Exception?) -> Unit = { if (it != null) throw it }) {
|
||||||
try {
|
try {
|
||||||
debug("Saving GameInfo %s to %s", game.gameId, file.path())
|
debug("Saving GameInfo %s to %s", game.gameId, file.path())
|
||||||
val string = gameInfoToString(game)
|
val string = gameInfoToString(game)
|
||||||
@ -322,7 +322,7 @@ class UncivFiles(
|
|||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Scenarios
|
//region Scenarios
|
||||||
val scenarioFolder = "scenarios"
|
private val scenarioFolder = "scenarios"
|
||||||
fun getScenarioFiles() = sequence {
|
fun getScenarioFiles() = sequence {
|
||||||
for (mod in RulesetCache.values) {
|
for (mod in RulesetCache.values) {
|
||||||
val modFolder = mod.folderLocation ?: continue
|
val modFolder = mod.folderLocation ?: continue
|
||||||
|
@ -19,7 +19,7 @@ import java.io.FileFilter
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URI
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.util.zip.ZipException
|
import java.util.zip.ZipException
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ object Github {
|
|||||||
// Consider merging this with the Dropbox function
|
// Consider merging this with the Dropbox function
|
||||||
/**
|
/**
|
||||||
* Helper opens an url and accesses its input stream, logging errors to the console
|
* Helper opens an url and accesses its input stream, logging errors to the console
|
||||||
* @param url String representing a [URL] to download.
|
* @param url String representing a [URI] to download.
|
||||||
* @param preDownloadAction Optional callback that will be executed between opening the connection and
|
* @param preDownloadAction Optional callback that will be executed between opening the connection and
|
||||||
* accessing its data - passes the [connection][HttpURLConnection] and allows e.g. reading the response headers.
|
* accessing its data - passes the [connection][HttpURLConnection] and allows e.g. reading the response headers.
|
||||||
* @return The [InputStream] if successful, `null` otherwise.
|
* @return The [InputStream] if successful, `null` otherwise.
|
||||||
@ -56,9 +56,8 @@ object Github {
|
|||||||
fun download(url: String, preDownloadAction: (HttpURLConnection) -> Unit = {}): InputStream? {
|
fun download(url: String, preDownloadAction: (HttpURLConnection) -> Unit = {}): InputStream? {
|
||||||
try {
|
try {
|
||||||
// Problem type 1 - opening the URL connection
|
// Problem type 1 - opening the URL connection
|
||||||
@Suppress("DEPRECATION") // We still support Java < 20
|
// URL(string) is deprecated, URI.toUrl(string) API level 36, see [Android Doc](https://developer.android.com/reference/java/net/URI#toURL()):
|
||||||
with(URL(url).openConnection() as HttpURLConnection)
|
with(URI(url).toURL().openConnection() as HttpURLConnection) {
|
||||||
{
|
|
||||||
preDownloadAction(this)
|
preDownloadAction(this)
|
||||||
// Problem type 2 - getting the information
|
// Problem type 2 - getting the information
|
||||||
try {
|
try {
|
||||||
|
@ -9,8 +9,7 @@ import java.io.DataOutputStream
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URI
|
||||||
import java.nio.charset.Charset
|
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import kotlin.concurrent.timer
|
import kotlin.concurrent.timer
|
||||||
@ -25,7 +24,8 @@ object DropBox: FileStorage {
|
|||||||
if (remainingRateLimitSeconds > 0)
|
if (remainingRateLimitSeconds > 0)
|
||||||
throw FileStorageRateLimitReached(remainingRateLimitSeconds)
|
throw FileStorageRateLimitReached(remainingRateLimitSeconds)
|
||||||
|
|
||||||
with(URL(url).openConnection() as HttpURLConnection) {
|
// URL(string) is deprecated, URI.toUrl(string) API level 36:
|
||||||
|
with(URI(url).toURL().openConnection() as HttpURLConnection) {
|
||||||
requestMethod = "POST" // default is GET
|
requestMethod = "POST" // default is GET
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
|
@ -7,8 +7,6 @@ import com.unciv.Constants
|
|||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.logic.multiplayer.FriendList
|
import com.unciv.logic.multiplayer.FriendList
|
||||||
import com.unciv.models.UncivSound
|
import com.unciv.models.UncivSound
|
||||||
import com.unciv.models.translations.Translations.Companion.getLocaleFromLanguage
|
|
||||||
import com.unciv.models.translations.Translations.Companion.getNumberFormatFromLanguage
|
|
||||||
import com.unciv.ui.components.fonts.FontFamilyData
|
import com.unciv.ui.components.fonts.FontFamilyData
|
||||||
import com.unciv.ui.components.fonts.Fonts
|
import com.unciv.ui.components.fonts.Fonts
|
||||||
import com.unciv.ui.components.input.KeyboardBindings
|
import com.unciv.ui.components.input.KeyboardBindings
|
||||||
@ -175,7 +173,7 @@ class GameSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateLocaleFromLanguage() {
|
fun updateLocaleFromLanguage() {
|
||||||
locale = getLocaleFromLanguage(language)
|
locale = LocaleCode.getLocale(language)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFontSize(): Int {
|
fun getFontSize(): Int {
|
||||||
@ -193,7 +191,7 @@ class GameSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentNumberFormat(): NumberFormat {
|
fun getCurrentNumberFormat(): NumberFormat {
|
||||||
return getNumberFormatFromLanguage(language)
|
return LocaleCode.getNumberFormatFromLanguage(language)
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@ -262,67 +260,6 @@ class GameSettings {
|
|||||||
|
|
||||||
enum class NationPickerListMode { Icons, List }
|
enum class NationPickerListMode { Icons, List }
|
||||||
|
|
||||||
/** Map Unciv language key to Java locale, for the purpose of getting a Collator for sorting.
|
|
||||||
* - Effect depends on the Java libraries and may not always conform to expectations.
|
|
||||||
* If in doubt, debug and see what Locale instance you get and compare its properties with `Locale.getDefault()`.
|
|
||||||
* (`Collator.getInstance(LocaleCode.*.run { Locale(language, country) }) to Collator.getInstance()`, drill to both `rules`, compare hashes - if equal and other properties equal, then Java doesn't know your Language))
|
|
||||||
* @property name same as translation file name with ' ', '_', '-', '(', ')' removed
|
|
||||||
* @property language ISO 639-1 code for the language
|
|
||||||
* @property country ISO 3166 code for the nation this is predominantly spoken in
|
|
||||||
* @property trueLanguage If set, used instead of language to trick Java into supplying a close-enough collator (a no-match would otherwise give us the default collator, not a collator for a partial match)
|
|
||||||
*/
|
|
||||||
enum class LocaleCode(val language: String, val country: String, val trueLanguage: String? = null) {
|
|
||||||
Afrikaans("af", "ZA"),
|
|
||||||
Arabic("ar", "IQ"),
|
|
||||||
Bangla("bn", "BD"),
|
|
||||||
Belarusian("be", "BY"),
|
|
||||||
Bosnian("bs", "BA"),
|
|
||||||
BrazilianPortuguese("pt", "BR"),
|
|
||||||
Bulgarian("bg", "BG"),
|
|
||||||
Catalan("ca", "ES"),
|
|
||||||
Croatian("hr", "HR"),
|
|
||||||
Czech("cs", "CZ"),
|
|
||||||
Danish("da", "DK"),
|
|
||||||
Dutch("nl", "NL"),
|
|
||||||
English("en", "US"),
|
|
||||||
Estonian("et", "EE"),
|
|
||||||
Finnish("fi", "FI"),
|
|
||||||
French("fr", "FR"),
|
|
||||||
Galician("gl", "ES"),
|
|
||||||
German("de", "DE"),
|
|
||||||
Greek("el", "GR"),
|
|
||||||
Hindi("hi", "IN"),
|
|
||||||
Hungarian("hu", "HU"),
|
|
||||||
Indonesian("in", "ID"),
|
|
||||||
Italian("it", "IT"),
|
|
||||||
Japanese("ja", "JP"),
|
|
||||||
Korean("ko", "KR"),
|
|
||||||
Latin("la", "IT"),
|
|
||||||
Latvian("lv", "LV"),
|
|
||||||
Lithuanian("lt", "LT"),
|
|
||||||
Malay("ms", "MY"),
|
|
||||||
Norwegian("no", "NO"),
|
|
||||||
NorwegianNynorsk("nn", "NO"),
|
|
||||||
PersianPinglishDIN("fa", "IR"), // These might just fall back to default
|
|
||||||
PersianPinglishUN("fa", "IR"),
|
|
||||||
Polish("pl", "PL"),
|
|
||||||
Portuguese("pt", "PT"),
|
|
||||||
Romanian("ro", "RO"),
|
|
||||||
Russian("ru", "RU"),
|
|
||||||
Rusyn("uk", "UA", "rus"), // No specific locale for rus exists, so use closest for collator
|
|
||||||
Serbian("sr", "RS"),
|
|
||||||
SimplifiedChinese("zh", "CN"),
|
|
||||||
Slovak("sk", "SK"),
|
|
||||||
Spanish("es", "ES"),
|
|
||||||
Swedish("sv", "SE"),
|
|
||||||
Thai("th", "TH"),
|
|
||||||
TraditionalChinese("zh", "TW"),
|
|
||||||
Turkish("tr", "TR"),
|
|
||||||
Ukrainian("uk", "UA"),
|
|
||||||
Vietnamese("vi", "VN"),
|
|
||||||
Zulu("zu", "ZA")
|
|
||||||
}
|
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
//region Multiplayer-specific
|
//region Multiplayer-specific
|
||||||
|
|
||||||
|
97
core/src/com/unciv/models/metadata/LocaleCode.kt
Normal file
97
core/src/com/unciv/models/metadata/LocaleCode.kt
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package com.unciv.models.metadata
|
||||||
|
|
||||||
|
import java.text.NumberFormat
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/** Map Unciv language key to Java locale, for the purpose of getting a Collator for sorting.
|
||||||
|
* - Effect depends on the Java libraries and may not always conform to expectations.
|
||||||
|
* If in doubt, debug and see what Locale instance you get and compare its properties with `Locale.getDefault()`.
|
||||||
|
* (`Collator.getInstance(LocaleCode.*.run { Locale(language, country) }) to Collator.getInstance()`, drill to both `rules`, compare hashes - if equal and other properties equal, then Java doesn't know your Language))
|
||||||
|
* - For languages without an easy predefined Locale, collation or numeric formats can be forced using [Unicode Extensions for BCP 47](https://www.unicode.org/reports/tr35/#Locale_Extension_Key_and_Type_Data).
|
||||||
|
*
|
||||||
|
* @property name **Must** be the same as the translation file name with ' ', '_', '-', '(', ')' removed
|
||||||
|
* @property languageTag IETF BCP 47 language tag - see [forLanguageTag][Locale.forLanguageTag] or [Android reference][https://developer.android.com/reference/java/util/Locale#forLanguageTag(java.lang.String)]
|
||||||
|
* Usually the ISO 639-1 code for the language, a dash, and the ISO 3166 code for the nation this is predominantly spoken in
|
||||||
|
* @property fastlaneFolder If set, it's used instead of the language part of [languageTag] as fastlane folder name
|
||||||
|
*/
|
||||||
|
enum class LocaleCode(val languageTag: String, private val fastlaneFolder: String? = null) {
|
||||||
|
Afrikaans("af-ZA"),
|
||||||
|
Arabic("ar-IQ"),
|
||||||
|
Bangla("bn-BD"),
|
||||||
|
Belarusian("be-BY"),
|
||||||
|
Bosnian("bs-BA"),
|
||||||
|
BrazilianPortuguese("pt-BR"),
|
||||||
|
Bulgarian("bg-BG"),
|
||||||
|
Catalan("ca-ES"),
|
||||||
|
Croatian("hr-HR"),
|
||||||
|
Czech("cs-CZ"),
|
||||||
|
Danish("da-DK"),
|
||||||
|
Dutch("nl-NL"),
|
||||||
|
English("en-US"),
|
||||||
|
Estonian("et-EE"),
|
||||||
|
Finnish("fi-FI"),
|
||||||
|
French("fr-FR"),
|
||||||
|
Galician("gl-ES"),
|
||||||
|
German("de-DE"),
|
||||||
|
Greek("el-GR"),
|
||||||
|
Hindi("hi-IN"),
|
||||||
|
Hungarian("hu-HU"),
|
||||||
|
Indonesian("in-ID"),
|
||||||
|
Italian("it-IT"),
|
||||||
|
Japanese("ja-JP"),
|
||||||
|
Korean("ko-KR"),
|
||||||
|
Latin("la-IT"),
|
||||||
|
Latvian("lv-LV"),
|
||||||
|
Lithuanian("lt-LT"),
|
||||||
|
Malay("ms-MY"),
|
||||||
|
Norwegian("no-NO"),
|
||||||
|
NorwegianNynorsk("nn-NO"),
|
||||||
|
PersianPinglishDIN("fa-IR"), // These might just fall back to default
|
||||||
|
PersianPinglishUN("fa-IR"),
|
||||||
|
Polish("pl-PL"),
|
||||||
|
Portuguese("pt-PT"),
|
||||||
|
Romanian("ro-RO"),
|
||||||
|
Russian("ru-RU"),
|
||||||
|
Rusyn("rue-SK-u-kr-cyrl-latn-digit", "rue"), // No specific locale exists, so use explicit cyrillic collation. Chose country with most speakers.
|
||||||
|
Serbian("sr-RS"),
|
||||||
|
SimplifiedChinese("zh-CN"),
|
||||||
|
Slovak("sk-SK"),
|
||||||
|
Spanish("es-ES"),
|
||||||
|
Swedish("sv-SE"),
|
||||||
|
Thai("th-TH"),
|
||||||
|
TraditionalChinese("zh-TW"),
|
||||||
|
Turkish("tr-TR"),
|
||||||
|
Ukrainian("uk-UA"),
|
||||||
|
Vietnamese("vi-VN"),
|
||||||
|
Zulu("zu-ZA")
|
||||||
|
;
|
||||||
|
|
||||||
|
fun locale(): Locale = Locale.forLanguageTag(languageTag)
|
||||||
|
fun fastlaneFolder(): String = this.fastlaneFolder ?: locale().language
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val bannedCharacters = listOf(' ', '_', '-', '(', ')') // Things not to have in enum names
|
||||||
|
|
||||||
|
/** Find a LocaleCode for a [language] as stored in GameSettings */
|
||||||
|
fun find(language: String): LocaleCode? {
|
||||||
|
val languageName = language.filterNot { it in bannedCharacters }
|
||||||
|
return LocaleCode.entries.firstOrNull { it.name == languageName }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a Java Locale for a [language] as stored in GameSettings */
|
||||||
|
fun getLocale(language: String): Locale =
|
||||||
|
find(language)?.locale() ?: Locale.getDefault()
|
||||||
|
|
||||||
|
/** Get the fastlane folder name for a [language] as stored in GameSettings */
|
||||||
|
fun fastlaneFolder(language: String) =
|
||||||
|
find(language)?.fastlaneFolder() ?: "en"
|
||||||
|
|
||||||
|
// NumberFormat cache, key: language, value: NumberFormat
|
||||||
|
private val languageToNumberFormat = mutableMapOf<String, NumberFormat>()
|
||||||
|
|
||||||
|
fun getNumberFormatFromLanguage(language: String): NumberFormat =
|
||||||
|
languageToNumberFormat.getOrPut(language) {
|
||||||
|
NumberFormat.getInstance(getLocale(language))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ import com.unciv.json.json
|
|||||||
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
|
||||||
import com.unciv.models.SpyAction
|
import com.unciv.models.SpyAction
|
||||||
import com.unciv.models.metadata.BaseRuleset
|
import com.unciv.models.metadata.BaseRuleset
|
||||||
import com.unciv.models.metadata.GameSettings.LocaleCode
|
import com.unciv.models.metadata.LocaleCode
|
||||||
import com.unciv.models.ruleset.Belief
|
import com.unciv.models.ruleset.Belief
|
||||||
import com.unciv.models.ruleset.Building
|
import com.unciv.models.ruleset.Building
|
||||||
import com.unciv.models.ruleset.Event
|
import com.unciv.models.ruleset.Event
|
||||||
@ -558,8 +558,7 @@ object TranslationFileWriter {
|
|||||||
!endWithNewline && translated.endsWith('\n') -> translated.removeSuffix("\n")
|
!endWithNewline && translated.endsWith('\n') -> translated.removeSuffix("\n")
|
||||||
else -> translated
|
else -> translated
|
||||||
}
|
}
|
||||||
val localeCode = LocaleCode.valueOf(language.replace("_",""))
|
val path = fastlanePath + LocaleCode.fastlaneFolder(language)
|
||||||
val path = fastlanePath + (localeCode.trueLanguage ?: localeCode.language)
|
|
||||||
File(path).mkdirs()
|
File(path).mkdirs()
|
||||||
File(path + File.separator + fileName).writeText(fileContent)
|
File(path + File.separator + fileName).writeText(fileContent)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package com.unciv.models.translations
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.models.metadata.GameSettings.LocaleCode
|
import com.unciv.models.metadata.LocaleCode
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.ruleset.unique.Unique
|
import com.unciv.models.ruleset.unique.Unique
|
||||||
import com.unciv.models.stats.Stat
|
import com.unciv.models.stats.Stat
|
||||||
@ -14,7 +14,6 @@ import com.unciv.utils.Log
|
|||||||
import com.unciv.utils.debug
|
import com.unciv.utils.debug
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import org.jetbrains.annotations.VisibleForTesting
|
import org.jetbrains.annotations.VisibleForTesting
|
||||||
import java.text.NumberFormat
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This collection holds all translations for the game.
|
* This collection holds all translations for the game.
|
||||||
@ -209,11 +208,8 @@ class Translations : LinkedHashMap<String, TranslationEntry>() {
|
|||||||
return getText(englishConditionalOrderingString, language, null)
|
return getText(englishConditionalOrderingString, language, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun placeConditionalsAfterUnique(language: String): Boolean {
|
fun placeConditionalsAfterUnique(language: String) =
|
||||||
if (get(conditionalUniqueOrderString, language, null)?.get(language) == "before")
|
get(conditionalUniqueOrderString, language, null)?.get(language) != "before"
|
||||||
return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the equivalent of a space in the given language
|
/** Returns the equivalent of a space in the given language
|
||||||
* Defaults to a space if no translation is provided
|
* Defaults to a space if no translation is provided
|
||||||
@ -239,26 +235,6 @@ class Translations : LinkedHashMap<String, TranslationEntry>() {
|
|||||||
const val conditionalUniqueOrderString = "ConditionalsPlacement"
|
const val conditionalUniqueOrderString = "ConditionalsPlacement"
|
||||||
const val shouldCapitalizeString = "StartWithCapitalLetter"
|
const val shouldCapitalizeString = "StartWithCapitalLetter"
|
||||||
const val effectBeforeCause = "EffectBeforeCause"
|
const val effectBeforeCause = "EffectBeforeCause"
|
||||||
|
|
||||||
// NumberFormat cache, key: language, value: NumberFormat
|
|
||||||
private val languageToNumberFormat = mutableMapOf<String, NumberFormat>()
|
|
||||||
|
|
||||||
fun getLocaleFromLanguage(language: String): Locale {
|
|
||||||
val bannedCharacters =
|
|
||||||
listOf(' ', '_', '-', '(', ')') // Things not to have in enum names
|
|
||||||
val languageName = language.filterNot { it in bannedCharacters }
|
|
||||||
return try {
|
|
||||||
val code = LocaleCode.valueOf(languageName)
|
|
||||||
Locale(code.language, code.country)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
Locale.getDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNumberFormatFromLanguage(language: String): NumberFormat =
|
|
||||||
languageToNumberFormat.getOrPut(language) {
|
|
||||||
NumberFormat.getInstance(getLocaleFromLanguage(language))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,5 +548,5 @@ fun Number.tr(): String {
|
|||||||
|
|
||||||
// formats number according to given language
|
// formats number according to given language
|
||||||
fun Number.tr(language: String): String {
|
fun Number.tr(language: String): String {
|
||||||
return Translations.getNumberFormatFromLanguage(language).format(this)
|
return LocaleCode.getNumberFormatFromLanguage(language).format(this)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
Удтвореня майпопуларної бавкы за створьованя цвілізацій – фрішноє, манінькоє, без рекламы, навхтема бесплатноє
|
|
||||||
Стройте свою цівілізацію, изучайте технолоґії, росширяйте свої території, сказіт тай дотовчіт своїх ворогув!
|
|
||||||
|
|
||||||
Понуканя? Багы? Испис задач сьої бавкы увидьте туйкы https://github.com/yairm210/Unciv/issues, ушитка помуч дуже ся чистує!
|
|
||||||
|
|
||||||
Звіданкы? Коментарії? Просто лудно? Прикапчуйте ся ид нам у діскордови https://discord.gg/bjrB4Xw.
|
|
||||||
|
|
||||||
Хотіли бы-сьте помочи перекласти бавку вашым языком? Напишіт ми мейл на yairm210@hotmail.com.
|
|
||||||
|
|
||||||
Знаєте за Grok Java авадь Kotlin? Пойте сюды https://github.com/yairm210/Unciv.
|
|
||||||
|
|
||||||
Світ вас чекат! Ци вчините из свойої цівілізації імперію, яка утримат провбу часом?
|
|
||||||
|
|
||||||
Позволеня на доступ ид сіті мусай дати про ініціовані бавлячом стирьханя тай про мультіплеєрноє бавліня. Ушиткі другі позволеня самі ся додавут API, якый изхосновали-сьме використали про уповісткы за ходы у совмістнуй бавці. Позволеня на доступ ид интернетови мусай дати, обы пак побрати си моды тай музыку, а ще для коректного ладованя мултіплеєрных бавок. Ушиткі другі міньбы не ініціювут ся ігров Unciv.
|
|
@ -1 +0,0 @@
|
|||||||
4X-стратеґія за створьованя цівілізацій
|
|
@ -5,7 +5,7 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.unciv.Constants
|
import com.unciv.Constants
|
||||||
import com.unciv.UncivGame
|
import com.unciv.UncivGame
|
||||||
import com.unciv.models.metadata.GameSettings
|
import com.unciv.models.metadata.GameSettings
|
||||||
import com.unciv.models.metadata.GameSettings.LocaleCode
|
import com.unciv.models.metadata.LocaleCode
|
||||||
import com.unciv.models.ruleset.Ruleset
|
import com.unciv.models.ruleset.Ruleset
|
||||||
import com.unciv.models.ruleset.RulesetCache
|
import com.unciv.models.ruleset.RulesetCache
|
||||||
import com.unciv.models.stats.Stats
|
import com.unciv.models.stats.Stats
|
||||||
|
Loading…
x
Reference in New Issue
Block a user