Issue
How to implement in app localization with Jetpack Compose? I mean I don't want the user to change their device language, instead, let them change only the app language. How to achieve that? All of the resources I found talks about changing the device language.
Solution
This is what I did based on this answer here.
In your application class, do the following:
class MyApp : Application() {
override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleHelper.setLocale(base, myLang))
}
companion object {
var myLang = "en"
}
}
I'm saving the language in myLang
variable, but in practice you will save in Shared Preferences.
In onAttachBaseContext
the setLocale
is called (it's declared below).
Then, in your activity you will do the same:
class MainActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(
LocaleHelper.setLocale(newBase, MyApp.myLang)
)
}
}
The object below will set the language in MyApp.myLang
and update the Context
object.
object LocaleHelper {
fun setLocale(context: Context, language: String): Context? {
MyApp.myLang = language
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, language);
}
return updateResourcesLegacy(context, language);
}
@TargetApi(Build.VERSION_CODES.N)
private fun updateResources(context: Context, language: String): Context? {
val locale = Locale(language)
Locale.setDefault(locale)
val configuration = context.resources.configuration
configuration.setLocale(locale)
configuration.setLayoutDirection(locale)
return context.createConfigurationContext(configuration)
}
private fun updateResourcesLegacy(context: Context, language: String): Context {
val locale = Locale(language)
Locale.setDefault(locale)
val resources = context.resources
val configuration = resources.configuration
configuration.locale = locale
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
}
Finally, in your composable, you can do the following:
@Composable
fun TestLanguage() {
val context = LocalContext.current
Text(text = stringResource(id = R.string.activity_java_text))
Button(onClick = {
LocaleHelper.setLocale(context, "pt")
(context as? Activity)?.recreate()
}) {
Text(text = stringResource(id = R.string.btn_ok))
}
}
Notice the recreate
method is called to recreate the current activity and apply the language change.
Answered By - nglauber
Answer Checked By - Willingham (JavaFixing Volunteer)