5

I am attempting to change my app language locally using the following code. If English and French are present in the Add a language of my phone's Settings, and then go into my app and change the language, the language change is successful, but if I remove the language from the Add a language in the phone's settings, the changes doesn't work. From the examples I am seeing online, it should be possible to change it without having any additional languages in the Add a language of the phone's Settings. I'm not sure what I am doing wrong, is there a way to enable language changes without having to add the language in the phone settings?

Any links to some documentation would also be quite appreciated.

This is the LocalUtil object I am creating to enable the language switching:

object LocalUtil {

    fun applyLanguageContext(context: Context, locale: Locale?): Context {

        if (locale == null) return context
        if (locale == getLocale(context.resources.configuration)) return context
        return try {
            setupLocale(locale)
            val resources = context.resources
            val configuration = getOverridingConfig(locale, resources)
            updateResources(context, resources, configuration)
            context.createConfigurationContext(configuration)
        } catch (e: Exception) {
            e.printStackTrace()
            context
        }
    }

    private fun updateResources(
        context: Context,
        resources: Resources,
        config: Configuration
    ) {
        if (context.applicationContext !== context) {
            resources.updateConfiguration(config, resources.displayMetrics)
        }
    }

    private fun setupLocale(locale: Locale) {
        Locale.setDefault(locale)
        LocaleList.setDefault(LocaleList(locale))
    }

    private fun getOverridingConfig(locale: Locale, resources: Resources): Configuration {
        val configuration = resources.configuration
        configuration.setLocales(LocaleList(locale))
        return configuration
    }

    private fun getLocale(configuration: Configuration): Locale {
        return configuration.locales.get(0)
    }
}

This is the Application() class which includes the LANGUAGE companion object variable

class MyApp: Application() {

    override fun getApplicationContext(): Context {
        val context = super.getApplicationContext()
        return LocalUtil.applyLanguageContext(context, Locale(LANGUAGE))
    }

    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(LocalUtil.applyLanguageContext(newBase, Locale(LANGUAGE)))
    }

    companion object {
        var LANGUAGE = "en"
    }
}

This is the MainActivity.kt, with a button that toggles between English "en" and French "fr" via the changeLangBtn: Button

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun setChangeLangBtn(view: View) {
        val changeLangBtn: Button = findViewById(R.id.change_lang_btn)
        changeLangBtn.setOnClickListener {
            if (MyApp.LANGUAGE == "en") MyApp.LANGUAGE = "fr" else MyApp.LANGUAGE = "en"
            reloadActivity()
        }
    }

    fun reloadActivity() {
         val intent = Intent(this, javaClass).apply {
             addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
             addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
         }

         startActivity(intent)
         recreate()
    }

    override fun getBaseContext(): Context {
        return LocalUtil.applyLanguageContext(super.getBaseContext(), Locale(MyApp.LANGUAGE))
    }

    override fun getApplicationContext(): Context {
        val context = super.getApplicationContext()
        return LocalUtil.applyLanguageContext(context, Locale(MyApp.LANGUAGE))
    }

    override fun attachBaseContext(newBase: Context) {
        super.attachBaseContext(LocalUtil.applyLanguageContext(newBase, Locale(MyApp.LANGUAGE)))
    }
}
PhilBlais
  • 1,076
  • 4
  • 13
  • 36
  • 1
    In your ``LocalUtil::updateResources`` is it necessary to check ``context.applicationContext !== context``? Here's how I change language in myapp: `` fun updateConfiguration(context: Context, language: String): Configuration { val locale = Locale(language) Locale.setDefault(locale) val config = context.resources.configuration config.setLocale(locale) context.resources.updateConfiguration(config, context.resources.displayMetrics) return config } `` – dardan.g Sep 26 '22 at 08:55
  • Thanks @d.gjinovci but that didn't resolve it – PhilBlais Sep 27 '22 at 12:00

2 Answers2

5

From this documentation: https://developer.android.com/guide/playcore/feature-delivery/on-demand#lang_resources

If you are using App bundles, the app will run ONLY with the necessary resources, so language resources other than the default wont be downloaded unless they are present in the user's phone settings. To enable additional languages while using app bundles, you should implement the Play Feature Delivery Library. follow the steps in the documentation to achieve this!

0

disabling the language split

  android {
        bundle {
            language {
                // Specifies that the app bundle should not support
                // configuration APKs for language resources. These
                // resources are instead packaged with each base and
                // dynamic feature APK.
                enableSplit = false
            }
        }
    }

You can disable the split from gradle.

Saiful Sazib
  • 451
  • 1
  • 3
  • 14