最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - Recompose an fragmentactivity in jetpack after changing the language - Stack Overflow

programmeradmin0浏览0评论

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.

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.

Share Improve this question asked Feb 3 at 8:55 Abhijith WarrierAbhijith Warrier 157 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

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.

  1. 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))
          }
       }
    }
    
  2. 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))
        }
    }
    
  3. Another approach — more common with traditional Android Views is to recreate the activity when the language changes.

You can check out official Android guide: https://developer.android/guide/topics/resources/app-languages#androidx-impl. It works in my case.

val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY")
// Call this on the main thread as it may require Activity.restart()
AppCompatDelegate.setApplicationLocales(appLocale)

Also, to get your app prefered language that the user choosen, use AppCompatDelegate.getApplicationLocales().

If your android version is below 13, declare a compatible service in your Manifest

<application
  ...
  <service
    android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
    android:enabled="false"
    android:exported="false">
    <meta-data
      android:name="autoStoreLocales"
      android:value="true" />
  </service>
  ...
</application>
发布评论

评论列表(0)

  1. 暂无评论