I have a code for changing the language of an APP. When I'm using this code, the language does change but not fully. Some parts of the page I'm in is still having the old language. For e.g., if I'm using English, Portugese and Spanish and when I change from English to Spanish, some parts are of the page are not changing. I have only two activities and rest of the them are fragments. And below is the code I'm using for the app to switch languages.
But when I go out of the page and come back again, the whole page is translated.
fun updateLocale(context: Context, language: String) {
val locale = when (language) {
"Portuguese" -> Locale("pt")
"Spanish" -> Locale("es")
else -> Locale("en")
}
Locale.setDefault(locale)
val config = Configuration()
config.setLocale(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.createConfigurationContext(config)
} else {
@Suppress("DEPRECATION")
context.resources.updateConfiguration(config, context.resources.displayMetrics)
}
}
How do make this function workable? Is there any additional code that has to be added for this to work?
This is how I'm using the code in my activity
Utils.updateLocale(this, App.instance.language)
I tried detaching and attaching the fragment. Recreated activities and still did not work.
When you change the language at runtime, some parts of your UI may continue to show old strings because they were composed (or “inflated”) with the previous configuration. In Jetpack Compose (or even in traditional fragments), the UI won’t automatically update if only the locale is changed in the resources. Instead, you have to “force” a recomposition (or even a full recreation) of your composables so that they pick up the new language from resources.
If you're using compose for your UI, you can save the state that tracks the current language and use a key to force a recomposition when it changes, as so:
@Composable
fun MainScreen(currentLanguage: String) {
key(currentLanguage) {
Column(modifier = Modifier.fillMaxSize()) {
Text(text = stringResource(id = R.string.hello))
}
}
}
Another Compose-friendly approach is to provide the current configuration (or locale) via a CompositionLocal.
// saving the state in your fragment/activity
private var currentLocale by mutableStateOf(Locale.getDefault())
// setting the composition local provider
setContent {
CompositionLocalProvider(LocalAppLocale provides currentLocale) {
MainScreen()
}
}
val LocalAppLocale = compositionLocalOf { Locale.getDefault() }
@Composable
fun MainScreen() {
// if the configuration changes, the UI will recompose.
val locale = LocalAppLocale.current
Column {
Text(text = stringResource(id = R.string.hello))
}
}
Another approach — more common with traditional Android Views is to recreate the activity when the language changes.