Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull
import com.lagradost.cloudstream3.CloudStreamApp
import com.lagradost.cloudstream3.CloudStreamApp.Companion.setKey
import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialogInstant
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showNginxTextInputDialog
import java.net.URLEncoder
import com.lagradost.cloudstream3.LoadResponse
import com.lagradost.cloudstream3.LoadResponse.Companion.getAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.getImdbId
Expand Down Expand Up @@ -907,6 +910,74 @@ class GeneratorPlayer : FullScreenPlayer() {
)
}

private fun handleTranslateSubtitlesClick(ctx: Context, sourceDialog: Dialog) {
val proxyUrl = DataStoreHelper.subtitleTranslationProxy
if (proxyUrl.isNullOrBlank()) {
activity?.showNginxTextInputDialog(
name = ctx.getString(R.string.subtitle_translation_proxy_title),
value = "",
textInputType = null,
dismissCallback = {}
) { input ->
if (input.isNotBlank()) {
DataStoreHelper.subtitleTranslationProxy = input.trim()
showToast(R.string.subtitle_translation_proxy_saved)
handleTranslateSubtitlesClick(ctx, sourceDialog)
}
}
return
}

val activeSub = player.getCurrentPreferredSubtitle()
?: viewModel.state.subtitles.firstOrNull { it.origin == SubtitleOrigin.URL }

if (activeSub == null) {
showToast(R.string.no_subtitle_selected_to_translate)
return
}
if (activeSub.origin != SubtitleOrigin.URL) {
showToast(R.string.only_url_subtitles_can_be_translated)
return
}

val languages = listOf(
Pair("🇦🇿 Azerbaijani", "az"),
Pair("🇹🇷 Turkish", "tr"),
Pair("🇬🇧 English", "en"),
Pair("🇷🇺 Russian", "ru"),
Pair("🇩🇪 German", "de"),
Pair("🇪🇸 Spanish", "es"),
Pair("🇫🇷 French", "fr"),
Pair("🇮🇹 Italian", "it"),
Pair("🇸🇦 Arabic", "ar"),
Pair("🇵🇹 Portuguese", "pt")
)

activity?.showBottomDialogInstant(
items = languages.map { it.first },
name = ctx.getString(R.string.select_target_language),
dismissCallback = {}
) { selectedIndex ->
if (selectedIndex in languages.indices) {
val (label, code) = languages[selectedIndex]
val encodedUrl = URLEncoder.encode(activeSub.getFixedUrl(), "UTF-8")
val proxiedUrl = "${proxyUrl.trimEnd('/')}/translate?url=$encodedUrl&target=$code"

val translatedData = SubtitleData(
originalName = "$label (AI)",
nameSuffix = "",
url = proxiedUrl,
origin = SubtitleOrigin.URL,
mimeType = MimeTypes.TEXT_VTT,
headers = emptyMap(),
languageCode = code
)
sourceDialog.dismissSafe(activity)
addAndSelectSubtitles(translatedData)
}
}
}

// Open file picker
private val subsPathPicker =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
Expand Down Expand Up @@ -1042,6 +1113,17 @@ class GeneratorPlayer : FullScreenPlayer() {
}
subtitleList.addFooterView(loadFromFileFooter)

val translateSubsFooter: TextView =
layoutInflater.inflate(R.layout.sort_bottom_footer_add_choice, null) as TextView
translateSubsFooter.text = ctx.getString(R.string.translate_subtitles)
translateSubsFooter.setCompoundDrawablesWithIntrinsicBounds(
R.drawable.ic_baseline_auto_awesome_24, 0, 0, 0
)
translateSubsFooter.setOnClickListener {
handleTranslateSubtitlesClick(ctx, sourceDialog)
}
subtitleList.addFooterView(translateSubsFooter)

var shouldDismiss = true

binding.subtitleSettingsBtt.setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ import com.lagradost.cloudstream3.ui.subtitles.ChromecastSubtitlesFragment
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.DataStoreHelper
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showNginxTextInputDialog
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard

