Browse Source

[resources] Select default resource if there are no exact language+region or default language match (#4577)

We need to filter by language and region together because there is
slightly different logic:
1) if there is the exact match language+region then use it
2) if there is the language WITHOUT region match then use it
3) in other cases use items WITHOUT language and region qualifiers at
all

Given resources:
values
values-en-rUS
values-de

Filter results:
"en" -> values
"en-US" -> values-en-rUS
"en-GB" -> values
"de-IT" -> values-de

fixes https://github.com/JetBrains/compose-multiplatform/issues/4571
pull/4585/head
Konstantin 4 weeks ago committed by GitHub
parent
commit
2bb6ec5e65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 34
      components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt
  2. 13
      components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ResourceTest.kt

34
components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt

@ -52,9 +52,7 @@ internal var getResourceEnvironment = ::getSystemEnvironment
internal fun Resource.getResourceItemByEnvironment(environment: ResourceEnvironment): ResourceItem {
//Priority of environments: https://developer.android.com/guide/topics/resources/providing-resources#table2
items.toList()
.filterBy(environment.language)
.also { if (it.size == 1) return it.first() }
.filterBy(environment.region)
.filterByLocale(environment.language, environment.region)
.also { if (it.size == 1) return it.first() }
.filterBy(environment.theme)
.also { if (it.size == 1) return it.first() }
@ -84,4 +82,34 @@ private fun List<ResourceItem>.filterBy(qualifier: Qualifier): List<ResourceItem
return filter { item ->
item.qualifiers.none { it::class == qualifier::class }
}
}
// we need to filter by language and region together because there is slightly different logic:
// 1) if there is the exact match language+region then use it
// 2) if there is the language WITHOUT region match then use it
// 3) in other cases use items WITHOUT language and region qualifiers at all
// issue: https://github.com/JetBrains/compose-multiplatform/issues/4571
private fun List<ResourceItem>.filterByLocale(language: LanguageQualifier, region: RegionQualifier): List<ResourceItem> {
val withLanguage = filter { item ->
item.qualifiers.any { it == language }
}
val withExactLocale = withLanguage.filter { item ->
item.qualifiers.any { it == region }
}
//if there are the exact language + the region items
if (withExactLocale.isNotEmpty()) return withExactLocale
val withDefaultRegion = withLanguage.filter { item ->
item.qualifiers.none { it is RegionQualifier }
}
//if there are the language without a region items
if (withDefaultRegion.isNotEmpty()) return withDefaultRegion
//items without any locale qualifiers
return filter { item ->
item.qualifiers.none { it is LanguageQualifier || it is RegionQualifier }
}
}

13
components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ResourceTest.kt

@ -30,6 +30,7 @@ class ResourceTest {
ResourceItem(setOf(), "default", -1, -1),
ResourceItem(setOf(LanguageQualifier("en")), "en", -1, -1),
ResourceItem(setOf(LanguageQualifier("en"), RegionQualifier("US"), XHDPI), "en-rUS-xhdpi", -1, -1),
ResourceItem(setOf(LanguageQualifier("de"), RegionQualifier("US")), "de-rUS", -1, -1),
ResourceItem(setOf(LanguageQualifier("fr"), LIGHT), "fr-light", -1, -1),
ResourceItem(setOf(DARK), "dark", -1, -1),
)
@ -48,6 +49,18 @@ class ResourceTest {
"en",
resource.getResourceItemByEnvironment(env("en", "IN", LIGHT, LDPI)).path
)
assertEquals(
"de-rUS",
resource.getResourceItemByEnvironment(env("de", "US", LIGHT, LDPI)).path
)
assertEquals(
"default",
resource.getResourceItemByEnvironment(env("de", "", LIGHT, LDPI)).path
)
assertEquals(
"default",
resource.getResourceItemByEnvironment(env("de", "IN", LIGHT, LDPI)).path
)
assertEquals(
"default",
resource.getResourceItemByEnvironment(env("ch", "", LIGHT, MDPI)).path

Loading…
Cancel
Save