Created
July 18, 2024 10:52
-
-
Save ElianFabian/4e5edb10d7b36935a2f2695227ad8e60 to your computer and use it in GitHub Desktop.
ContextWrapper to propperly update the locale of your application. The default implementation takes the first supported locale, otherwise takes the default locale.. Gist to generate the supported and default locale: Gist to generate the supported locales: https://gist.github.com/ElianFabian/e94071f348998c24bedaa959ddb8df40
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.annotation.SuppressLint | |
import android.app.Application | |
import android.content.ComponentCallbacks | |
import android.content.Context | |
import android.content.ContextWrapper | |
import android.content.res.Configuration | |
import android.content.res.Resources | |
import android.os.Build | |
import android.os.LocaleList | |
import androidx.core.os.ConfigurationCompat | |
import androidx.core.os.LocaleListCompat | |
import java.util.Locale | |
fun Application.createLocaleContextWrapper(baseContext: Context): ContextWrapper { | |
return LocaleContextWrapper( | |
application = this, | |
baseContext = baseContext, | |
createUpdatedLocaleContext = { oldContext, newConfig -> | |
createContextWithFirstSupportedUserLocaleOrForceDefault( | |
context = oldContext, | |
configuration = newConfig, | |
defaultLanguage = AppBuildConfig.DefaultLanguage, | |
supportedLanguages = AppBuildConfig.SupportedLanguages, | |
) | |
}, | |
) | |
} | |
class LocaleContextWrapper( | |
application: Application, | |
baseContext: Context, | |
private val createUpdatedLocaleContext: (oldContext: Context, newConfig: Configuration) -> Context, | |
) : ContextWrapper( | |
createUpdatedLocaleContext(baseContext, baseContext.resources.configuration) | |
) { | |
init { | |
application.registerComponentCallbacks(object : ComponentCallbacks { | |
override fun onConfigurationChanged(newConfig: Configuration) { | |
_baseContext = createUpdatedLocaleContext(_baseContext, newConfig) | |
} | |
override fun onLowMemory() = Unit | |
}) | |
} | |
private var _baseContext = super.getBaseContext() | |
override fun getResources(): Resources = _baseContext.resources | |
override fun getTheme(): Resources.Theme = _baseContext.theme | |
override fun getBaseContext(): Context = _baseContext | |
override fun setTheme(resid: Int) { | |
_baseContext.setTheme(resid) | |
} | |
} | |
@Suppress("DEPRECATION") | |
@SuppressLint("ObsoleteSdkInt") | |
private fun createContextWithFirstSupportedUserLocaleOrForceDefault( | |
context: Context, | |
configuration: Configuration, | |
defaultLanguage: String, | |
supportedLanguages: List<String>, | |
): Context { | |
val userSupportedLocales = ConfigurationCompat | |
.getLocales(configuration) | |
.getMatches(supportedLanguages) | |
val newLocales = userSupportedLocales.ifEmpty { | |
listOf(Locale(defaultLanguage)) | |
} | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
val newLocaleList = LocaleList(*newLocales.toTypedArray()) | |
LocaleList.setDefault(newLocaleList) | |
configuration.setLocales(newLocaleList) | |
} | |
else { | |
val newLocale = newLocales.first() | |
Locale.setDefault(newLocale) | |
configuration.locale = newLocale | |
} | |
return context.createConfigurationContext(configuration) | |
} | |
private fun LocaleListCompat.getMatches(supportedLocales: List<String>): List<Locale> { | |
val currentSupportedLocales = supportedLocales.toMutableList() | |
return buildList { | |
while (currentSupportedLocales.isNotEmpty()) { | |
val match = getFirstMatch(currentSupportedLocales.toTypedArray()) ?: continue | |
add(match) | |
currentSupportedLocales.removeAll { supportedLocale -> | |
match.toString().startsWith(supportedLocale) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.app.Application | |
import android.content.Context | |
class YourApplication : Application() { | |
override fun attachBaseContext(base: Context?) { | |
if (base == null) { | |
return super.attachBaseContext(null) | |
} | |
val localeContext = createLocaleContextWrapper(base) | |
super.attachBaseContext(localeContext) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment