I am currently implementing a code that I had in another application and that was working correctly, to make a language selector. The problem I have found is that when I follow the same steps, in my other app it works, but in the new one, it doesn't finish changing the language.
When accessing the list of available languages, you press one of them, and the app freezes, it doesn't go back and you can't select another option either. If you exit and re-enter the app, you will see that the language has changed, but if you try to change the language again, it freezes again.
Through the logcat I see the following messages:
- Storing App Locales : app-locales: en persisted successfully.
- Schedule relaunch activity: com.jeluchu.test.MainActivity
So I understand that the change has been done correctly but the screen is not refreshing. Here's the code I used to implement this feature, in case someone knows what the error might be
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
...
android:localeConfig="@xml/locales_config"
...
tools:targetApi="tiramisu">
...
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
</application>
</manifest>
locales_config
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="en"/>
<locale android:name="es"/>
</locale-config>
LanguageSettings.kt
private fun getLanguageNumberByCode(languageCode: String): Int =
languageMap.entries.find { it.value == languageCode }?.key ?: 0
fun getLanguageNumber(): Int {
return if (Build.VERSION.SDK_INT >= 33)
getLanguageNumberByCode(
LocaleListCompat.getAdjustedDefault()[0]?.toLanguageTag().toString()
)
else getLanguage
}
@Composable
fun getLanguageDesc(language: Int = getLanguageNumber()): String = stringResource(
when (language) {
ENGLISH -> R.string.la_en_US
SPANISH -> R.string.la_es
else -> R.string.follow_system
}
)
private const val ENGLISH = 1
private const val SPANISH = 2
val languageMap: Map<Int, String> = mapOf(
ENGLISH to "en",
SPANISH to "es"
)
LanguageView.kt (In Compose)
val language = rememberMutableStateOf(getLanguageNumber())
Scaffold {
LazyColumn {
item {
PreferenceSingleChoiceItem(
modifier = Modifier.background(milky),
text = R.string.follow_system.toStringRes(),
selected = language.value == 0,
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 18.dp)
) { onLanguageClick(language, 0) }
}
languageMap.forEach { languageData ->
item {
PreferenceSingleChoiceItem(
modifier = Modifier.background(milky),
text = getLanguageDesc(languageData.key),
selected = language.value == languageData.key,
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 18.dp)
) { onLanguageClick(language, languageData.key) }
}
}
}
}
onLanguageClick function is:
languageMap.getOrElse(PreferencesService.getLanguage) { "" }.setLanguage()
selected.value = id
.setLanguage() is:
fun String.setLanguage() = AppCompatDelegate.setApplicationLocales(
if (isEmpty()) LocaleListCompat.getEmptyLocaleList()
else LocaleListCompat.forLanguageTags(this)
)