Skip to content

Instantly share code, notes, and snippets.

@NaingAungLuu
Created June 8, 2022 08:03
Show Gist options
  • Save NaingAungLuu/275a77a83fac4bffb0a19c72d0c14d9f to your computer and use it in GitHub Desktop.
Save NaingAungLuu/275a77a83fac4bffb0a19c72d0c14d9f to your computer and use it in GitHub Desktop.
Auto Translation
/**
* Created by Naing Aung Luu on 27/05/2022
*/
fun <T : Any> T.translateToAppLanguage(appLanguage: Language): T {
if (this::class.isData) {
this::class.declaredMemberProperties
.filter(KProperty1<out Any, *>::isATranslationProperty)
.map { it as KProperty1<Any, Translation<*>> }
.forEach {
it.get(this).translateToAppLanguage(appLanguage)
}
}
return this
}
fun KProperty1<*, *>.isATranslationProperty(): Boolean {
val typeArguments = this.returnType.arguments
return if (typeArguments.isNotEmpty()) {
this.returnType == Translation::class.createType(arguments = typeArguments)
} else {
false
}
}
// Example Usage in ViewModel
class MainViewModel(): ViewModel() {
fun merchandiseListFlow(): Flow<List<Merchandise>> {
repository.getMerchandiseList()
.onEach { list ->
list.forEach { item ->
// Auto Translate to app's language
item.translateToAppLanguage(currentLanguage)
}
}
}
}
// Example Usage in DataModel
data class Merchandise(
val name: Translation<String> = Translation(""),
val sellerName: Translation<String> = Translation(""),
val categories: Translation<List<Category>> = Translation(emptyList()),
val price: Int = Translation(0)
)
class Translation<T> : Serializable {
var default: T
private set
var english: T
private set
var chinese: T
private set
get() = field ?: default
var indonesian: T
private set
get() = field ?: default
constructor(
default: T
) {
this.default = default
english = default
chinese = default
indonesian = default
}
constructor(
english: T,
chinese: T? = null,
indonesian: T? = null
) : this(english) {
setTranslation(
english = english,
chinese = chinese,
indonesian = indonesian
)
}
fun setTranslation(
english: T? = null,
chinese: T? = null,
indonesian: T? = null
): Translation<T> {
english?.let { this.english = english }
chinese?.let { this.chinese = chinese }
indonesian?.let { this.indonesian = indonesian }
return this
}
fun getValue(appLanguage: Language = Language.ENG) =
when (appLanguage) {
Language.ENG -> english
Language.CN -> chinese
Language.IDN -> indonesian
}
fun translateToAppLanguage(appLanguage: Language = Language.ENG) {
default = when (appLanguage) {
Language.ENG -> english
Language.CN -> chinese
Language.IDN -> indonesian
}
}
/*
* Syntactic Sugar to get default translation,
* e.g: data.name() instead of data.name.default
*/
operator fun invoke(): T = default
}
fun Translation<String>.isNotEmpty() = (default.isNotBlank())
.or(english.isNotBlank())
.or(chinese.isNotBlank())
.or(indonesian.isNotBlank())
@Composable
fun ComposableView() {
val itemList = viewModel.merchandiseListFlow().collectAsState()
LazyColumn {
items(itemList) { item ->
MerchandiseItem(item)
}
}
}
@Composable
fun MerchandiseItem(data: Merchandise) {
Row {
Text(item.name())
Text(item.sellerName())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment