Files
aiturk-mobil/app/src/main/java/com/m57/hermescontrol/util/LocaleContextWrapper.kt
T
M57 5c1492a80e feat(chat): add animated GIF rendering with tap-to-play animation (#721) (#731)
* feat(chat): add animated GIF rendering with tap-to-play animation

Closes #721

* fix(#721): add missing GifImageThumbnail component and format ktlint

* fix(analytics): resolve ktlint indentation error in itemsIndexed

* feat(chat): add interactive play/pause toggle for animated GIFs

* fix(chat): control GIF playback via Animatable start and stop
2026-07-27 18:32:45 +03:00

82 lines
2.6 KiB
Kotlin

package com.m57.hermescontrol.util
import android.content.Context
import android.content.ContextWrapper
import android.os.Build
import java.util.Locale
/**
* Static helpers for applying a user-selected in-app display language.
*
* Hermes Mobile's [com.m57.hermescontrol.MainActivity] extends the plain
* `ComponentActivity` (not `AppCompatActivity`), so we apply the locale through
* `attachBaseContext` + [ContextWrapper.wrap] rather than relying on
* AppCompatDelegate. Works on minSdk 26.
*/
object LocaleContextWrapper {
const val SYSTEM_LANGUAGE = "system"
/**
* Resolve a language code ("system", "en", "ko", …) into a [Locale].
*
* "system" returns the device's default locale (so passing it through
* [wrap] is effectively a no-op). Codes containing a region separator
* ("zh-rCN", "pt-BR") are split into language + country.
*/
fun localeForCode(code: String): Locale =
when {
code.isEmpty() || code == SYSTEM_LANGUAGE -> {
Locale.getDefault()
}
code.contains("-r", ignoreCase = true) -> {
val parts = code.split("-r", ignoreCase = true)
Locale(parts[0], parts.getOrElse(1) { "" })
}
code.contains("-") -> {
val parts = code.split("-")
Locale(parts[0], parts.getOrElse(1) { "" })
}
code.contains("_") -> {
val parts = code.split("_")
Locale(parts[0], parts.getOrElse(1) { "" })
}
else -> {
Locale(code)
}
}
/**
* Wrap [base] so the configuration carries [locale].
*
* On API 33+ we use [Context.createConfigurationContext] which is the only
* reliable path once the deprecated `Configuration.locale` / `setLocale`
* APIs were removed from the public surface.
*/
fun wrap(
base: Context,
locale: Locale,
): Context {
val config = base.resources.configuration
val newConfig =
android.content.res.Configuration(config).apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
setLocales(android.os.LocaleList(locale))
} else {
@Suppress("DEPRECATION")
setLocale(locale)
}
}
return base.createConfigurationContext(newConfig)
}
/** Convenience: wrap [base] using a stored language code. */
fun wrapWithCode(
base: Context,
code: String,
): Context = wrap(base, localeForCode(code))
}