diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt index b39ce64153..00f322fb09 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceEnvironment.kt +++ b/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.filterBy(qualifier: Qualifier): List 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.filterByLocale(language: LanguageQualifier, region: RegionQualifier): List { + 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 } + } } \ No newline at end of file diff --git a/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ResourceTest.kt b/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ResourceTest.kt index 8f1f8b36de..61bccc16c0 100644 --- a/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ResourceTest.kt +++ b/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