class SettingsPlayer : BasePreferenceFragmentCompat() {
Expand Down Expand Up @@ -247,6 +249,29 @@ class SettingsPlayer : BasePreferenceFragmentCompat() {
return@setOnPreferenceClickListener true
}

val translationProxyPref = getPref(R.string.subtitle_translation_proxy_key)
fun updateProxySummary() {
val current = DataStoreHelper.subtitleTranslationProxy
translationProxyPref?.summary = if (current.isNullOrBlank()) {
getString(R.string.subtitle_translation_proxy_not_set)
} else {
current
}
}
updateProxySummary()
translationProxyPref?.setOnPreferenceClickListener {
activity?.showNginxTextInputDialog(
name = getString(R.string.subtitle_translation_proxy_title),
value = DataStoreHelper.subtitleTranslationProxy ?: "",
textInputType = null,
dismissCallback = {}
) { input ->
DataStoreHelper.subtitleTranslationProxy = input.trim().ifBlank { null }
updateProxySummary()
}
return@setOnPreferenceClickListener true
}

getPref(R.string.player_source_priority_key)?.setOnPreferenceClickListener {
ioSafe {
val defaultSources = QualityProfileDialog.getAllDefaultSources()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const val RESULT_SEASON = "result_season"
const val RESULT_DUB = "result_dub"
const val KEY_RESULT_SORT = "result_sort"
const val USER_PINNED_PROVIDERS = "user_pinned_providers" // Key for pinned user set
const val SUBTITLE_TRANSLATION_PROXY = "subtitle_translation_proxy"

class UserPreferenceDelegate<T : Any>(
private val key: String,
Expand Down Expand Up @@ -160,6 +161,16 @@ object DataStoreHelper {
_resultsSortingMode = value.ordinal
}

var subtitleTranslationProxy: String?
get() = getKey(SUBTITLE_TRANSLATION_PROXY)
set(value) {
if (value.isNullOrBlank()) {
removeKey(SUBTITLE_TRANSLATION_PROXY)
} else {
setKey(SUBTITLE_TRANSLATION_PROXY, value)
}
}

@Serializable
data class Account(
@JsonProperty("keyIndex") @SerialName("keyIndex") val keyIndex: Int,
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_baseline_auto_awesome_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,9l1.25,-2.75L23,5l-2.75,-1.25L19,1l-1.25,2.75L15,5l2.75,1.25L19,9zM11.5,9.5L9,4L6.5,9.5L1,12l5.5,2.5L9,20l2.5,-5.5L17,12l-5.5,-2.5zM19,15l-1.25,2.75L15,19l2.75,1.25L19,23l1.25,-2.75L23,19l-2.75,-1.25L19,15z"/>
</vector>
11 changes: 11 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,17 @@
<string name="subtitle_offset">Sync subs</string>
<string name="subtitle_offset_hint">1000 ms</string>
<string name="subtitle_offset_title">Subtitle delay</string>
<string name="subtitle_translation_proxy_key">subtitle_translation_proxy_key</string>
<string name="subtitle_translation_proxy_title">Subtitle Translation Proxy</string>
<string name="subtitle_translation_proxy_summary">Proxy server URL for translating subtitles</string>
<string name="subtitle_translation_proxy_not_set">Not configured. Tap to set proxy URL.</string>
<string name="subtitle_translation_proxy_dialog_message">Enter your subtitle translation proxy server URL (e.g. https://your-proxy.com).</string>
<string name="subtitle_translation_proxy_saved">Translation proxy URL saved</string>
<string name="subtitle_translation_proxy_cleared">Translation proxy URL cleared</string>
<string name="translate_subtitles">Translate subtitles</string>
<string name="select_target_language">Select target language</string>
<string name="no_subtitle_selected_to_translate">Please select a subtitle to translate first</string>
<string name="only_url_subtitles_can_be_translated">Only online URL subtitles can be translated</string>
<string name="subtitle_offset_extra_hint_later_format">Use this if the subtitles are shown %d ms too early</string>
<string name="subtitle_offset_extra_hint_before_format">Use this if subtitles are shown %d ms too late</string>
<string name="subtitle_offset_extra_hint_none_format">No subtitle delay</string>
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/xml/settings_player.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
android:key="@string/subtitle_settings_chromecast_key"
android:title="@string/chromecast_subtitles_settings"
app:summary="@string/chromecast_subtitles_settings_des" />
<Preference
android:icon="@drawable/ic_baseline_auto_awesome_24"
android:key="@string/subtitle_translation_proxy_key"
android:title="@string/subtitle_translation_proxy_title"
app:summary="@string/subtitle_translation_proxy_summary" />
</PreferenceCategory>


Expand Down