diff --git a/CHANGELOG.md b/CHANGELOG.md index baa2df0bd08..20d0cd746e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.20.32 +* `Resources`: + * Make `StringResource` serializable + * Add several variants of builder usages + ## 0.20.31 * `Versions`: diff --git a/resources/src/commonMain/kotlin/StringResource.kt b/resources/src/commonMain/kotlin/StringResource.kt index d87526fc691..397afa6af27 100644 --- a/resources/src/commonMain/kotlin/StringResource.kt +++ b/resources/src/commonMain/kotlin/StringResource.kt @@ -1,6 +1,11 @@ package dev.inmo.micro_utils.strings import dev.inmo.micro_utils.language_codes.IetfLang +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder /** * Use this class as a type of your strings object fields. For example: @@ -15,9 +20,10 @@ import dev.inmo.micro_utils.language_codes.IetfLang * * @see buildStringResource */ -class StringResource( +@Serializable(StringResource.Companion::class) +data class StringResource( val default: String, - val map: Map> + val translations: Map> ) { class Builder( var default: String @@ -31,11 +37,18 @@ class StringResource( infix fun IetfLang.variant(value: () -> String) = this variant lazy(value) infix fun IetfLang.variant(value: String) = this variant lazyOf(value) + operator fun IetfLang.invoke(value: () -> String) = this variant value + operator fun IetfLang.invoke(value: String) = this variant value + infix fun String.variant(value: Lazy) = IetfLang(this) variant value infix fun String.variant(value: () -> String) = IetfLang(this) variant lazy(value) infix fun String.variant(value: String) = this variant lazyOf(value) + + operator fun String.invoke(value: () -> String) = this variant value + operator fun String.invoke(value: String) = this variant value + fun build() = StringResource(default, map.toMap()) } @@ -43,17 +56,48 @@ class StringResource( if (languageCode == null) { return default } - map[languageCode] ?.let { return it.value } + translations[languageCode] ?.let { return it.value } return languageCode.parentLang ?.let { - map[it] ?.value + translations[it] ?.value } ?: default } + + companion object : KSerializer { + @Serializable + private class Surrogate( + val default: String, + val translations: Map + ) + + override val descriptor: SerialDescriptor + get() = Surrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): StringResource { + val surrogate = Surrogate.serializer().deserialize(decoder) + return StringResource( + surrogate.default, + surrogate.translations.map { IetfLang(it.key) to lazyOf(it.value) }.toMap() + ) + } + + override fun serialize(encoder: Encoder, value: StringResource) { + Surrogate.serializer().serialize( + encoder, + Surrogate( + value.default, + value.translations.map { + it.key.code to it.value.value + }.toMap() + ) + ) + } + } } inline fun buildStringResource( default: String, - builder: StringResource.Builder.() -> Unit + builder: StringResource.Builder.() -> Unit = {} ): StringResource { return StringResource.Builder(default).apply(builder).build() }