mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-12-23 09:07:14 +00:00
commit
eeaceb6cf5
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,5 +1,16 @@
|
||||
# Changelog
|
||||
|
||||
## 0.20.23
|
||||
|
||||
* `Versions`:
|
||||
* `Koin`: `3.5.0` -> `3.5.3`
|
||||
* `Okio`: `3.6.0` -> `3.7.0`
|
||||
* `LanguageCodes`:
|
||||
* Fixes in intermediate language codes (like `Chinese.Hans`)
|
||||
* Rename `IetfLanguageCode` to `IetfLang`
|
||||
* Rename all subsequent functions (including serializer)
|
||||
* New lazy properties `knownLanguageCodesMap`, `knownLanguageCodesMapByLowerCasedKeys` and several others
|
||||
|
||||
## 0.20.22
|
||||
|
||||
* `Common`:
|
||||
|
@ -15,5 +15,5 @@ crypto_js_version=4.1.1
|
||||
# Project data
|
||||
|
||||
group=dev.inmo
|
||||
version=0.20.22
|
||||
android_code_version=228
|
||||
version=0.20.23
|
||||
android_code_version=229
|
||||
|
@ -17,9 +17,9 @@ ktor = "2.3.7"
|
||||
|
||||
gh-release = "2.4.1"
|
||||
|
||||
koin = "3.5.0"
|
||||
koin = "3.5.3"
|
||||
|
||||
okio = "3.6.0"
|
||||
okio = "3.7.0"
|
||||
|
||||
ksp = "1.9.21-1.0.16"
|
||||
kotlin-poet = "1.15.3"
|
||||
|
@ -12,9 +12,12 @@ private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
private const val baseClassName = "IetfLanguageCode"
|
||||
private const val baseClassName = "IetfLang"
|
||||
private const val oldBaseClassName = "IetfLanguageCode"
|
||||
private const val unknownBaseClassName = "Unknown$baseClassName"
|
||||
private const val baseClassSerializerName = "IetfLanguageCodeSerializer"
|
||||
private const val oldUnknownBaseClassName = "Unknown$oldBaseClassName"
|
||||
private const val baseClassSerializerName = "${baseClassName}Serializer"
|
||||
private const val oldBaseClassSerializerName = "IetfLanguageCodeSerializer"
|
||||
private const val baseClassSerializerAnnotationName = "@Serializable(${baseClassSerializerName}::class)"
|
||||
|
||||
@Serializable
|
||||
@ -78,14 +81,12 @@ private fun printLanguageCodeAndTags(
|
||||
indents: String = " "
|
||||
): String = if (tag.subtags.isEmpty()) {
|
||||
"""${indents}${baseClassSerializerAnnotationName}
|
||||
${indents}object ${tag.title} : ${parent ?.title ?: baseClassName}() { override val code: String = "${tag.tag}"; override val withoutDialect: String get() = ${parent ?.title ?.let { "$it.code" } ?: "code"} }"""
|
||||
${indents}object ${tag.title} : ${parent ?.title ?: baseClassName}() { override val code: String = "${tag.tag}"${parent ?.let { parent -> "; override val parentLang: ${parent.title} get() = ${parent.title};" } ?: ""} }"""
|
||||
} else {
|
||||
"""
|
||||
${indents}${baseClassSerializerAnnotationName}
|
||||
${indents}sealed class ${tag.title} : ${parent ?.title ?: baseClassName}() {
|
||||
${indents} override val code: String = "${tag.tag}"
|
||||
${indents} override val withoutDialect: String
|
||||
${indents} get() = code
|
||||
${indents} override val code: String = "${tag.tag}"${parent ?.let { parent -> "\n${indents} override val parentLang: ${parent.title} get() = ${parent.title};" } ?: ""}
|
||||
|
||||
${tag.subtags.joinToString("\n") { printLanguageCodeAndTags(it, tag, "${indents} ") }}
|
||||
|
||||
@ -95,7 +96,7 @@ ${indents}}
|
||||
"""
|
||||
}
|
||||
|
||||
fun buildKtFileContent(tags: List<Tag>): String = """
|
||||
fun buildKtFileContent(tags: List<Tag>, prePackage: String): String = """
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
@ -106,20 +107,27 @@ import kotlinx.serialization.Serializable
|
||||
${baseClassSerializerAnnotationName}
|
||||
sealed class $baseClassName {
|
||||
abstract val code: String
|
||||
abstract val withoutDialect: String
|
||||
open val parentLang: $baseClassName?
|
||||
get() = null
|
||||
open val withoutDialect: String
|
||||
get() = parentLang ?.code ?: code
|
||||
|
||||
${tags.joinToString("\n") { printLanguageCodeAndTags(it, indents = " ") } }
|
||||
|
||||
$baseClassSerializerAnnotationName
|
||||
data class $unknownBaseClassName (override val code: String) : $baseClassName() {
|
||||
override val withoutDialect: String = code.takeWhile { it != '-' }
|
||||
override val parentLang = code.dropLastWhile { it != '-' }.removeSuffix("-").takeIf { it.length > 0 } ?.let(::$unknownBaseClassName)
|
||||
}
|
||||
@Deprecated("Renamed", ReplaceWith("$baseClassName.$unknownBaseClassName", "${if (prePackage.isNotEmpty()) "$prePackage." else ""}$baseClassName.$unknownBaseClassName"))
|
||||
val $oldUnknownBaseClassName = $unknownBaseClassName
|
||||
|
||||
override fun toString() = code
|
||||
}
|
||||
@Deprecated("Renamed", ReplaceWith("$baseClassName", "${if (prePackage.isNotEmpty()) "$prePackage." else ""}$baseClassName"))
|
||||
typealias $oldBaseClassName = $baseClassName
|
||||
""".trimIndent()
|
||||
|
||||
fun createStringConverterCode(tags: List<Tag>): String {
|
||||
fun createStringConverterCode(tags: List<Tag>, prePackage: String): String {
|
||||
fun createDeserializeVariantForTag(
|
||||
tag: Tag,
|
||||
pretitle: String = baseClassName,
|
||||
@ -128,19 +136,70 @@ fun createStringConverterCode(tags: List<Tag>): String {
|
||||
val currentTitle = "$pretitle.${tag.title}"
|
||||
return """${indents}$currentTitle.code -> $currentTitle${if (tag.subtags.isNotEmpty()) tag.subtags.joinToString("\n", "\n") { createDeserializeVariantForTag(it, currentTitle, indents) } else ""}"""
|
||||
}
|
||||
|
||||
return """fun String.as$baseClassName(): $baseClassName {
|
||||
return when (this) {
|
||||
${tags.joinToString("\n") { createDeserializeVariantForTag(it) }}
|
||||
else -> $baseClassName.${unknownBaseClassName}(this)
|
||||
fun createInheritorVariantForTag(
|
||||
tag: Tag,
|
||||
pretitle: String = baseClassName,
|
||||
indents: String = " "
|
||||
): String {
|
||||
val currentTitle = "$pretitle.${tag.title}"
|
||||
val subtags = if (tag.subtags.isNotEmpty()) {
|
||||
tag.subtags.joinToString(",\n", ",\n") { createInheritorVariantForTag(it, currentTitle, "$indents ") }
|
||||
} else {
|
||||
""
|
||||
}
|
||||
return "${indents}$currentTitle$subtags"
|
||||
}
|
||||
fun createInheritorVariantForMapForTag(
|
||||
tag: Tag,
|
||||
pretitle: String = baseClassName,
|
||||
indents: String = " ",
|
||||
codeSuffix: String = ""
|
||||
): String {
|
||||
val currentTitle = "$pretitle.${tag.title}"
|
||||
val subtags = if (tag.subtags.isNotEmpty()) {
|
||||
tag.subtags.joinToString(",\n", ",\n") { createInheritorVariantForMapForTag(it, currentTitle, "$indents ", codeSuffix) }
|
||||
} else {
|
||||
""
|
||||
}
|
||||
return "${indents}$currentTitle.code${codeSuffix} to $currentTitle$subtags"
|
||||
}
|
||||
|
||||
return """val knownLanguageCodesMap: Map<String, $baseClassName> by lazy {
|
||||
mapOf(
|
||||
${tags.joinToString(",\n") { createInheritorVariantForMapForTag(it, indents = " ") }}
|
||||
)
|
||||
}
|
||||
val knownLanguageCodesMapByLowerCasedKeys: Map<String, $baseClassName> by lazy {
|
||||
mapOf(
|
||||
${tags.joinToString(",\n") { createInheritorVariantForMapForTag(it, indents = " ", codeSuffix = ".lowercase()") }}
|
||||
)
|
||||
}
|
||||
val knownLanguageCodes: List<$baseClassName> by lazy {
|
||||
knownLanguageCodesMap.values.toList()
|
||||
}
|
||||
|
||||
fun String.as$baseClassName(): $baseClassName {
|
||||
return knownLanguageCodesMap[this] ?: $baseClassName.${unknownBaseClassName}(this)
|
||||
}
|
||||
fun String.as${baseClassName}CaseInsensitive(): $baseClassName {
|
||||
return knownLanguageCodesMapByLowerCasedKeys[this.lowercase()] ?: $baseClassName.${unknownBaseClassName}(this)
|
||||
}
|
||||
@Deprecated("Renamed", ReplaceWith("this.as$baseClassName()", "${if (prePackage.isNotEmpty()) "$prePackage." else ""}as$baseClassName"))
|
||||
fun String.as$oldBaseClassName(): $baseClassName = as$baseClassName()
|
||||
|
||||
fun convertTo$baseClassName(code: String) = code.as$baseClassName()
|
||||
fun convertTo${baseClassName}CaseInsensitive(code: String) = code.as${baseClassName}CaseInsensitive()
|
||||
@Deprecated("Renamed", ReplaceWith("convertTo$baseClassName(code)", "${if (prePackage.isNotEmpty()) "$prePackage." else ""}convertTo$baseClassName"))
|
||||
fun convertTo$oldBaseClassName(code: String) = convertTo$baseClassName(code)
|
||||
|
||||
fun $baseClassName(code: String) = code.as$baseClassName()
|
||||
fun ${baseClassName}CaseInsensitive(code: String) = code.as${baseClassName}CaseInsensitive()
|
||||
@Deprecated("Renamed", ReplaceWith("$baseClassName(code)", "${if (prePackage.isNotEmpty()) "$prePackage." else ""}$baseClassName"))
|
||||
fun $oldBaseClassName(code: String) = $baseClassName(code)
|
||||
"""
|
||||
}
|
||||
|
||||
fun createSerializerCode(tags: List<Tag>): String {
|
||||
fun createSerializerCode(tags: List<Tag>, prePackage: String): String {
|
||||
return """import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
@ -153,16 +212,20 @@ object $baseClassSerializerName : KSerializer<$baseClassName> {
|
||||
return $baseClassName(decoder.decodeString())
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: IetfLanguageCode) {
|
||||
override fun serialize(encoder: Encoder, value: $baseClassName) {
|
||||
encoder.encodeString(value.code)
|
||||
}
|
||||
}
|
||||
@Deprecated("Renamed", ReplaceWith("$baseClassSerializerName", "${if (prePackage.isNotEmpty()) "$prePackage." else ""}$baseClassSerializerName"))
|
||||
typealias $oldBaseClassSerializerName = $baseClassSerializerName
|
||||
"""
|
||||
}
|
||||
|
||||
suspend fun main(vararg args: String) {
|
||||
val outputFolder = args.firstOrNull() ?.let { File(it) }
|
||||
outputFolder ?.mkdirs()
|
||||
val targetPackage = args.getOrNull(1)
|
||||
val targetPackagePrefix = targetPackage ?.let { "package $it\n\n" } ?: ""
|
||||
val ietfLanguageCodesLink = "https://datahub.io/core/language-codes/r/language-codes.json"
|
||||
val ietfLanguageCodesAdditionalTagsLink = "https://datahub.io/core/language-codes/r/ietf-language-tags.json"
|
||||
|
||||
@ -203,18 +266,18 @@ suspend fun main(vararg args: String) {
|
||||
File(outputFolder, "LanguageCodes.kt").apply {
|
||||
delete()
|
||||
createNewFile()
|
||||
writeText(buildKtFileContent(tags))
|
||||
writeText(targetPackagePrefix + buildKtFileContent(tags, targetPackage ?: ""))
|
||||
}
|
||||
|
||||
File(outputFolder, "StringToLanguageCodes.kt").apply {
|
||||
delete()
|
||||
createNewFile()
|
||||
writeText(createStringConverterCode(tags))
|
||||
writeText(targetPackagePrefix + createStringConverterCode(tags, targetPackage ?: ""))
|
||||
}
|
||||
|
||||
File(outputFolder, "$baseClassSerializerName.kt").apply {
|
||||
delete()
|
||||
createNewFile()
|
||||
writeText(createSerializerCode(tags))
|
||||
writeText(targetPackagePrefix + createSerializerCode(tags, targetPackage ?: ""))
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package dev.inmo.micro_utils.language_codes
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
object IetfLangSerializer : KSerializer<IetfLang> {
|
||||
override val descriptor = String.serializer().descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): IetfLang {
|
||||
return IetfLang(decoder.decodeString())
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: IetfLang) {
|
||||
encoder.encodeString(value.code)
|
||||
}
|
||||
}
|
||||
@Deprecated("Renamed", ReplaceWith("IetfLangSerializer", "dev.inmo.micro_utils.language_codes.IetfLangSerializer"))
|
||||
typealias IetfLanguageCodeSerializer = IetfLangSerializer
|
@ -1,18 +0,0 @@
|
||||
package dev.inmo.micro_utils.language_codes
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
object IetfLanguageCodeSerializer : KSerializer<IetfLanguageCode> {
|
||||
override val descriptor = String.serializer().descriptor
|
||||
|
||||
override fun deserialize(decoder: Decoder): IetfLanguageCode {
|
||||
return IetfLanguageCode(decoder.decodeString())
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: IetfLanguageCode) {
|
||||
encoder.encodeString(value.code)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@
|
||||
package dev.inmo.micro_utils.language_codes
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class UnknownIetfLanguageTests {
|
||||
@Test
|
||||
fun commonTestOfParentCode() {
|
||||
knownLanguageCodes.forEach {
|
||||
val language = IetfLang.UnknownIetfLang(it.code)
|
||||
assertEquals(it.code, language.code)
|
||||
assertEquals(it.withoutDialect, language.withoutDialect)
|
||||
assertEquals(it.parentLang ?.code, language.parentLang ?.code)
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,9 @@ package dev.inmo.micro_utils.language_codes
|
||||
|
||||
import java.util.Locale
|
||||
|
||||
fun IetfLanguageCode.toJavaLocale(): Locale = Locale.forLanguageTag(code)
|
||||
fun IetfLanguageCode?.toJavaLocaleOrDefault(): Locale = this ?.toJavaLocale() ?: Locale.getDefault()
|
||||
fun IetfLang.toJavaLocale(): Locale = Locale.forLanguageTag(code)
|
||||
fun IetfLang?.toJavaLocaleOrDefault(): Locale = this?.toJavaLocale() ?: Locale.getDefault()
|
||||
|
||||
fun Locale.toIetfLanguageCode(): IetfLanguageCode = IetfLanguageCode(toLanguageTag())
|
||||
fun Locale.toIetfLang(): IetfLang = IetfLang(toLanguageTag())
|
||||
@Deprecated("Renamed", ReplaceWith("this.toIetfLang()", "dev.inmo.micro_utils.language_codes.toIetfLang"))
|
||||
fun Locale.toIetfLanguageCode(): IetfLang = toIetfLang()
|
||||
|
@ -4,7 +4,6 @@ import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import dev.inmo.micro_utils.language_codes.toIetfLanguageCode
|
||||
|
||||
fun StringResource.translation(configuration: Configuration): String = translation(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
|
@ -1,27 +1,51 @@
|
||||
package dev.inmo.micro_utils.strings
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
|
||||
import dev.inmo.micro_utils.language_codes.IetfLang
|
||||
|
||||
/**
|
||||
* Use this class as a type of your strings object fields. For example:
|
||||
*
|
||||
* ```kotlin
|
||||
* object Strings {
|
||||
* val someResource: StringResource
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Use [buildStringResource] for useful creation of string resource
|
||||
*
|
||||
* @see buildStringResource
|
||||
*/
|
||||
class StringResource(
|
||||
val default: String,
|
||||
val map: Map<IetfLanguageCode, Lazy<String>>
|
||||
val map: Map<IetfLang, Lazy<String>>
|
||||
) {
|
||||
class Builder(
|
||||
var default: String
|
||||
) {
|
||||
private val map = mutableMapOf<IetfLanguageCode, Lazy<String>>()
|
||||
private val map = mutableMapOf<IetfLang, Lazy<String>>()
|
||||
|
||||
infix fun IetfLanguageCode.variant(value: Lazy<String>) {
|
||||
infix fun IetfLang.variant(value: Lazy<String>) {
|
||||
map[this] = value
|
||||
}
|
||||
infix fun IetfLanguageCode.variant(value: String) = this variant lazyOf(value)
|
||||
infix fun String.variant(value: Lazy<String>) = IetfLanguageCode(this) variant value
|
||||
|
||||
infix fun IetfLang.variant(value: () -> String) = this variant lazy(value)
|
||||
infix fun IetfLang.variant(value: String) = this variant lazyOf(value)
|
||||
|
||||
|
||||
infix fun String.variant(value: Lazy<String>) = 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)
|
||||
|
||||
fun build() = StringResource(default, map.toMap())
|
||||
}
|
||||
|
||||
fun translation(languageCode: IetfLanguageCode): String = (map[languageCode] ?: map[IetfLanguageCode(languageCode.withoutDialect)]) ?.value ?: default
|
||||
fun translation(languageCode: IetfLang): String {
|
||||
map[languageCode] ?.let { return it.value }
|
||||
|
||||
return languageCode.parentLang ?.let {
|
||||
map[it] ?.value
|
||||
} ?: default
|
||||
}
|
||||
}
|
||||
|
||||
inline fun buildStringResource(
|
||||
|
@ -1,10 +1,10 @@
|
||||
package dev.inmo.micro_utils.strings
|
||||
|
||||
import dev.inmo.micro_utils.language_codes.toIetfLanguageCode
|
||||
import dev.inmo.micro_utils.language_codes.toIetfLang
|
||||
import java.util.Locale
|
||||
|
||||
fun StringResource.translation(locale: Locale = Locale.getDefault()): String {
|
||||
return translation(locale.toIetfLanguageCode())
|
||||
return translation(locale.toIetfLang())
|
||||
}
|
||||
|
||||
fun Locale.translation(resource: StringResource): String = resource.translation(this)
|
Loading…
Reference in New Issue
Block a user