Yuito-app-android/app/src/main/java/com/keylesspalace/tusky/util/LocaleManager.kt

106 lines
4.0 KiB
Kotlin

/* Copyright 2019 Mélanie Chauvel (ariasuni)
*
* This file is a part of Tusky.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see <http://www.gnu.org/licenses>. */
package com.keylesspalace.tusky.util
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import androidx.preference.PreferenceDataStore
import androidx.preference.PreferenceManager
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.settings.PrefKeys
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class LocaleManager @Inject constructor(
val context: Context
) : PreferenceDataStore() {
private var prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
fun setLocale() {
val language = prefs.getNonNullString(PrefKeys.LANGUAGE, DEFAULT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (language != HANDLED_BY_SYSTEM) {
// app is being opened on Android 13+ for the first time
// hand over the old setting to the system and save a dummy value in Shared Preferences
applyLanguageToApp(language)
prefs.edit()
.putString(PrefKeys.LANGUAGE, HANDLED_BY_SYSTEM)
.apply()
}
} else {
// on Android < 13 we have to apply the language at every app start
applyLanguageToApp(language)
}
}
override fun putString(key: String?, value: String?) {
// if we are on Android < 13 we have to save the selected language so we can apply it at appstart
// on Android 13+ the system handles it for us
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
prefs.edit()
.putString(PrefKeys.LANGUAGE, value)
.apply()
}
applyLanguageToApp(value)
}
override fun getString(key: String?, defValue: String?): String? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val selectedLanguage = AppCompatDelegate.getApplicationLocales()
if (selectedLanguage.isEmpty) {
DEFAULT
} else {
// Android lets users select all variants of languages we support in the system settings,
// so we need to find the closest match
// it should not happen that we find no match, but returning null is fine (picker will show default)
val availableLanguages = context.resources.getStringArray(R.array.language_values)
return availableLanguages.find { it == selectedLanguage[0]!!.toLanguageTag() }
?: availableLanguages.find { language ->
language.startsWith(selectedLanguage[0]!!.language)
}
}
} else {
prefs.getNonNullString(PrefKeys.LANGUAGE, DEFAULT)
}
}
private fun applyLanguageToApp(language: String?) {
val localeList = if (language == DEFAULT) {
LocaleListCompat.getEmptyLocaleList()
} else {
LocaleListCompat.forLanguageTags(language)
}
AppCompatDelegate.setApplicationLocales(localeList)
}
companion object {
private const val DEFAULT = "default"
private const val HANDLED_BY_SYSTEM = "handled_by_system"
}
}