Android Jetpack Compose Localisation issue

Viewed 1090

Trying to slowly integrate Compose into our app. The app is released in a few countries, so we support some extra languages other than English.

During our first steps with Compose, we are trying to migrate a "Change Password" screen. Here is a small code snippet:

@Composable
fun ChangePasswordScreen() {
    Scaffold(
        topBar = {
            CustomTopBarWithBackArrow(title = stringResource(id = R.string.a_change_password))
        },
        modifier = Modifier
            .background(Color.White)
            .fillMaxSize(),
        content = {
            ChangePasswordScreenContent()
        }
    )
}

@Composable
fun ChangePasswordScreenContent() {
    Column(
        modifier = Modifier
            .padding(16.dp)
            .background(colorResource(id = R.color.white))
            .fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        PasswordInput(
            title = stringResource(id = R.string.d_current_password),
            placeholder = stringResource(id = R.string.e_password_length)
        )
    }
}

@Composable
fun PasswordInput(title: String, placeholder: String) {
    TextFieldTitle(title = title)
    PasswordTextField(placeholder = placeholder)
}

I am using the stringResource method. The user is able to change the selected country and based on that country, we update the Locale. For some reason, the stringResource method is not updated with the latest Locale, unless we restart the app.

The LocalConfiguration.current.locales[0].country is returning always the correct country code. But the resources are not updated.

Has anybody found a possible solution to this? Or maybe, am I missing something?

2 Answers

Changing the language/region programmatically does not recompose your UI. You either have to update the state of the various screens/composable or restart your app. Updating your screens/composables can be a pain. You are better off restarting the activity:

startActivity(Intent.makeRestartActivityTask(this.intent?.component))

A better solution is to use Jetmagic. It's a framework designed to handle device configuration changes without the need to restart the app. A demo app shows how the locale is updated:

https://github.com/JohannBlake/Jetmagic

Building upon Johann's answer, you can try to manually trigger a recomposition.

Try this,

setContent{
var trigger by mutableStateOf(false)
}

Then, at the place you are changing the Locale, just trigger = !trigger. Now, since the setContent method is reading it, the entire screen will recompose.

Anyway, if your Locale Changer is located somewhere outside setContent in a non-Compose scope, you can just declare this variable on top of the activity, then just type it just like that in the setContent

setContent{
 trigger
 ...
}

This is just to give Compose a message that this trigger is being read by setContent and it should recompose upon its value change. Since we do not really care what the value of trigger is, you can write it without using remember at all.

Seems clean to me,

Related