Skip to content

Commit

Permalink
added description translation
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Apr 16, 2024
1 parent 8d7ca78 commit 10cf182
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 6 deletions.
2 changes: 2 additions & 0 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ kotlin {
implementation(libs.coroutines.android)

implementation(libs.android.credentials.play.services)

implementation(libs.translate)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package dev.datlag.aniflow.ui.navigation.screen.medium.component

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Translate
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import com.google.mlkit.common.model.DownloadConditions
import com.google.mlkit.nl.translate.TranslateLanguage
import com.google.mlkit.nl.translate.Translation
import com.google.mlkit.nl.translate.TranslatorOptions
import dev.datlag.aniflow.SharedRes
import dev.icerock.moko.resources.compose.stringResource
import io.github.aakira.napier.Napier
import java.util.Locale

@Composable
actual fun TranslateButton(text: String, onTranslation: (String?) -> Unit) {
val locale = remember { Locale.getDefault() }
if (locale.language.equals(Locale.forLanguageTag("en").language, ignoreCase = true)) {
Napier.e("Language is english")
return
}
if (locale.toLanguageTag().equals("en", ignoreCase = true)) {
Napier.e("LanguageTag is english")
return
}
if (locale.isO3Language.equals("ENG", ignoreCase = true)) {
Napier.e("Language ISO is english")
return
}

val targetLanguage = remember(locale) {
TranslateLanguage.fromLanguageTag(locale.toLanguageTag())
?: TranslateLanguage.fromLanguageTag(locale.language)
?: TranslateLanguage.fromLanguageTag(locale.isO3Language)
}

if (targetLanguage == null || targetLanguage == TranslateLanguage.ENGLISH) {
Napier.e("TargetLanguage is: $targetLanguage, ${locale.toLanguageTag()}")
return
}

val options = remember(targetLanguage) {
TranslatorOptions.Builder()
.setSourceLanguage(TranslateLanguage.ENGLISH)
.setTargetLanguage(targetLanguage)
.build()
}
val englishLocaleTranslator = remember(options) { Translation.getClient(options) }
val downloadConditions = remember {
DownloadConditions.Builder()
.requireWifi()
.build()
}
var enabled by remember { mutableStateOf(true) }
var translated by remember { mutableStateOf(false) }

TextButton(
onClick = {
if (translated) {
translated = false
onTranslation(null)
} else {
englishLocaleTranslator
.downloadModelIfNeeded(downloadConditions)
.addOnFailureListener {
enabled = false
}.addOnSuccessListener {
enabled = true

englishLocaleTranslator
.translate(text)
.addOnFailureListener {
translated = false
onTranslation(null)
}.addOnSuccessListener {
translated = true
onTranslation(it)
}
}
}
},
enabled = enabled
) {
Icon(
modifier = Modifier.size(ButtonDefaults.IconSize),
imageVector = Icons.Default.Translate,
contentDescription = null
)
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
Text(stringResource(SharedRes.strings.translate))
}

DisposableEffect(englishLocaleTranslator) {
onDispose {
englishLocaleTranslator.close()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface MediumComponent : ContentHolderComponent {
val coverImage: StateFlow<Medium.CoverImage>
val title: StateFlow<Medium.Title>
val description: StateFlow<String?>
val translatedDescription: StateFlow<String?>
val genres: StateFlow<Set<String>>

val format: StateFlow<MediaFormat>
Expand All @@ -36,4 +37,5 @@ interface MediumComponent : ContentHolderComponent {
}
fun rate(onLoggedIn: () -> Unit)
fun rate(value: Int)
fun descriptionTranslation(text: String?)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import dev.datlag.aniflow.other.StateSaver
import dev.datlag.aniflow.ui.custom.EditFAB
import dev.datlag.aniflow.ui.navigation.screen.initial.home.component.GenreChip
import dev.datlag.aniflow.ui.navigation.screen.medium.component.CharacterCard
import dev.datlag.aniflow.ui.navigation.screen.medium.component.TranslateButton
import dev.datlag.tooling.compose.onClick
import dev.datlag.tooling.decompose.lifecycle.collectAsStateWithLifecycle
import dev.icerock.moko.resources.compose.painterResource
Expand Down Expand Up @@ -405,13 +406,23 @@ fun MediumScreen(component: MediumComponent) {
}
if (!description.isNullOrBlank()) {
item {
Text(
modifier = Modifier.padding(top = 16.dp).padding(horizontal = 16.dp),
text = "Description",
style = MaterialTheme.typography.headlineSmall
)
Row(
modifier = Modifier.fillParentMaxWidth().padding(top = 16.dp).padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
modifier = Modifier.weight(1F),
text = stringResource(SharedRes.strings.description),
style = MaterialTheme.typography.headlineSmall
)
TranslateButton(description!!) { text ->
component.descriptionTranslation(text)
}
}
}
item {
val translatedDescription by component.translatedDescription.collectAsStateWithLifecycle()
val animatedLines by animateIntAsState(
targetValue = if (descriptionExpanded) {
Int.MAX_VALUE
Expand All @@ -425,7 +436,7 @@ fun MediumScreen(component: MediumComponent) {
modifier = Modifier.padding(horizontal = 16.dp).onClick {
descriptionExpanded = !descriptionExpanded
},
text = description!!.htmlToAnnotatedString(),
text = (translatedDescription ?: description)!!.htmlToAnnotatedString(),
maxLines = max(animatedLines, 1),
softWrap = true,
overflow = TextOverflow.Ellipsis,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class MediumScreenComponent(
initialValue = null
)

override val translatedDescription: MutableStateFlow<String?> = MutableStateFlow(null)

override val genres: StateFlow<Set<String>> = mediumSuccessState.mapNotNull {
it?.data?.genres?.ifEmpty { null }
}.flowOn(
Expand Down Expand Up @@ -365,4 +367,10 @@ class MediumScreenComponent(
}
}
}

override fun descriptionTranslation(text: String?) {
launchIO {
translatedDescription.emit(text)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package dev.datlag.aniflow.ui.navigation.screen.medium.component

import androidx.compose.runtime.Composable

@Composable
expect fun TranslateButton(text: String, onTranslation: (String?) -> Unit)
2 changes: 2 additions & 0 deletions composeApp/src/commonMain/moko-resources/base/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@
<string name="rated">Rated</string>
<string name="popular">Popular</string>
<string name="score">Score</string>
<string name="translate">Translate</string>
<string name="description">Description</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.datlag.aniflow.ui.navigation.screen.medium.component

import androidx.compose.runtime.Composable

@Composable
actual fun TranslateButton(text: String, onTranslation: (String?) -> Unit) {
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sekret = "2.0.0-alpha-04"
serialization = "1.6.3"
splashscreen = "1.0.1"
tooling = "1.3.2"
translate = "17.0.2"
versions = "0.51.0"
windowsize = "0.5.0"

Expand Down Expand Up @@ -105,6 +106,7 @@ splashscreen = { group = "androidx.core", name = "core-splashscreen", version.re
tooling = { group = "dev.datlag.tooling", name = "tooling-async", version.ref = "tooling" }
tooling-country = { group = "dev.datlag.tooling", name = "tooling-country", version.ref = "tooling" }
tooling-decompose = { group = "dev.datlag.tooling", name = "tooling-decompose", version.ref = "tooling" }
translate = { group = "com.google.mlkit", name = "translate", version.ref = "translate" }
windowsize = { group = "dev.chrisbanes.material3", name = "material3-window-size-class-multiplatform", version.ref = "windowsize" }

[plugins]
Expand Down

0 comments on commit 10cf182

Please sign in to comment.