Snowmlt: Add support to arabic (#7514)
* Add support to arabic * Refatoring
This commit is contained in:
parent
d6e5553084
commit
643376e8a0
|
@ -2,3 +2,5 @@ font_size_title=Font size
|
||||||
font_size_summary=Font changes will not be applied to downloaded or cached chapters. The font size will be adjusted according to the size of the dialog box.
|
font_size_summary=Font changes will not be applied to downloaded or cached chapters. The font size will be adjusted according to the size of the dialog box.
|
||||||
font_size_message=Font size changed to %s
|
font_size_message=Font size changed to %s
|
||||||
default_font_size=Default
|
default_font_size=Default
|
||||||
|
disable_website_setting_title=Disable source settings
|
||||||
|
disable_website_setting_summary=The site's fonts and colors will be disabled
|
||||||
|
|
|
@ -2,3 +2,5 @@ font_size_title=Tamanho da fonte
|
||||||
font_size_summary=As alterações de fonte não serão aplicadas aos capítulos baixados ou armazenados em cache. O tamanho da fonte será ajustado de acordo com o tamanho da caixa de diálogo.
|
font_size_summary=As alterações de fonte não serão aplicadas aos capítulos baixados ou armazenados em cache. O tamanho da fonte será ajustado de acordo com o tamanho da caixa de diálogo.
|
||||||
font_size_message=Tamanho da fonte foi alterada para %s
|
font_size_message=Tamanho da fonte foi alterada para %s
|
||||||
default_font_size=Padrão
|
default_font_size=Padrão
|
||||||
|
disable_website_setting_title=Desativar configurações do site
|
||||||
|
disable_website_setting_summary=As fontes e cores do site serão desativadas
|
||||||
|
|
|
@ -6,7 +6,9 @@ import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import eu.kanade.tachiyomi.lib.i18n.Intl
|
import eu.kanade.tachiyomi.lib.i18n.Intl
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.interceptors.ComposedImageInterceptor
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.interceptors.ComposedImageInterceptor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
@ -22,6 +24,7 @@ import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
|
@ -33,12 +36,13 @@ import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
abstract class MachineTranslations(
|
abstract class MachineTranslations(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val baseUrl: String,
|
override val baseUrl: String,
|
||||||
val language: Language,
|
private val language: Language,
|
||||||
) : ParsedHttpSource(), ConfigurableSource {
|
) : ParsedHttpSource(), ConfigurableSource {
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
@ -47,14 +51,31 @@ abstract class MachineTranslations(
|
||||||
|
|
||||||
override val lang = language.lang
|
override val lang = language.lang
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
protected val preferences: SharedPreferences by lazy {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag that tracks whether the settings have been changed. It is used to indicate if
|
||||||
|
* any configuration change has occurred. Once the value is accessed, it resets to `false`.
|
||||||
|
* This is useful for tracking whether a preference has been modified, and ensures that
|
||||||
|
* the change status is cleared after it has been accessed, to prevent multiple triggers.
|
||||||
|
*/
|
||||||
|
private var isSettingsChanged: Boolean = false
|
||||||
|
get() {
|
||||||
|
val current = field
|
||||||
|
field = false
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
protected var fontSize: Int
|
protected var fontSize: Int
|
||||||
get() = preferences.getString(FONT_SIZE_PREF, DEFAULT_FONT_SIZE)!!.toInt()
|
get() = preferences.getString(FONT_SIZE_PREF, DEFAULT_FONT_SIZE)!!.toInt()
|
||||||
set(value) = preferences.edit().putString(FONT_SIZE_PREF, value.toString()).apply()
|
set(value) = preferences.edit().putString(FONT_SIZE_PREF, value.toString()).apply()
|
||||||
|
|
||||||
|
protected var disableSourceSettings: Boolean
|
||||||
|
get() = preferences.getBoolean(DISABLE_SOURCE_SETTINGS_PREF, language.disableSourceSettings)
|
||||||
|
set(value) = preferences.edit().putBoolean(DISABLE_SOURCE_SETTINGS_PREF, value).apply()
|
||||||
|
|
||||||
private val intl = Intl(
|
private val intl = Intl(
|
||||||
language = language.lang,
|
language = language.lang,
|
||||||
baseLanguage = "en",
|
baseLanguage = "en",
|
||||||
|
@ -62,10 +83,33 @@ abstract class MachineTranslations(
|
||||||
classLoader = this::class.java.classLoader!!,
|
classLoader = this::class.java.classLoader!!,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val client: OkHttpClient by lazy {
|
private val settings get() = language.apply {
|
||||||
network.cloudflareClient.newBuilder()
|
fontSize = this@MachineTranslations.fontSize
|
||||||
.addInterceptor(ComposedImageInterceptor(baseUrl, language, fontSize))
|
}
|
||||||
.build()
|
|
||||||
|
open val useDefaultComposedImageInterceptor: Boolean = true
|
||||||
|
|
||||||
|
override val client: OkHttpClient get() = clientInstance!!
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This ensures that the `OkHttpClient` instance is only created when required, and it is rebuilt
|
||||||
|
* when there are configuration changes to ensure that the client uses the most up-to-date settings.
|
||||||
|
*/
|
||||||
|
private var clientInstance: OkHttpClient? = null
|
||||||
|
get() {
|
||||||
|
if (field == null || isSettingsChanged) {
|
||||||
|
field = clientBuilder().build()
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun clientBuilder() = network.cloudflareClient.newBuilder()
|
||||||
|
.connectTimeout(1, TimeUnit.MINUTES)
|
||||||
|
.readTimeout(2, TimeUnit.MINUTES)
|
||||||
|
.addInterceptorIf(useDefaultComposedImageInterceptor, ComposedImageInterceptor(baseUrl, settings))
|
||||||
|
|
||||||
|
private fun OkHttpClient.Builder.addInterceptorIf(condition: Boolean, interceptor: Interceptor): OkHttpClient.Builder {
|
||||||
|
return this.takeIf { condition.not() } ?: this.addInterceptor(interceptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================== Popular ===============================
|
// ============================== Popular ===============================
|
||||||
|
@ -249,7 +293,7 @@ abstract class MachineTranslations(
|
||||||
entryValues = sizes
|
entryValues = sizes
|
||||||
summary = intl["font_size_summary"]
|
summary = intl["font_size_summary"]
|
||||||
|
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChange { _, newValue ->
|
||||||
val selected = newValue as String
|
val selected = newValue as String
|
||||||
val index = this.findIndexOfValue(selected)
|
val index = this.findIndexOfValue(selected)
|
||||||
val entry = entries[index] as String
|
val entry = entries[index] as String
|
||||||
|
@ -262,16 +306,43 @@ abstract class MachineTranslations(
|
||||||
Toast.LENGTH_LONG,
|
Toast.LENGTH_LONG,
|
||||||
).show()
|
).show()
|
||||||
|
|
||||||
false
|
true // It's necessary to update the user interface
|
||||||
}
|
}
|
||||||
}.also(screen::addPreference)
|
}.also(screen::addPreference)
|
||||||
|
|
||||||
|
if (language.disableSourceSettings.not()) {
|
||||||
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
|
key = DISABLE_SOURCE_SETTINGS_PREF
|
||||||
|
title = "⚠ ${intl["disable_website_setting_title"]}"
|
||||||
|
summary = intl["disable_website_setting_summary"]
|
||||||
|
setDefaultValue(false)
|
||||||
|
setOnPreferenceChange { _, newValue ->
|
||||||
|
disableSourceSettings = newValue as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an `OnPreferenceChangeListener` for the preference, and before triggering the original listener,
|
||||||
|
* marks that the configuration has changed by setting `isSettingsChanged` to `true`.
|
||||||
|
* This behavior is useful for applying runtime configurations in the HTTP client,
|
||||||
|
* ensuring that the preference change is registered before invoking the original listener.
|
||||||
|
*/
|
||||||
|
protected fun Preference.setOnPreferenceChange(onPreferenceChangeListener: Preference.OnPreferenceChangeListener) {
|
||||||
|
setOnPreferenceChangeListener { preference, newValue ->
|
||||||
|
isSettingsChanged = true
|
||||||
|
onPreferenceChangeListener.onPreferenceChange(preference, newValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val PAGE_REGEX = Regex(".*?\\.(webp|png|jpg|jpeg)#\\[.*?]", RegexOption.IGNORE_CASE)
|
val PAGE_REGEX = Regex(".*?\\.(webp|png|jpg|jpeg)#\\[.*?]", RegexOption.IGNORE_CASE)
|
||||||
const val PREFIX_SEARCH = "id:"
|
const val PREFIX_SEARCH = "id:"
|
||||||
const val FONT_SIZE_PREF = "fontSizePref"
|
private const val FONT_SIZE_PREF = "fontSizePref"
|
||||||
const val DEFAULT_FONT_SIZE = "24"
|
private const val DISABLE_SOURCE_SETTINGS_PREF = "disableSourceSettingsPref"
|
||||||
|
private const val DEFAULT_FONT_SIZE = "24"
|
||||||
|
|
||||||
private val dateFormat: SimpleDateFormat = SimpleDateFormat("dd MMMM yyyy", Locale.US)
|
private val dateFormat: SimpleDateFormat = SimpleDateFormat("dd MMMM yyyy", Locale.US)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,18 @@ package eu.kanade.tachiyomi.multisrc.machinetranslations
|
||||||
|
|
||||||
class MachineTranslationsFactoryUtils
|
class MachineTranslationsFactoryUtils
|
||||||
|
|
||||||
data class Language(val lang: String, val target: String = lang, val origin: String = "en")
|
interface Language {
|
||||||
|
val lang: String
|
||||||
|
val target: String
|
||||||
|
val origin: String
|
||||||
|
var fontSize: Int
|
||||||
|
var disableSourceSettings: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
data class LanguageImpl(
|
||||||
|
override val lang: String,
|
||||||
|
override val target: String = lang,
|
||||||
|
override val origin: String = "en",
|
||||||
|
override var fontSize: Int = 24,
|
||||||
|
override var disableSourceSettings: Boolean = false,
|
||||||
|
) : Language
|
||||||
|
|
|
@ -34,8 +34,7 @@ import kotlin.math.sqrt
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
class ComposedImageInterceptor(
|
class ComposedImageInterceptor(
|
||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
val language: Language,
|
var language: Language,
|
||||||
val fontSize: Int = 24,
|
|
||||||
) : Interceptor {
|
) : Interceptor {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
@ -63,7 +62,9 @@ class ComposedImageInterceptor(
|
||||||
|
|
||||||
// Load the fonts before opening the connection to load the image,
|
// Load the fonts before opening the connection to load the image,
|
||||||
// so there aren't two open connections inside the interceptor.
|
// so there aren't two open connections inside the interceptor.
|
||||||
|
if (language.disableSourceSettings.not()) {
|
||||||
loadAllFont(chain)
|
loadAllFont(chain)
|
||||||
|
}
|
||||||
|
|
||||||
val response = chain.proceed(imageRequest)
|
val response = chain.proceed(imageRequest)
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ class ComposedImageInterceptor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTextPaint(font: Typeface?): TextPaint {
|
private fun createTextPaint(font: Typeface?): TextPaint {
|
||||||
val defaultTextSize = fontSize.pt
|
val defaultTextSize = language.fontSize.pt
|
||||||
return TextPaint().apply {
|
return TextPaint().apply {
|
||||||
color = Color.BLACK
|
color = Color.BLACK
|
||||||
textSize = defaultTextSize
|
textSize = defaultTextSize
|
||||||
|
@ -116,6 +117,10 @@ class ComposedImageInterceptor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun selectFontFamily(type: String): Typeface? {
|
private fun selectFontFamily(type: String): Typeface? {
|
||||||
|
if (language.disableSourceSettings) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
if (type in fontFamily) {
|
if (type in fontFamily) {
|
||||||
return fontFamily[type]?.second
|
return fontFamily[type]?.second
|
||||||
}
|
}
|
||||||
|
@ -218,7 +223,7 @@ class ComposedImageInterceptor(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use source setup
|
// Use source setup
|
||||||
if (dialog.isNewApi) {
|
if (dialog.isNewApi && language.disableSourceSettings.not()) {
|
||||||
textPaint.color = dialog.foregroundColor
|
textPaint.color = dialog.foregroundColor
|
||||||
textPaint.bgColor = dialog.backgroundColor
|
textPaint.bgColor = dialog.backgroundColor
|
||||||
textPaint.style = if (dialog.isBold) Paint.Style.FILL_AND_STROKE else Paint.Style.FILL
|
textPaint.style = if (dialog.isBold) Paint.Style.FILL_AND_STROKE else Paint.Style.FILL
|
||||||
|
|
|
@ -3,7 +3,7 @@ ext {
|
||||||
extClass = '.SnowmtlFactory'
|
extClass = '.SnowmtlFactory'
|
||||||
themePkg = 'machinetranslations'
|
themePkg = 'machinetranslations'
|
||||||
baseUrl = 'https://snowmtl.ru'
|
baseUrl = 'https://snowmtl.ru'
|
||||||
overrideVersionCode = 7
|
overrideVersionCode = 8
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,19 @@ package eu.kanade.tachiyomi.extension.all.snowmtl
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.preference.PreferenceScreen
|
||||||
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import eu.kanade.tachiyomi.extension.all.snowmtl.interceptors.TranslationInterceptor
|
import eu.kanade.tachiyomi.extension.all.snowmtl.interceptors.TranslationInterceptor
|
||||||
import eu.kanade.tachiyomi.extension.all.snowmtl.translator.BingTranslator
|
import eu.kanade.tachiyomi.extension.all.snowmtl.translator.BingTranslator
|
||||||
import eu.kanade.tachiyomi.extension.all.snowmtl.translator.TranslatorEngine
|
import eu.kanade.tachiyomi.extension.all.snowmtl.translator.TranslatorEngine
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.Language
|
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.MachineTranslations
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.MachineTranslations
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.interceptors.ComposedImageInterceptor
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.interceptors.ComposedImageInterceptor
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
class Snowmtl(
|
class Snowmtl(
|
||||||
language: Language,
|
private val language: LanguageSetting,
|
||||||
) : MachineTranslations(
|
) : MachineTranslations(
|
||||||
name = "Snow Machine Translations",
|
name = "Snow Machine Translations",
|
||||||
baseUrl = "https://snowmtl.ru",
|
baseUrl = "https://snowmtl.ru",
|
||||||
|
@ -22,18 +22,59 @@ class Snowmtl(
|
||||||
) {
|
) {
|
||||||
override val lang = language.lang
|
override val lang = language.lang
|
||||||
|
|
||||||
|
private var disableTranslationOptimization: Boolean
|
||||||
|
get() = preferences.getBoolean(DISABLE_TRANSLATION_OPTIM_PREF, language.disableTranslationOptimization)
|
||||||
|
set(value) = preferences.edit().putBoolean(DISABLE_TRANSLATION_OPTIM_PREF, value).apply()
|
||||||
|
|
||||||
|
private val settings: LanguageSetting get() = language.copy(
|
||||||
|
fontSize = this@Snowmtl.fontSize,
|
||||||
|
disableTranslationOptimization = this@Snowmtl.disableTranslationOptimization,
|
||||||
|
disableSourceSettings = this@Snowmtl.disableSourceSettings,
|
||||||
|
)
|
||||||
|
|
||||||
private val clientUtils = network.cloudflareClient.newBuilder()
|
private val clientUtils = network.cloudflareClient.newBuilder()
|
||||||
.rateLimit(1, 2, TimeUnit.SECONDS)
|
.rateLimit(3, 2, TimeUnit.SECONDS)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
private val translator: TranslatorEngine = BingTranslator(clientUtils, headers)
|
private val translator: TranslatorEngine = BingTranslator(clientUtils, headers)
|
||||||
|
|
||||||
override val client: OkHttpClient by lazy {
|
// Keeps object state
|
||||||
network.cloudflareClient.newBuilder()
|
private val composeInterceptor = ComposedImageInterceptor(baseUrl, settings)
|
||||||
.connectTimeout(1, TimeUnit.MINUTES)
|
private val translatorInterceptor = TranslationInterceptor(settings, translator)
|
||||||
.readTimeout(2, TimeUnit.MINUTES)
|
|
||||||
.addInterceptor(TranslationInterceptor(language, translator))
|
override val useDefaultComposedImageInterceptor = false
|
||||||
.addInterceptor(ComposedImageInterceptor(baseUrl, language, fontSize))
|
|
||||||
.build()
|
override fun clientBuilder() = super.clientBuilder()
|
||||||
|
.rateLimit(3)
|
||||||
|
.addInterceptor(translatorInterceptor.apply { language = this@Snowmtl.settings })
|
||||||
|
.addInterceptor(composeInterceptor.apply { language = this@Snowmtl.settings })
|
||||||
|
|
||||||
|
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||||
|
super.setupPreferenceScreen(screen)
|
||||||
|
|
||||||
|
if (language.target == language.origin) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (language.disableTranslationOptimization.not()) {
|
||||||
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
|
key = DISABLE_TRANSLATION_OPTIM_PREF
|
||||||
|
title = "⚠ Disable translation optimization"
|
||||||
|
summary = buildString {
|
||||||
|
append("Allows dialog boxes to be translated sequentially. ")
|
||||||
|
append("Avoids problems when loading some translated pages caused by the translator's text formatting. ")
|
||||||
|
append("Pages will load more slowly.")
|
||||||
|
}
|
||||||
|
setDefaultValue(false)
|
||||||
|
setOnPreferenceChange { _, newValue ->
|
||||||
|
disableTranslationOptimization = newValue as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DISABLE_TRANSLATION_OPTIM_PREF = "disableTranslationOptimizationPref"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,19 @@ class SnowmtlFactory : SourceFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
private val languageList = listOf(
|
private val languageList = listOf(
|
||||||
Language("en"),
|
LanguageSetting("ar", disableSourceSettings = true, disableTranslationOptimization = true),
|
||||||
Language("es"),
|
LanguageSetting("en"),
|
||||||
Language("id"),
|
LanguageSetting("es"),
|
||||||
Language("it"),
|
LanguageSetting("id"),
|
||||||
Language("pt-BR", "pt"),
|
LanguageSetting("it"),
|
||||||
|
LanguageSetting("pt-BR", "pt"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class LanguageSetting(
|
||||||
|
override val lang: String,
|
||||||
|
override val target: String = lang,
|
||||||
|
override val origin: String = "en",
|
||||||
|
override var fontSize: Int = 24,
|
||||||
|
override var disableSourceSettings: Boolean = false,
|
||||||
|
val disableTranslationOptimization: Boolean = false,
|
||||||
|
) : Language
|
||||||
|
|
|
@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.extension.all.snowmtl.interceptors
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import eu.kanade.tachiyomi.extension.all.snowmtl.LanguageSetting
|
||||||
import eu.kanade.tachiyomi.extension.all.snowmtl.translator.TranslatorEngine
|
import eu.kanade.tachiyomi.extension.all.snowmtl.translator.TranslatorEngine
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.Dialog
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.Dialog
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.Language
|
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.MachineTranslations.Companion.PAGE_REGEX
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.MachineTranslations.Companion.PAGE_REGEX
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
|
@ -15,7 +15,7 @@ import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
class TranslationInterceptor(
|
class TranslationInterceptor(
|
||||||
private val source: Language,
|
var language: LanguageSetting,
|
||||||
private val translator: TranslatorEngine,
|
private val translator: TranslatorEngine,
|
||||||
) : Interceptor {
|
) : Interceptor {
|
||||||
|
|
||||||
|
@ -25,14 +25,19 @@ class TranslationInterceptor(
|
||||||
val request = chain.request()
|
val request = chain.request()
|
||||||
val url = request.url.toString()
|
val url = request.url.toString()
|
||||||
|
|
||||||
if (PAGE_REGEX.containsMatchIn(url).not() || source.target == source.origin) {
|
if (PAGE_REGEX.containsMatchIn(url).not() || language.target == language.origin) {
|
||||||
return chain.proceed(request)
|
return chain.proceed(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
val dialogues = request.url.fragment?.parseAs<List<Dialog>>()
|
val dialogues = request.url.fragment?.parseAs<List<Dialog>>()
|
||||||
?: return chain.proceed(request)
|
?: return chain.proceed(request)
|
||||||
|
|
||||||
val translated = translationOptimized(dialogues)
|
val translated = when {
|
||||||
|
language.disableTranslationOptimization -> dialogues.map {
|
||||||
|
it.replaceText(translator.translate(language.origin, language.target, it.text))
|
||||||
|
}
|
||||||
|
else -> translationOptimized(dialogues)
|
||||||
|
}
|
||||||
|
|
||||||
val newRequest = request.newBuilder()
|
val newRequest = request.newBuilder()
|
||||||
.url("${url.substringBeforeLast("#")}#${json.encodeToString(translated)}")
|
.url("${url.substringBeforeLast("#")}#${json.encodeToString(translated)}")
|
||||||
|
@ -52,7 +57,7 @@ class TranslationInterceptor(
|
||||||
val mapping = buildMap(dialogues)
|
val mapping = buildMap(dialogues)
|
||||||
|
|
||||||
val tokens = tokenizeAssociatedDialog(mapping).flatMap { token ->
|
val tokens = tokenizeAssociatedDialog(mapping).flatMap { token ->
|
||||||
translator.translate(source.origin, source.target, token).split(delimiter)
|
translator.translate(language.origin, language.target, token).split(delimiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
return replaceDialoguesWithTranslations(tokens, mapping)
|
return replaceDialoguesWithTranslations(tokens, mapping)
|
||||||
|
@ -79,12 +84,14 @@ class TranslationInterceptor(
|
||||||
val key = list.first()
|
val key = list.first()
|
||||||
val text = list.last()
|
val text = list.last()
|
||||||
|
|
||||||
mapping[key]?.second?.dialog?.copy(
|
mapping[key]?.second?.dialog?.replaceText(text)
|
||||||
textByLanguage = mapOf(
|
}
|
||||||
"text" to text,
|
|
||||||
|
private fun Dialog.replaceText(value: String) = this.copy(
|
||||||
|
textByLanguage = mutableMapOf(
|
||||||
|
"text" to value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tokenizes the associated dialogues.
|
* Tokenizes the associated dialogues.
|
||||||
|
|
|
@ -4,8 +4,6 @@ import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.Language
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.Language
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.MachineTranslations
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.MachineTranslations
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
class Solarmtl(
|
class Solarmtl(
|
||||||
|
@ -14,9 +12,4 @@ class Solarmtl(
|
||||||
name = "Solar Machine Translations",
|
name = "Solar Machine Translations",
|
||||||
baseUrl = "https://solarmtl.com",
|
baseUrl = "https://solarmtl.com",
|
||||||
language,
|
language,
|
||||||
) {
|
)
|
||||||
override val client = super.client.newBuilder()
|
|
||||||
.connectTimeout(1, TimeUnit.MINUTES)
|
|
||||||
.rateLimit(2)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.extension.all.solarmtl
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import eu.kanade.tachiyomi.multisrc.machinetranslations.Language
|
import eu.kanade.tachiyomi.multisrc.machinetranslations.LanguageImpl
|
||||||
import eu.kanade.tachiyomi.source.SourceFactory
|
import eu.kanade.tachiyomi.source.SourceFactory
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@ -11,7 +11,7 @@ class SolarmtlFactory : SourceFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
private val languageList = listOf(
|
private val languageList = listOf(
|
||||||
Language("en"),
|
LanguageImpl("en"),
|
||||||
Language("fr"),
|
LanguageImpl("fr"),
|
||||||
Language("pt-BR", "pt"),
|
LanguageImpl("pt-BR", "pt"),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue