You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

73 lines
2.9 KiB

/*
* Copyright 2020-2024 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/
package org.jetbrains.compose.resources.plural
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.jetbrains.compose.resources.InternalResourceApi
import org.jetbrains.compose.resources.LanguageQualifier
import org.jetbrains.compose.resources.RegionQualifier
internal class PluralRuleList(private val rules: Array<PluralRule>) {
fun getCategory(quantity: Int): PluralCategory {
return rules.first { rule -> rule.appliesTo(quantity) }.category
}
companion object {
private val cacheMutex = Mutex()
private val cache = Array<Deferred<PluralRuleList>?>(cldrPluralRuleLists.size) { null }
private val emptyList = PluralRuleList(emptyArray())
@OptIn(InternalResourceApi::class)
suspend fun getInstance(
languageQualifier: LanguageQualifier,
regionQualifier: RegionQualifier,
): PluralRuleList {
val cldrLocaleName = buildCldrLocaleName(languageQualifier, regionQualifier) ?: return emptyList
return getInstance(cldrLocaleName)
}
suspend fun getInstance(cldrLocaleName: String): PluralRuleList {
val listIndex = cldrPluralRuleListIndexByLocale[cldrLocaleName]!!
return coroutineScope {
val deferred = cacheMutex.withLock {
if (cache[listIndex] == null) {
cache[listIndex] = async(start = CoroutineStart.LAZY) {
createInstance(listIndex)
}
}
cache[listIndex]!!
}
deferred.await()
}
}
@OptIn(InternalResourceApi::class)
private fun buildCldrLocaleName(
languageQualifier: LanguageQualifier,
regionQualifier: RegionQualifier,
): String? {
val localeWithRegion = languageQualifier.language + "_" + regionQualifier.region
if (cldrPluralRuleListIndexByLocale.containsKey(localeWithRegion)) {
return localeWithRegion
}
if (cldrPluralRuleListIndexByLocale.containsKey(languageQualifier.language)) {
return languageQualifier.language
}
return null
}
private fun createInstance(cldrPluralRuleListIndex: Int): PluralRuleList {
val cldrPluralRuleList = cldrPluralRuleLists[cldrPluralRuleListIndex]
val pluralRules = cldrPluralRuleList.map { PluralRule(it.first, it.second) }
return PluralRuleList(pluralRules.toTypedArray())
}
}
}