akexorcist / Localization

[Android] In-app language changing library
Apache License 2.0
983 stars 154 forks source link

Giving context access to abstract getDefaultLanguage method. #107

Closed iamriajul closed 3 years ago

iamriajul commented 3 years ago

So user of getDefaultLanguage can access Shared Preference and return Locale based on Persisted language.

Fixes: #106

akexorcist commented 3 years ago

Is there any reason why you don't access the context in Application class directly?

Because Application class is based on Context by itself.

class MainApplication : LocalizationApplication() {
    override fun getDefaultLanguage(): Locale {
        val context: Context = this
        // Get your default language from shared preferences
    }
}
iamriajul commented 3 years ago

Is there any reason why you don't access the context in Application class directly?

Because Application class is based on Context by itself.

Logically context should be accessible directly via the Application class but it seems it doesn't until attachBaseContext attach a context. Trying to access context before attachBaseContext will throw NullPointerException.

like this: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.SharedPreferences android.content.Context.getSharedPreferences(java.lang.String, int)' on a null object reference

iamriajul commented 3 years ago

FYI: My current working implementation with delegate:


    private val localizationDelegate = LocalizationApplicationDelegate()

    override fun attachBaseContext(base: Context) {
        // Koin DI has not been started
        // usage of DI here will throw: java.lang.IllegalStateException: KoinApplication has not been started
        val sharedPreferences: SharedPreferences = base.getSharedPreferences(AppSettings.PREF_NAME, Context.MODE_PRIVATE)

        var appLanguage: String? = sharedPreferences.getString(AppSettings.KEY_APP_LANGUAGE, null)

        if (appLanguage == null) {
            // If no language found on Pref, now detect automatically based on Country of the Device.
            appLanguage = CountryDetector.getLanguage(base)
        }

        localizationDelegate.setDefaultLanguage(base, appLanguage)
        super.attachBaseContext(localizationDelegate.attachBaseContext(base))
    }

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

    override fun getApplicationContext(): Context {
        return localizationDelegate.getApplicationContext(super.getApplicationContext())
    }

Using delegate requires boilerplate codes.

akexorcist commented 3 years ago

Basically, getDefaultLanguage() is only requires when first time launch without language setting stored in the library's shared preferences . So you don't need to get the language from your own shared preference for it.

Get device's language with Locale.getDefault() should be fine.

class MainApplication : LocalizationApplication() {
    override fun getDefaultLanguage(): Locale = Locale.getDefault()
}
iamriajul commented 3 years ago

Basically, getDefaultLanguage() is only requires when first time launch without language setting stored in the library's shared preferences.

But it seems getDefaultLanguage is called every time the app start?

And also my current situation doesn't use only Shared Preference for deciding Default Language, If you have seen my code above that look for saved language if not available then it detect language based on Country. Most people in Bangladesh set their device Language in English, but they prefer Bengali Language for content reading experience. So returning Locale.getDefault() won't be a good UX for our users.

if (appLanguage == null) {
    // If no language found on Pref, now detect automatically based on Country of the Device.
    appLanguage = CountryDetector.getLanguage(base)
}

So we need context for above logic.

akexorcist commented 3 years ago

OK. Let's merge!

akexorcist commented 3 years ago

This PR is live in version 1.2.10

Thank you for your contribution!