Search code examples
androidkotlinandroid-architecture-navigation

How to change language runtime for fragment


I'm using navigation component for Single Activity architecture. I'm trying to change language of my app in runtime, I'm using this article to do so.

So I've the following files:

RuntimeLocaleChanger

object RuntimeLocaleChanger {

    fun wrapContext(context: Context): Context {

        val savedLocale = Locale(PreferencesHelper.readLanguageCode()) // load the user language from SharedPreferences

        // as part of creating a new context that contains the new locale we also need to override the default locale.
        Locale.setDefault(savedLocale)

        // create new configuration with the saved locale
        val newConfig = Configuration()
        newConfig.setLocale(savedLocale)

        return context.createConfigurationContext(newConfig)
    }

    fun overrideLocale(context: Context) {

        val savedLocale = Locale(PreferencesHelper.readLanguageCode()) // load the user language from SharedPreferences

        // as part of creating a new context that contains the new locale we also need to override the default locale.
        Locale.setDefault(savedLocale)

        // create new configuration with the saved locale
        val newConfig = Configuration()
        newConfig.setLocale(savedLocale)

        // override the locale on the given context (Activity, Fragment, etc...)
        context.createConfigurationContext(newConfig)

        // override the locale on the application context
        if (context != context.applicationContext) {
            context.applicationContext.run { createConfigurationContext(newConfig) }
        }
    }
}

Application

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(RuntimeLocaleChanger.wrapContext(base))
}

MainActivity

override fun attachBaseContext(base: Context) {
    super.attachBaseContext(RuntimeLocaleChanger.wrapContext(base))
}

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    RuntimeLocaleChanger.overrideLocale(this)
}

I change the language like this:

// PreferencesHelper.readLanguageCode() is the language code saved in SharedPreferences
if(PreferencesHelper.readLanguageCode() == "en") {
    PreferencesHelper.writeLanguageCode("he")
} else {
    PreferencesHelper.writeLanguageCode("en")
}

I feel like there is something missing but I can't get my head to it


Solution

  • I've found a solution:

    MainActivity:

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        // Will give the direction of the layout depending of the Locale you've just set
        window.decorView.layoutDirection = Locale.getDefault().layoutDirection
    }
    

    Fragment

    // PreferencesHelper.readLanguageCode() is the language code saved in SharedPreferences
    if(PreferencesHelper.readLanguageCode() == "en") {
        PreferencesHelper.writeLanguageCode("he")
    } else {
        PreferencesHelper.writeLanguageCode("en")
    }
    (activity as? MainActivity)?.recreate()
    

    I've also found a nice library locale-helper