Problems making changes to the app with per-app language preferences

375 Views Asked by At

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)
)
0

There are 0 best solutions below