https://kotlinlang.org logo
#compose
Title
# compose
r

Rene Win

03/08/2023, 1:28 PM
I have a question regarding Previews in Jetpack Compose: if i use the locale parameter within the Preview annotation like this:
Copy code
@Preview(locale = "en")
then i assume that some code (in this example
Locale.getDefault()
) would also return this locale. but it doesnt matter what i put in their, the Locale.getDefault() always returns the (i assume) system language full preview code for completeness:
Copy code
@Preview(locale = "en")
@Composable
fun Test() {
    Text("${Locale.getDefault()}")
}
The reason behind this is that we use the previews for screenshot testing and we have a datetimeformatter which depends on the current locale.. (which is calling Locale.getDefault() in the background)
s

Stylianos Gakis

03/08/2023, 1:30 PM
I think the locale is passed inside the LocalConfiguration from this annotation and not to wherever java.util.Locale.getDefault() is looking at to fetch the locale. Try adding a function like this
Copy code
@Composable
@ReadOnlyComposable
fun getLocale(): Locale {
    val configuration = LocalConfiguration.current
    return ConfigurationCompat.getLocales(configuration).get(0) ?: LocaleListCompat.getAdjustedDefault()[0]!!
}
And see if this returns the right locale, I’m also curious
r

Rene Win

03/08/2023, 1:39 PM
yes, this function does indeed return the locale from the locale preview parameter. but where the Locale.getdefault is currently used i have no compose context - so therefore i cant call this function. but it should be the same with the context right? so
context.resources.configuration
should be the same as
LocalConfiguration.current
e

ephemient

03/08/2023, 1:41 PM
it should be the case that
Copy code
LocalView.current.context == LocalContext.current
LocalContext.current.resources.configuration == LocalConfiguration.current
s

Stylianos Gakis

03/08/2023, 1:41 PM
Yeah I think those two should return the same thing. It's just that for compose you also get for free that if the configuration changes, you will get the updated value. If you're not in a composable context, you need to make sure you get the refreshed configuration. Normally though, if you're not overriding this in your manifest the activity will be recreated and you will be forced to get the latest configuration that way.
e

ephemient

03/08/2023, 1:43 PM
☝️ on configuration change,
LocalView.current
and
LocalContext.current
won't change, but
LocalConfiguration.current
will
s

Stylianos Gakis

03/08/2023, 1:45 PM
Does this then mean that if you rely on
LocalContext.current.resources.configuration
you're going to be getting stale information about the configuration? Or did I misunderstand you?
e

ephemient

03/08/2023, 1:45 PM
yes, it means that
LocalContext.current....
may be outdated because it doesn't that part of the context has mutated
y

yschimke

03/08/2023, 7:09 PM
There is a test harness module in Accompanist that can override with a fake Context. Maybe try that.
e

ephemient

03/08/2023, 7:10 PM
that doesn't change the global JVM Locale either
basically it's a bad fit for testability and you should avoid APIs that use the default locale
(it's also a bad fit for Compose because
Locale.setDefault()
isn't observable)
y

yschimke

03/08/2023, 7:13 PM
With the test harness module you could have a single preview, with a parameter provider with 20+ locales, and all the forms should match.
s

Stylianos Gakis

03/08/2023, 7:14 PM
Thinking about all this, I remember another discussion revolving around the same exact thing tbh. I think a lint against using Locale.getDefault should be a great idea.
185 Views