Search code examples
android-jetpack-composeandroid-jetpack-compose-text

stringResource() not loading strings of current locale


Update

In the application class, I am injecting the ChangeLanguageRepository which sets the app language at each app startup by calling the function changeLanguage.

class ChangeLanguageRepository @Inject constructor(@ApplicationContext private val context: Context) {

    fun changeLanguage(languageLocale: String) {
        val locale = Locale(languageLocale)
        Locale.setDefault(locale)
        val config = Configuration()
        config.locale = locale
        context.resources.updateConfiguration(config, context.resources.displayMetrics)
    }
}

I have developed an app using Jetpack Compose in which there is an option to change the language of the app. Now, when the language is changed, all the string resources that are loaded using stringResource() are not updating for the current locale even when the activity or app is restarted.

One of the screens inside the app is loading strings using the Context provided by Dagger Hilt in the Repository as shown below.

class HelplineRepository @Inject constructor(@ApplicationContext private val context: Context) {

    fun getHelplines(): List<Helpline> {
        val ambulance = Helpline(
            Icons.Rounded.Emergency,
            context.getString(R.string.helpline_text_ambulance),
            context.getString(R.string.helpline_text_ambulance_number)
        )

        val fireStation = Helpline(
            Icons.Rounded.LocalFireDepartment,
            context.getString(R.string.helpline_text_fire_station),
            context.getString(R.string.helpline_text_fire_station_number)
        )

        return listOf(ambulance, fireStation, policeControlRoom, womenHelpLine)
    }
}

This screen properly shows the localized strings when the language is changed but the rest of the screens where I use the stringResource() inside a composable to load the strings don't update for the current locale.

Note: I have already tried restarting both the activity and the app and have also made sure that the locale is being changed when the user changes the language.

I also found a thread on the issue tracker mentioning a similar problem but couldn't find the solution.

Any help will be appreciated.


Solution

  • Updated answer

    Composable code

    @Composable
    fun LocalizedGreeting() {
        val context = LocalContext.current
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .fillMaxSize(),
        ) {
            Column {
                Button(
                    onClick = {
                        changeLanguage(
                            context = context,
                            language = "it",
                        )
                    },
                ) {
                    Text("Italian")
                }
                Button(
                    onClick = {
                        changeLanguage(
                            context = context,
                            language = "en",
                        )
                    },
                ) {
                    Text("English")
                }
                Text(
                    stringResource(
                        id = R.string.localized_greeting,
                    )
                )
            }
        }
    }
    
    fun changeLanguage(
        context: Context,
        language: String,
    ) {
        val locale = Locale(language)
        Locale.setDefault(locale)
        val config = Configuration()
        config.locale = locale
        context.resources.updateConfiguration(config, context.resources.displayMetrics)
        context.startActivity(Intent.makeRestartActivityTask((context as Activity).intent?.component))
    }
    

    Video

    The resources remain the same as the old answer given below.

    Note

    After the language is changed, the activity has to be restarted to get the updated strings. If there are multiple activities in the back stack, all of them have to be restarted.


    Old Answer

    (For using the localized strings without changing the locale programmatically)

    To use localized string resources,

    Composable code

    @Composable
    fun LocalizedGreeting() {
        Box(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .fillMaxSize(),
        ) {
            Text(
                stringResource(
                    id = R.string.localized_greeting,
                )
            )
        }
    }
    

    Default strings
    res/values/strings.xml

    <resources>
        <string name="localized_greeting">Hello!</string>
    </resources>
    

    Italian strings
    res/values-it/strings.xml

    <resources>
        <string name="localized_greeting">Ciao!</string>
    </resources>
    

    jetpackComposeVersion = "1.2.0-beta02"


    Using localized strings was straightforward.
    Probably you were missing something.
    Provide the code you are using for further debugging if required.