mirror of
https://github.com/amir1376/ab-download-manager.git
synced 2025-02-20 11:43:24 +08:00
set system language as default language (#386)
This commit is contained in:
parent
ddec1f383f
commit
30e70f8b1c
@ -318,26 +318,36 @@ fun themeConfig(
|
|||||||
fun languageConfig(
|
fun languageConfig(
|
||||||
languageManager: LanguageManager,
|
languageManager: LanguageManager,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
): EnumConfigurable<LanguageInfo> {
|
): EnumConfigurable<LanguageInfo?> {
|
||||||
val currentLanguageName = languageManager.selectedLanguage
|
val currentLanguageName = languageManager.selectedLanguageInStorage
|
||||||
val allLanguages = languageManager.languageList
|
val allLanguages = languageManager.languageList.value
|
||||||
return EnumConfigurable(
|
return EnumConfigurable(
|
||||||
title = Res.string.settings_language.asStringSource(),
|
title = Res.string.settings_language.asStringSource(),
|
||||||
description = "".asStringSource(),
|
description = "".asStringSource(),
|
||||||
backedBy = createMutableStateFlowFromStateFlow(
|
backedBy = createMutableStateFlowFromStateFlow(
|
||||||
flow = currentLanguageName.mapStateFlow { l ->
|
flow = currentLanguageName.mapStateFlow { language ->
|
||||||
allLanguages.value.find {
|
language?.let {
|
||||||
it.toLocaleString() == l
|
allLanguages.find {
|
||||||
} ?: LanguageManager.DefaultLanguageInfo
|
it.toLocaleString() == language
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updater = { languageInfo ->
|
updater = { languageInfo ->
|
||||||
languageManager.selectLanguage(languageInfo)
|
languageManager.selectLanguage(languageInfo)
|
||||||
},
|
},
|
||||||
scope = scope,
|
scope = scope,
|
||||||
),
|
),
|
||||||
possibleValues = allLanguages.value,
|
possibleValues = listOf(null).plus(allLanguages),
|
||||||
describe = {
|
describe = {
|
||||||
it.nativeName.asStringSource()
|
val isAuto = it == null
|
||||||
|
val language = it ?: languageManager.systemLanguageOrDefault
|
||||||
|
val languageName = language.nativeName
|
||||||
|
if (isAuto) {
|
||||||
|
// always use english here!
|
||||||
|
"System ($languageName)".asStringSource()
|
||||||
|
} else {
|
||||||
|
languageName.asStringSource()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import java.io.File
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class AppSettingsModel(
|
data class AppSettingsModel(
|
||||||
val theme: String = "dark",
|
val theme: String = "dark",
|
||||||
val language: String = "en",
|
val language: String? = null,
|
||||||
val uiScale: Float? = null,
|
val uiScale: Float? = null,
|
||||||
val mergeTopBarWithTitleBar: Boolean = false,
|
val mergeTopBarWithTitleBar: Boolean = false,
|
||||||
val threadCount: Int = 8,
|
val threadCount: Int = 8,
|
||||||
@ -95,7 +95,7 @@ data class AppSettingsModel(
|
|||||||
override fun set(source: MapConfig, focus: AppSettingsModel): MapConfig {
|
override fun set(source: MapConfig, focus: AppSettingsModel): MapConfig {
|
||||||
return source.apply {
|
return source.apply {
|
||||||
put(Keys.theme, focus.theme)
|
put(Keys.theme, focus.theme)
|
||||||
put(Keys.language, focus.language)
|
putNullable(Keys.language, focus.language)
|
||||||
putNullable(Keys.uiScale, focus.uiScale)
|
putNullable(Keys.uiScale, focus.uiScale)
|
||||||
put(Keys.mergeTopBarWithTitleBar, focus.mergeTopBarWithTitleBar)
|
put(Keys.mergeTopBarWithTitleBar, focus.mergeTopBarWithTitleBar)
|
||||||
put(Keys.threadCount, focus.threadCount)
|
put(Keys.threadCount, focus.threadCount)
|
||||||
@ -127,6 +127,15 @@ private val uiScaleLens: Lens<AppSettingsModel, Float?>
|
|||||||
s.copy(uiScale = f)
|
s.copy(uiScale = f)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
private val languageLens: Lens<AppSettingsModel, String?>
|
||||||
|
get() = Lens(
|
||||||
|
get = {
|
||||||
|
it.language
|
||||||
|
},
|
||||||
|
set = { s, f ->
|
||||||
|
s.copy(language = f)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
class AppSettingsStorage(
|
class AppSettingsStorage(
|
||||||
settings: DataStore<MapConfig>,
|
settings: DataStore<MapConfig>,
|
||||||
@ -134,7 +143,7 @@ class AppSettingsStorage(
|
|||||||
ConfigBaseSettingsByMapConfig<AppSettingsModel>(settings, AppSettingsModel.ConfigLens),
|
ConfigBaseSettingsByMapConfig<AppSettingsModel>(settings, AppSettingsModel.ConfigLens),
|
||||||
LanguageStorage {
|
LanguageStorage {
|
||||||
var theme = from(AppSettingsModel.theme)
|
var theme = from(AppSettingsModel.theme)
|
||||||
override val selectedLanguage = from(AppSettingsModel.language)
|
override val selectedLanguage = from(languageLens)
|
||||||
var uiScale = from(uiScaleLens)
|
var uiScale = from(uiScaleLens)
|
||||||
var mergeTopBarWithTitleBar = from(AppSettingsModel.mergeTopBarWithTitleBar)
|
var mergeTopBarWithTitleBar = from(AppSettingsModel.mergeTopBarWithTitleBar)
|
||||||
val threadCount = from(AppSettingsModel.threadCount)
|
val threadCount = from(AppSettingsModel.threadCount)
|
||||||
@ -152,4 +161,4 @@ class AppSettingsStorage(
|
|||||||
val browserIntegrationPort = from(AppSettingsModel.browserIntegrationPort)
|
val browserIntegrationPort = from(AppSettingsModel.browserIntegrationPort)
|
||||||
val trackDeletedFilesOnDisk = from(AppSettingsModel.trackDeletedFilesOnDisk)
|
val trackDeletedFilesOnDisk = from(AppSettingsModel.trackDeletedFilesOnDisk)
|
||||||
val useBitsForSpeed = from(AppSettingsModel.useBitsForSpeed)
|
val useBitsForSpeed = from(AppSettingsModel.useBitsForSpeed)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
|
|||||||
import ir.amirab.util.compose.contants.FILE_PROTOCOL
|
import ir.amirab.util.compose.contants.FILE_PROTOCOL
|
||||||
import ir.amirab.util.compose.contants.RESOURCE_PROTOCOL
|
import ir.amirab.util.compose.contants.RESOURCE_PROTOCOL
|
||||||
import ir.amirab.util.flow.mapStateFlow
|
import ir.amirab.util.flow.mapStateFlow
|
||||||
|
import ir.amirab.util.flow.mapTwoWayStateFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import okio.FileSystem
|
import okio.FileSystem
|
||||||
@ -11,14 +12,24 @@ import okio.Path.Companion.toPath
|
|||||||
import okio.buffer
|
import okio.buffer
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.util.Properties
|
import java.util.*
|
||||||
|
|
||||||
class LanguageManager(
|
class LanguageManager(
|
||||||
private val storage: LanguageStorage,
|
private val storage: LanguageStorage,
|
||||||
) {
|
) {
|
||||||
private val _languageList: MutableStateFlow<List<LanguageInfo>> = MutableStateFlow(emptyList())
|
private val _languageList: MutableStateFlow<List<LanguageInfo>> = MutableStateFlow(emptyList())
|
||||||
val languageList = _languageList.asStateFlow()
|
val languageList = _languageList.asStateFlow()
|
||||||
val selectedLanguage = storage.selectedLanguage
|
val systemLanguageOrDefault: LanguageInfo by lazy {
|
||||||
|
getSystemLanguageIfWeCanUse()
|
||||||
|
}
|
||||||
|
val selectedLanguageInStorage = storage.selectedLanguage
|
||||||
|
val selectedLanguage = storage.selectedLanguage.mapStateFlow {
|
||||||
|
it ?: systemLanguageOrDefault.toLocaleString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// val selectedLanguageInfo = selectedLanguage.mapStateFlow {
|
||||||
|
// bestLanguageInfo(it)
|
||||||
|
// }
|
||||||
val isRtl = selectedLanguage.mapStateFlow { selectedLanguage ->
|
val isRtl = selectedLanguage.mapStateFlow { selectedLanguage ->
|
||||||
rtlLanguages.any { selectedLanguage.startsWith(it) }
|
rtlLanguages.any { selectedLanguage.startsWith(it) }
|
||||||
}
|
}
|
||||||
@ -28,11 +39,11 @@ class LanguageManager(
|
|||||||
instance = this
|
instance = this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectLanguage(languageInfo: LanguageInfo) {
|
fun selectLanguage(languageInfo: LanguageInfo?) {
|
||||||
// ensure that language info is in the list!
|
// ensure that language info is in the list!
|
||||||
// val languageInfo = languageList.value.find { it == languageInfo }
|
// val languageInfo = languageList.value.find { it == languageInfo }
|
||||||
// selectedLanguage.value = (languageInfo ?: DefaultLanguageInfo).toLocaleString()
|
// selectedLanguage.value = (languageInfo ?: DefaultLanguageInfo).toLocaleString()
|
||||||
selectedLanguage.value = languageInfo.toLocaleString()
|
selectedLanguageInStorage.value = languageInfo?.toLocaleString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMessage(key: String): String {
|
fun getMessage(key: String): String {
|
||||||
@ -42,7 +53,7 @@ class LanguageManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getRequestedLanguage(): String {
|
private fun getRequestedLanguage(): String {
|
||||||
return selectedLanguage.value
|
return selectedLanguage.value ?: systemLanguageOrDefault.toLocaleString()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
@ -74,6 +85,10 @@ class LanguageManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the best language info for the given locale.
|
||||||
|
* the returned language is guaranteed to be available. (at least [DefaultLanguageInfo])
|
||||||
|
*/
|
||||||
private fun bestLanguageInfo(locale: String): LanguageInfo {
|
private fun bestLanguageInfo(locale: String): LanguageInfo {
|
||||||
return languageList.value.find {
|
return languageList.value.find {
|
||||||
it.toLocaleString() == locale
|
it.toLocaleString() == locale
|
||||||
@ -122,6 +137,11 @@ class LanguageManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSystemLanguageIfWeCanUse(): LanguageInfo {
|
||||||
|
val systemLocale = getSystemLocale().toString()
|
||||||
|
return bestLanguageInfo(systemLocale)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var instance: LanguageManager
|
lateinit var instance: LanguageManager
|
||||||
private const val LOCALES_PATH = "/com/abdownloadmanager/resources/locales"
|
private const val LOCALES_PATH = "/com/abdownloadmanager/resources/locales"
|
||||||
@ -130,10 +150,8 @@ class LanguageManager(
|
|||||||
languageCode = "en",
|
languageCode = "en",
|
||||||
countryCode = "US",
|
countryCode = "US",
|
||||||
)
|
)
|
||||||
LanguageInfo(
|
locale.toLanguageInfo(
|
||||||
locale = locale,
|
path = "$RESOURCE_PROTOCOL:$LOCALES_PATH/${locale}.properties",
|
||||||
nativeName = "English",
|
|
||||||
path = URI("$RESOURCE_PROTOCOL:$LOCALES_PATH/${locale}.properties")
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,3 +222,11 @@ data class LanguageInfo(
|
|||||||
return locale.toString()
|
return locale.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSystemLocale(): MyLocale {
|
||||||
|
val javaSystemLocale = Locale.getDefault(Locale.Category.DISPLAY)
|
||||||
|
return MyLocale(
|
||||||
|
languageCode = javaSystemLocale.language,
|
||||||
|
countryCode = javaSystemLocale.country,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -3,5 +3,6 @@ package ir.amirab.util.compose.localizationmanager
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
interface LanguageStorage {
|
interface LanguageStorage {
|
||||||
val selectedLanguage: MutableStateFlow<String>
|
// null means auto
|
||||||
}
|
val selectedLanguage: MutableStateFlow<String?>
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user