mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge branch 'recloudstream:master' into arabicLanguage
This commit is contained in:
commit
96a447c302
23 changed files with 1014 additions and 141 deletions
|
@ -20,6 +20,8 @@
|
|||
***The list of supported languages:***
|
||||
* 🇱🇧 Arabic
|
||||
* 🇧🇬 Bulgarian
|
||||
* 🇨🇳 Chinese Simplified
|
||||
* 🇹🇼 Chinese Traditional
|
||||
* 🇭🇷 Croatian
|
||||
* 🇨🇿 Czech
|
||||
* 🇳🇱 Dutch
|
||||
|
|
|
@ -191,7 +191,8 @@ dependencies {
|
|||
// implementation("com.squareup.okhttp3:okhttp:4.9.2")
|
||||
// implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1")
|
||||
implementation("com.github.Blatzar:NiceHttp:0.3.5")
|
||||
|
||||
// To fix SSL fuckery on android 9
|
||||
implementation("org.conscrypt:conscrypt-android:2.2.1")
|
||||
// Util to skip the URI file fuckery 🙏
|
||||
implementation("com.github.tachiyomiorg:unifile:17bec43")
|
||||
|
||||
|
|
|
@ -110,6 +110,17 @@
|
|||
|
||||
<data android:scheme="cloudstreamrepo" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Allow searching with intents: cloudstreamsearch://Your%20Name -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="cloudstreamsearch" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
|
|
|
@ -108,9 +108,18 @@ object CommonActivity {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not all languages can be fetched from locale with a code.
|
||||
* This map allows sidestepping the default Locale(languageCode)
|
||||
* when setting the app language.
|
||||
**/
|
||||
val appLanguageExceptions = hashMapOf(
|
||||
"zh_TW" to Locale.TRADITIONAL_CHINESE
|
||||
)
|
||||
|
||||
fun setLocale(context: Context?, languageCode: String?) {
|
||||
if (context == null || languageCode == null) return
|
||||
val locale = Locale(languageCode)
|
||||
val locale = appLanguageExceptions[languageCode] ?: Locale(languageCode)
|
||||
val resources: Resources = context.resources
|
||||
val config = resources.configuration
|
||||
Locale.setDefault(locale)
|
||||
|
@ -146,8 +155,8 @@ object CommonActivity {
|
|||
val resultCode = result.resultCode
|
||||
val data = result.data
|
||||
if (resultCode == AppCompatActivity.RESULT_OK && data != null && resumeApp.position != null && resumeApp.duration != null) {
|
||||
val pos = data.getLongExtra(resumeApp.position, -1L)
|
||||
val dur = data.getLongExtra(resumeApp.duration, -1L)
|
||||
val pos = resumeApp.getPosition(data)
|
||||
val dur = resumeApp.getDuration(data)
|
||||
if (dur > 0L && pos > 0L)
|
||||
DataStoreHelper.setViewPos(getKey(resumeApp.lastId), pos, dur)
|
||||
removeKey(resumeApp.lastId)
|
||||
|
@ -421,4 +430,4 @@ object CommonActivity {
|
|||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1143,9 +1143,9 @@ fun getDurationFromString(input: String?): Int? {
|
|||
if (values.size == 3) {
|
||||
val hours = values[1].toIntOrNull()
|
||||
val minutes = values[2].toIntOrNull()
|
||||
return if (minutes != null && hours != null) {
|
||||
hours * 60 + minutes
|
||||
} else null
|
||||
if (minutes != null && hours != null) {
|
||||
return hours * 60 + minutes
|
||||
}
|
||||
}
|
||||
}
|
||||
Regex("([0-9]*)m").find(cleanInput)?.groupValues?.let { values ->
|
||||
|
@ -1153,6 +1153,27 @@ fun getDurationFromString(input: String?): Int? {
|
|||
return values[1].toIntOrNull()
|
||||
}
|
||||
}
|
||||
Regex("(\\s\\d+\\shr)|(\\s\\d+\\shour)|(\\s\\d+\\smin)|(\\s\\d+\\ssec)").findAll(input).let { values ->
|
||||
var seconds = 0
|
||||
values.forEach {
|
||||
val time_text = it.value
|
||||
if (time_text.isNotBlank()) {
|
||||
val time = time_text.filter { s -> s.isDigit() }.trim().toInt()
|
||||
val scale = time_text.filter { s -> !s.isDigit() }.trim()
|
||||
//println("Scale: $scale")
|
||||
val timeval = when (scale) {
|
||||
"hr", "hour" -> time * 60 * 60
|
||||
"min" -> time * 60
|
||||
"sec" -> time
|
||||
else -> 0
|
||||
}
|
||||
seconds += timeval
|
||||
}
|
||||
}
|
||||
if (seconds > 0) {
|
||||
return seconds / 60
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,9 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.*
|
||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
|
@ -44,17 +42,21 @@ import com.lagradost.cloudstream3.CommonActivity.onUserLeaveHint
|
|||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.CommonActivity.updateLocale
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.network.initClient
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager.loadAllOnlinePlugins
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager.loadSinglePlugin
|
||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.OAuth2Apis
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appString
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringSearch
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths
|
||||
import com.lagradost.cloudstream3.ui.APIRepository
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
||||
import com.lagradost.cloudstream3.ui.search.SearchFragment
|
||||
import com.lagradost.cloudstream3.ui.search.SearchResultBuilder
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
|
@ -88,11 +90,9 @@ import kotlinx.android.synthetic.main.activity_main.*
|
|||
import kotlinx.android.synthetic.main.fragment_result_swipe.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import okhttp3.ConnectionSpec
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.internal.applyConnectionSpec
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
import java.net.URLDecoder
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
@ -115,13 +115,15 @@ val VLC_COMPONENT = ComponentName(VLC_PACKAGE, "$VLC_PACKAGE.gui.video.VideoPlay
|
|||
val MPV_COMPONENT = ComponentName(MPV_PACKAGE, "$MPV_PACKAGE.MPVActivity")
|
||||
|
||||
//TODO REFACTOR AF
|
||||
data class ResultResume(
|
||||
open class ResultResume(
|
||||
val packageString: String,
|
||||
val action: String = Intent.ACTION_VIEW,
|
||||
val position: String? = null,
|
||||
val duration: String? = null,
|
||||
var launcher: ActivityResultLauncher<Intent>? = null,
|
||||
) {
|
||||
val defaultTime = -1L
|
||||
|
||||
val lastId get() = "${packageString}_last_open_id"
|
||||
suspend fun launch(id: Int?, callback: suspend Intent.() -> Unit) {
|
||||
val intent = Intent(action)
|
||||
|
@ -135,21 +137,45 @@ data class ResultResume(
|
|||
callback.invoke(intent)
|
||||
launcher?.launch(intent)
|
||||
}
|
||||
|
||||
open fun getPosition(intent: Intent?): Long {
|
||||
return defaultTime
|
||||
}
|
||||
|
||||
open fun getDuration(intent: Intent?): Long {
|
||||
return defaultTime
|
||||
}
|
||||
}
|
||||
|
||||
val VLC = ResultResume(
|
||||
val VLC = object : ResultResume(
|
||||
VLC_PACKAGE,
|
||||
"org.videolan.vlc.player.result",
|
||||
"extra_position",
|
||||
"extra_duration",
|
||||
)
|
||||
) {
|
||||
override fun getPosition(intent: Intent?): Long {
|
||||
return intent?.getLongExtra(this.position, defaultTime) ?: defaultTime
|
||||
}
|
||||
|
||||
val MPV = ResultResume(
|
||||
override fun getDuration(intent: Intent?): Long {
|
||||
return intent?.getLongExtra(this.duration, defaultTime) ?: defaultTime
|
||||
}
|
||||
}
|
||||
|
||||
val MPV = object : ResultResume(
|
||||
MPV_PACKAGE,
|
||||
//"is.xyz.mpv.MPVActivity.result", // resume not working :pensive:
|
||||
position = "position",
|
||||
position = "position",
|
||||
duration = "duration",
|
||||
)
|
||||
) {
|
||||
override fun getPosition(intent: Intent?): Long {
|
||||
return intent?.getIntExtra(this.position, defaultTime.toInt())?.toLong() ?: defaultTime
|
||||
}
|
||||
|
||||
override fun getDuration(intent: Intent?): Long {
|
||||
return intent?.getIntExtra(this.duration, defaultTime.toInt())?.toLong() ?: defaultTime
|
||||
}
|
||||
}
|
||||
|
||||
val WEB_VIDEO = ResultResume(WEB_VIDEO_CAST_PACKAGE)
|
||||
|
||||
|
@ -188,6 +214,15 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
companion object {
|
||||
const val TAG = "MAINACT"
|
||||
|
||||
/**
|
||||
* Setting this will automatically enter the query in the search
|
||||
* next time the search fragment is opened.
|
||||
* This variable will clear itself after one use. Null does nothing.
|
||||
*
|
||||
* This is a very bad solution but I was unable to find a better one.
|
||||
**/
|
||||
private var nextSearchQuery: String? = null
|
||||
|
||||
/**
|
||||
* Fires every time a new batch of plugins have been loaded, no guarantee about how often this is run and on which thread
|
||||
* */
|
||||
|
@ -206,6 +241,9 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
isWebview: Boolean
|
||||
): Boolean =
|
||||
with(activity) {
|
||||
// Invalid URIs can crash
|
||||
fun safeURI(uri: String) = normalSafeApiCall { URI(uri) }
|
||||
|
||||
if (str != null && this != null) {
|
||||
if (str.startsWith("https://cs.repo")) {
|
||||
val realUrl = "https://" + str.substringAfter("?")
|
||||
|
@ -241,10 +279,14 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
return true
|
||||
}
|
||||
}
|
||||
} else if (URI(str).scheme == appStringRepo) {
|
||||
} else if (safeURI(str)?.scheme == appStringRepo) {
|
||||
val url = str.replaceFirst(appStringRepo, "https")
|
||||
loadRepository(url)
|
||||
return true
|
||||
} else if (safeURI(str)?.scheme == appStringSearch) {
|
||||
nextSearchQuery =
|
||||
URLDecoder.decode(str.substringAfter("$appStringSearch://"), "UTF-8")
|
||||
nav_view.selectedItemId = R.id.navigation_search
|
||||
} else if (!isWebview) {
|
||||
if (str.startsWith(DOWNLOAD_NAVIGATE_TO)) {
|
||||
this.navigate(R.id.navigation_downloads)
|
||||
|
@ -553,7 +595,16 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
) {
|
||||
PluginManager.updateAllOnlinePluginsAndLoadThem(this@MainActivity)
|
||||
} else {
|
||||
PluginManager.loadAllOnlinePlugins(this@MainActivity)
|
||||
loadAllOnlinePlugins(this@MainActivity)
|
||||
}
|
||||
|
||||
//Automatically download not existing plugins
|
||||
if (settingsManager.getBoolean(
|
||||
getString(R.string.auto_download_plugins_key),
|
||||
false
|
||||
)
|
||||
) {
|
||||
PluginManager.downloadNotExistingPluginsAndLoad(this@MainActivity)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,6 +670,17 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
val navHostFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
|
||||
val navController = navHostFragment.navController
|
||||
|
||||
navController.addOnDestinationChangedListener { _: NavController, navDestination: NavDestination, bundle: Bundle? ->
|
||||
// Intercept search and add a query
|
||||
if (navDestination.matchDestination(R.id.navigation_search) && !nextSearchQuery.isNullOrBlank()) {
|
||||
bundle?.apply {
|
||||
this.putString(SearchFragment.SEARCH_QUERY, nextSearchQuery)
|
||||
nextSearchQuery = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//val navController = findNavController(R.id.nav_host_fragment)
|
||||
|
||||
/*navOptions = NavOptions.Builder()
|
||||
|
|
|
@ -13,39 +13,42 @@ open class VoeExtractor : ExtractorApi() {
|
|||
override val requiresReferer = false
|
||||
|
||||
private data class ResponseLinks(
|
||||
@JsonProperty("hls") val url: String?,
|
||||
@JsonProperty("hls") val hls: String?,
|
||||
@JsonProperty("mp4") val mp4: String?,
|
||||
@JsonProperty("video_height") val label: Int?
|
||||
//val type: String // Mp4
|
||||
)
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
|
||||
val doc = app.get(url).text
|
||||
if (doc.isNotBlank()) {
|
||||
val start = "const sources ="
|
||||
var src = doc.substring(doc.indexOf(start))
|
||||
src = src.substring(start.length, src.indexOf(";"))
|
||||
val html = app.get(url).text
|
||||
if (html.isNotBlank()) {
|
||||
val src = html.substringAfter("const sources =").substringBefore(";")
|
||||
// Remove last comma, it is not proper json otherwise
|
||||
.replace("0,", "0")
|
||||
.trim()
|
||||
// Make json use the proper quotes
|
||||
.replace("'", "\"")
|
||||
|
||||
//Log.i(this.name, "Result => (src) ${src}")
|
||||
parseJson<ResponseLinks?>(src)?.let { voelink ->
|
||||
//Log.i(this.name, "Result => (voelink) ${voelink}")
|
||||
val linkUrl = voelink.url
|
||||
val linkLabel = voelink.label?.toString() ?: ""
|
||||
parseJson<ResponseLinks?>(src)?.let { voeLink ->
|
||||
//Log.i(this.name, "Result => (voeLink) ${voeLink}")
|
||||
|
||||
// Always defaults to the hls link, but returns the mp4 if null
|
||||
val linkUrl = voeLink.hls ?: voeLink.mp4
|
||||
val linkLabel = voeLink.label?.toString() ?: ""
|
||||
if (!linkUrl.isNullOrEmpty()) {
|
||||
extractedLinksList.add(
|
||||
return listOf(
|
||||
ExtractorLink(
|
||||
name = this.name,
|
||||
source = this.name,
|
||||
url = linkUrl,
|
||||
quality = getQualityFromName(linkLabel),
|
||||
referer = url,
|
||||
isM3u8 = true
|
||||
isM3u8 = voeLink.hls != null
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return extractedLinksList
|
||||
return emptyList()
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package com.lagradost.cloudstream3.network
|
|||
|
||||
import androidx.annotation.AnyThread
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.nicehttp.Requests.Companion.await
|
||||
import com.lagradost.nicehttp.Requests
|
||||
import com.lagradost.nicehttp.cookies
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.Interceptor
|
||||
|
@ -41,7 +41,8 @@ class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor {
|
|||
savedCookiesMap[request.url.host]
|
||||
// If no cookies are found fetch and save em.
|
||||
?: (request.url.scheme + "://" + request.url.host + (ddosBypassPath ?: "")).let {
|
||||
app.get(it, cacheTime = 0).cookies.also { cookies ->
|
||||
// Somehow app.get fails
|
||||
Requests().get(it).cookies.also { cookies ->
|
||||
savedCookiesMap[request.url.host] = cookies
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +52,6 @@ class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor {
|
|||
request.newBuilder()
|
||||
.headers(headers)
|
||||
.build()
|
||||
).await()
|
||||
).execute()
|
||||
}
|
||||
}
|
|
@ -4,15 +4,19 @@ import android.content.Context
|
|||
import androidx.preference.PreferenceManager
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.USER_AGENT
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.nicehttp.Requests
|
||||
import com.lagradost.nicehttp.ignoreAllSSLErrors
|
||||
import okhttp3.Cache
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Headers.Companion.toHeaders
|
||||
import okhttp3.OkHttpClient
|
||||
import org.conscrypt.Conscrypt
|
||||
import java.io.File
|
||||
import java.security.Security
|
||||
|
||||
fun Requests.initClient(context: Context): OkHttpClient {
|
||||
normalSafeApiCall { Security.insertProviderAt(Conscrypt.newProvider(), 1) }
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0)
|
||||
baseClient = OkHttpClient.Builder()
|
||||
|
|
|
@ -13,11 +13,13 @@ import androidx.core.app.NotificationManagerCompat
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.google.gson.Gson
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.removePluginMapping
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.showToast
|
||||
import com.lagradost.cloudstream3.MainAPI.Companion.settingsForProvider
|
||||
import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent
|
||||
import com.lagradost.cloudstream3.mvvm.debugPrint
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
|
@ -26,6 +28,8 @@ import com.lagradost.cloudstream3.plugins.RepositoryManager.ONLINE_PLUGINS_FOLDE
|
|||
import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES
|
||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.downloadPluginToFile
|
||||
import com.lagradost.cloudstream3.plugins.RepositoryManager.getRepoPlugins
|
||||
import com.lagradost.cloudstream3.ui.result.UiText
|
||||
import com.lagradost.cloudstream3.ui.result.txt
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
|
@ -219,9 +223,7 @@ object PluginManager {
|
|||
fun updateAllOnlinePluginsAndLoadThem(activity: Activity) {
|
||||
// Load all plugins as fast as possible!
|
||||
loadAllOnlinePlugins(activity)
|
||||
|
||||
afterPluginsLoadedEvent.invoke(true)
|
||||
|
||||
afterPluginsLoadedEvent.invoke(true)
|
||||
|
||||
val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
|
||||
?: emptyArray()) + PREBUILT_REPOSITORIES
|
||||
|
@ -265,16 +267,98 @@ object PluginManager {
|
|||
}
|
||||
|
||||
main {
|
||||
createNotification(activity, updatedPlugins)
|
||||
val uitext = txt(R.string.plugins_updated, updatedPlugins.size)
|
||||
createNotification(activity, uitext, updatedPlugins)
|
||||
}
|
||||
|
||||
// ioSafe {
|
||||
// ioSafe {
|
||||
afterPluginsLoadedEvent.invoke(true)
|
||||
// }
|
||||
// }
|
||||
|
||||
Log.i(TAG, "Plugin update done!")
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically download plugins not yet existing on local
|
||||
* 1. Gets all online data from online plugins repo
|
||||
* 2. Fetch all not downloaded plugins
|
||||
* 3. Download them and reload plugins
|
||||
**/
|
||||
fun downloadNotExistingPluginsAndLoad(activity: Activity) {
|
||||
val newDownloadPlugins = mutableListOf<String>()
|
||||
val urls = (getKey<Array<RepositoryData>>(REPOSITORIES_KEY)
|
||||
?: emptyArray()) + PREBUILT_REPOSITORIES
|
||||
val onlinePlugins = urls.toList().apmap {
|
||||
getRepoPlugins(it.url)?.toList() ?: emptyList()
|
||||
}.flatten().distinctBy { it.second.url }
|
||||
|
||||
val providerLang = activity.getApiProviderLangSettings()
|
||||
//Log.i(TAG, "providerLang => ${providerLang.toJson()}")
|
||||
|
||||
// Iterate online repos and returns not downloaded plugins
|
||||
val notDownloadedPlugins = onlinePlugins.mapNotNull { onlineData ->
|
||||
val sitePlugin = onlineData.second
|
||||
//Don't include empty urls
|
||||
if (sitePlugin.url.isBlank()) { return@mapNotNull null }
|
||||
if (sitePlugin.repositoryUrl.isNullOrBlank()) { return@mapNotNull null }
|
||||
|
||||
//Omit already existing plugins
|
||||
if (getPluginPath(activity, sitePlugin.internalName, onlineData.first).exists()) {
|
||||
Log.i(TAG, "Skip > ${sitePlugin.internalName}")
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
//Omit lang not selected on language setting
|
||||
val lang = sitePlugin.language ?: return@mapNotNull null
|
||||
//If set to 'universal', don't skip any language
|
||||
if (!providerLang.contains(AllLanguagesName) && !providerLang.contains(lang)) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
//Log.i(TAG, "sitePlugin lang => $lang")
|
||||
|
||||
//Omit NSFW, if disabled
|
||||
sitePlugin.tvTypes?.let { tvtypes ->
|
||||
if (!settingsForProvider.enableAdult) {
|
||||
if (tvtypes.contains(TvType.NSFW.name)) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
}
|
||||
}
|
||||
val savedData = PluginData(
|
||||
url = sitePlugin.url,
|
||||
internalName = sitePlugin.internalName,
|
||||
isOnline = true,
|
||||
filePath = "",
|
||||
version = sitePlugin.version
|
||||
)
|
||||
OnlinePluginData(savedData, onlineData)
|
||||
}
|
||||
//Log.i(TAG, "notDownloadedPlugins => ${notDownloadedPlugins.toJson()}")
|
||||
|
||||
notDownloadedPlugins.apmap { pluginData ->
|
||||
downloadAndLoadPlugin(
|
||||
activity,
|
||||
pluginData.onlineData.second.url,
|
||||
pluginData.savedData.internalName,
|
||||
pluginData.onlineData.first
|
||||
).let { success ->
|
||||
if (success)
|
||||
newDownloadPlugins.add(pluginData.onlineData.second.name)
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
val uitext = txt(R.string.plugins_downloaded, newDownloadPlugins.size)
|
||||
createNotification(activity, uitext, newDownloadPlugins)
|
||||
}
|
||||
|
||||
// ioSafe {
|
||||
afterPluginsLoadedEvent.invoke(true)
|
||||
// }
|
||||
|
||||
Log.i(TAG, "Plugin download done!")
|
||||
}
|
||||
|
||||
/**
|
||||
* Use updateAllOnlinePluginsAndLoadThem
|
||||
* */
|
||||
|
@ -527,12 +611,14 @@ object PluginManager {
|
|||
|
||||
private fun createNotification(
|
||||
context: Context,
|
||||
extensionNames: List<String>
|
||||
uitext: UiText,
|
||||
extensions: List<String>
|
||||
): Notification? {
|
||||
try {
|
||||
if (extensionNames.isEmpty()) return null
|
||||
|
||||
val content = extensionNames.joinToString(", ")
|
||||
if (extensions.isEmpty()) return null
|
||||
|
||||
val content = extensions.joinToString(", ")
|
||||
// main { // DON'T WANT TO SLOW IT DOWN
|
||||
val builder = NotificationCompat.Builder(context, EXTENSIONS_CHANNEL_ID)
|
||||
.setAutoCancel(false)
|
||||
|
@ -541,7 +627,8 @@ object PluginManager {
|
|||
.setSilent(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setColor(context.colorFromAttribute(R.attr.colorPrimary))
|
||||
.setContentTitle(context.getString(R.string.plugins_updated, extensionNames.size))
|
||||
.setContentTitle(uitext.asString(context))
|
||||
//.setContentTitle(context.getString(title, extensionNames.size))
|
||||
.setSmallIcon(R.drawable.ic_baseline_extension_24)
|
||||
.setStyle(
|
||||
NotificationCompat.BigTextStyle()
|
||||
|
|
|
@ -43,6 +43,9 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
|||
const val appString = "cloudstreamapp"
|
||||
const val appStringRepo = "cloudstreamrepo"
|
||||
|
||||
// Instantly start the search given a query
|
||||
const val appStringSearch = "cloudstreamsearch"
|
||||
|
||||
val unixTime: Long
|
||||
get() = System.currentTimeMillis() / 1000L
|
||||
val unixTimeMs: Long
|
||||
|
|
|
@ -15,6 +15,8 @@ import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
|||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
||||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPIManager
|
||||
import com.lagradost.cloudstream3.utils.AppUtils
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubApi {
|
||||
override val idPrefix = "opensubtitles"
|
||||
|
@ -175,7 +177,7 @@ class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubApi
|
|||
val searchQueryUrl = when (imdbId > 0) {
|
||||
//Use imdb_id to search if its valid
|
||||
true -> "$host/subtitles?imdb_id=$imdbId&languages=${fixedLang}$yearQuery$epQuery$seasonQuery"
|
||||
false -> "$host/subtitles?query=$queryText&languages=${fixedLang}$yearQuery$epQuery$seasonQuery"
|
||||
false -> "$host/subtitles?query=${URLEncoder.encode(queryText.lowercase(), StandardCharsets.UTF_8.toString())}&languages=${fixedLang}$yearQuery$epQuery$seasonQuery"
|
||||
}
|
||||
|
||||
val req = app.get(
|
||||
|
|
|
@ -612,6 +612,7 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
|||
//player_media_route_button?.isClickable = !isGone
|
||||
player_go_back_holder?.isGone = isGone
|
||||
player_sources_btt?.isGone = isGone
|
||||
player_skip_episode?.isClickable = !isGone
|
||||
}
|
||||
|
||||
private fun updateLockUI() {
|
||||
|
@ -1101,7 +1102,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() {
|
|||
}
|
||||
|
||||
protected fun uiReset() {
|
||||
isLocked = false
|
||||
isShowing = false
|
||||
|
||||
// if nothing has loaded these buttons should not be visible
|
||||
|
|
|
@ -1582,7 +1582,6 @@ class ResultViewModel2 : ViewModel() {
|
|||
return
|
||||
}
|
||||
|
||||
val episodes = currentEpisodes[indexer]
|
||||
val ranges = currentRanges[indexer]
|
||||
|
||||
if (ranges?.contains(range) != true) {
|
||||
|
@ -1594,7 +1593,6 @@ class ResultViewModel2 : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
val size = episodes?.size
|
||||
val isMovie = currentResponse?.isMovie() == true
|
||||
currentIndex = indexer
|
||||
currentRange = range
|
||||
|
@ -1604,6 +1602,7 @@ class ResultViewModel2 : ViewModel() {
|
|||
text to r
|
||||
} ?: emptyList())
|
||||
|
||||
val size = currentEpisodes[indexer]?.size
|
||||
_episodesCountText.postValue(
|
||||
some(
|
||||
if (isMovie) null else
|
||||
|
@ -1683,9 +1682,12 @@ class ResultViewModel2 : ViewModel() {
|
|||
generator = if (isMovie) {
|
||||
getMovie()?.let { RepoLinkGenerator(listOf(it), page = currentResponse) }
|
||||
} else {
|
||||
episodes?.let { list ->
|
||||
RepoLinkGenerator(list, page = currentResponse)
|
||||
}
|
||||
val episodes = currentEpisodes.filter { it.key.dubStatus == indexer.dubStatus }
|
||||
.toList()
|
||||
.sortedBy { it.first.season }
|
||||
.flatMap { it.second }
|
||||
|
||||
RepoLinkGenerator(episodes, page = currentResponse)
|
||||
}
|
||||
|
||||
if (isMovie) {
|
||||
|
|
|
@ -73,6 +73,14 @@ class SearchFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val SEARCH_QUERY = "search_query"
|
||||
|
||||
fun newInstance(query: String): Bundle {
|
||||
return Bundle().apply {
|
||||
putString(SEARCH_QUERY, query)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val searchViewModel: SearchViewModel by activityViewModels()
|
||||
|
@ -132,7 +140,8 @@ class SearchFragment : Fragment() {
|
|||
val default = enumValues<TvType>().sorted().filter { it != TvType.NSFW }
|
||||
.map { it.ordinal.toString() }.toSet()
|
||||
val preferredTypes = (PreferenceManager.getDefaultSharedPreferences(ctx)
|
||||
.getStringSet(this.getString(R.string.prefer_media_type_key), default)?.ifEmpty { default } ?: default)
|
||||
.getStringSet(this.getString(R.string.prefer_media_type_key), default)
|
||||
?.ifEmpty { default } ?: default)
|
||||
.mapNotNull { it.toIntOrNull() ?: return@mapNotNull null }
|
||||
|
||||
val settings = ctx.getApiSettings()
|
||||
|
@ -487,6 +496,14 @@ class SearchFragment : Fragment() {
|
|||
search_master_recycler?.adapter = masterAdapter
|
||||
search_master_recycler?.layoutManager = GridLayoutManager(context, 1)
|
||||
|
||||
// Automatically search the specified query, this allows the app search to launch from intent
|
||||
arguments?.getString(SEARCH_QUERY)?.let { query ->
|
||||
if (query.isBlank()) return@let
|
||||
main_search?.setQuery(query, true)
|
||||
// Clear the query as to not make it request the same query every time the page is opened
|
||||
arguments?.putString(SEARCH_QUERY, null)
|
||||
}
|
||||
|
||||
// SubtitlesFragment.push(activity)
|
||||
//searchViewModel.search("iron man")
|
||||
//(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
|
||||
|
|
|
@ -47,7 +47,7 @@ fun getCurrentLocale(context: Context): String {
|
|||
// Change locale settings in the app.
|
||||
// val dm = res.displayMetrics
|
||||
val conf = res.configuration
|
||||
return conf?.locale?.language ?: "en"
|
||||
return conf?.locale?.toString() ?: "en"
|
||||
}
|
||||
|
||||
// idk, if you find a way of automating this it would be great
|
||||
|
@ -75,7 +75,8 @@ val appLanguages = arrayListOf(
|
|||
Triple("\uD83C\uDDE7\uD83C\uDDF7", "Brazilian Portuguese", "bp"),
|
||||
Triple("", "Romanian", "ro"),
|
||||
Triple("", "Italian", "it"),
|
||||
Triple("", "Chinese", "zh"),
|
||||
Triple("", "Chinese Simplified", "zh"),
|
||||
Triple("\uD83C\uDDF9\uD83C\uDDFC", "Chinese Traditional", "zh_TW"),
|
||||
Triple("\uD83C\uDDEE\uD83C\uDDE9", "Indonesian", "in"),
|
||||
Triple("", "Czech", "cs"),
|
||||
Triple("", "Croatian", "hr"),
|
||||
|
@ -368,4 +369,4 @@ class SettingsGeneral : PreferenceFragmentCompat() {
|
|||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import androidx.appcompat.widget.SearchView
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.lagradost.cloudstream3.APIHolder.getApiProviderLangSettings
|
||||
import com.lagradost.cloudstream3.AllLanguagesName
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.mvvm.observe
|
||||
|
@ -45,6 +47,15 @@ class PluginsFragment : Fragment() {
|
|||
pluginViewModel.languages = listOf()
|
||||
pluginViewModel.search(null)
|
||||
|
||||
// Filter by language set on preferred media
|
||||
activity?.let {
|
||||
val providerLangs = it.getApiProviderLangSettings().toList()
|
||||
if (!providerLangs.contains(AllLanguagesName)) {
|
||||
pluginViewModel.languages = mutableListOf("none") + providerLangs
|
||||
//Log.i("DevDebug", "providerLang => ${pluginViewModel.languages.toJson()}")
|
||||
}
|
||||
}
|
||||
|
||||
val name = arguments?.getString(PLUGINS_BUNDLE_NAME)
|
||||
val url = arguments?.getString(PLUGINS_BUNDLE_URL)
|
||||
val isLocal = arguments?.getBoolean(PLUGINS_BUNDLE_LOCAL) == true
|
||||
|
|
|
@ -274,7 +274,12 @@
|
|||
app:exitAnim="@anim/exit_anim"
|
||||
app:popEnterAnim="@anim/enter_anim"
|
||||
app:popExitAnim="@anim/exit_anim"
|
||||
tools:layout="@layout/fragment_search" />
|
||||
tools:layout="@layout/fragment_search">
|
||||
<argument
|
||||
android:name="search_query"
|
||||
android:defaultValue=""
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/navigation_downloads"
|
||||
|
|
|
@ -62,61 +62,7 @@
|
|||
<string name="sort_apply">Appliquer</string>
|
||||
<string name="sort_cancel">Annuler</string>
|
||||
<string name="player_speed">Vitesse de lecture</string>
|
||||
<string name="subtitles_settings">Paramètres de sous-titres</string>
|
||||
<string name="subs_text_color">Couleur du texte</string>
|
||||
<string name="subs_outline_color">Couleur de la bordure exterieur</string>
|
||||
<string name="subs_background_color">Couleur de fond</string>
|
||||
<string name="subs_window_color">Couleur de la fenètre</string>
|
||||
<string name="subs_edge_type">Type de bordure</string>
|
||||
<string name="subs_subtitle_elevation">Élévation des sous-titres</string>
|
||||
<string name="preview_background_img_des">Aperçu de l\'arrière-plan</string>
|
||||
<string name="subs_font">Police</string>
|
||||
<string name="search_provider_text_providers">Rechercher en utilisant les fournisseurs</string>
|
||||
<string name="search_provider_text_types">Rechercher en utilisant les types</string>
|
||||
<string name="benene_count_text">%d Benenes données au dev</string>
|
||||
<string name="benene_count_text_none">Aucune Benenes donnée</string>
|
||||
<string name="subs_auto_select_language">Sélection automatique de la langue</string>
|
||||
<string name="subs_download_languages">Télécharger les langues</string>
|
||||
<string name="subs_hold_to_reset_to_default">Maintenir pour réinitialiser les valeurs par défaut</string>
|
||||
<string name="continue_watching">Continuer à regarder</string>
|
||||
<string name="action_remove_watching">Supprimer</string>
|
||||
<string name="action_open_watching">Plus d\'info</string>
|
||||
<string name="vpn_might_be_needed">Un VPN peut être requit pour que ce fournisseur fonctionne</string>
|
||||
<string name="vpn_torrent">Ce fournisseur est un torrent, un VPN est recommandé</string>
|
||||
<string name="torrent_plot">Description</string>
|
||||
<string name="normal_no_plot">Aucune description trouvée</string>
|
||||
<string name="torrent_no_plot">Aucune description trouvée</string>
|
||||
<string name="picture_in_picture">Lecteur en mode Picture-in-Picture</string>
|
||||
<string name="picture_in_picture_des">Continuer la lecture dans une fenêtre miniature en superposition sur d\'autres applis</string>
|
||||
<string name="player_size_settings">Bouton de redimensionnement du lecteur</string>
|
||||
<string name="player_size_settings_des">Supprimer les bordures noires</string>
|
||||
<string name="player_subtitles_settings">Sous-titres</string>
|
||||
<string name="player_subtitles_settings_des">Paramètres des sous-titres du lecteur</string>
|
||||
<string name="eigengraumode_settings">Vitesse de lecture</string>
|
||||
<string name="eigengraumode_settings_des">Ajouter l\'option de vitesse sur le lecteur</string>
|
||||
<string name="swipe_to_seek_settings">Balayer pour avancer rapidement</string>
|
||||
<string name="swipe_to_seek_settings_des">Balayer vers la gauche ou la droite pour contrôler le temps du lecteur vidéo</string>
|
||||
<string name="swipe_to_change_settings">Balayer pour changer les paramètres</string>
|
||||
<string name="swipe_to_change_settings_des">Balayer sur le coté droit ou gauche pour changer le niveau de luminosité ou de volume</string>
|
||||
<string name="double_tap_to_seek_settings">Taper deux fois pour rechercher</string>
|
||||
|
||||
<string name="double_tap_to_pause_settings">Taper deux fois pour mettre en pause</string>
|
||||
|
||||
<string name="double_tap_to_seek_settings_des">Taper deux fois sur le coté droit ou gauche pour avancer ou reculer</string>
|
||||
<string name="search">Rechercher</string>
|
||||
<string name="settings_info">Informations</string>
|
||||
<string name="advanced_search">Recherche Avancée</string>
|
||||
<string name="advanced_search_des">Donne les résultats séparés par les fournisseurs</string>
|
||||
<string name="bug_report_settings_off">N\'envoyer les données que lors d\'un crash</string>
|
||||
<string name="bug_report_settings_on">N\'envoyer aucune données</string>
|
||||
<string name="updates_settings">Afficher les mises-à-jour de l\'application</string>
|
||||
<string name="updates_settings_des">Chercher des mises-à-jour automatiquement au démarage</string>
|
||||
<string name="uprereleases_settings">Mettre à jour vers une version bêta</string>
|
||||
<string name="uprereleases_settings_des">Rechercher pour une mise à jour vers une version bêta au lieu des version complètes seulement</string>
|
||||
<string name="github">Github</string>
|
||||
<string name="lightnovel">L\'application Light Novel par les mêmes devs</string>
|
||||
<string name="anim">Application d\'animés par les mêmes devs</string>
|
||||
<string name="discord">Rejoindre le serveur Discord</string>
|
||||
<string name="benene">Donner une benene aux devs</string>
|
||||
<string name="benene_des">benenes données</string>
|
||||
<string name="app_language">Language de l\'application</string>
|
||||
|
@ -192,16 +138,12 @@
|
|||
<string name="primary_color_settings">Couleur principale</string>
|
||||
<string name="app_theme_settings">Thème de l\'application</string>
|
||||
<string name="player_speed_text_format" formatted="true">Vitesse (%.2fx)</string>
|
||||
<string name="use_system_brightness_settings">Utiliser la luminosité du système</string>
|
||||
<string name="category_general">Général</string>
|
||||
<string name="dns_pref">DNS avec HTTPS</string>
|
||||
<string name="display_subbed_dubbed_settings">Afficher les animés en Anglais (Dub) / sous-titrés</string>
|
||||
<string name="phone_layout">Disposition en mode téléphone</string>
|
||||
<string name="app_dub_sub_episode_text_format">%s Ep %d</string>
|
||||
<string name="rated_format" formatted="true">Note : %.1f</string>
|
||||
<string name="subs_font_size">Taille de la police</string>
|
||||
<string name="use_system_brightness_settings_des">Utiliser la luminosité du système dans le lecteur de l\'application au lieu d\'un écran noir</string>
|
||||
<string name="show_fillers_settings">Afficher les épisodes spéciaux pour les animés</string>
|
||||
<string name="resize_zoom">Zoom</string>
|
||||
<string name="resize_fit">Adapter à l\'écran</string>
|
||||
<string name="app_layout">Disposition de l\'application</string>
|
||||
|
@ -211,27 +153,8 @@
|
|||
<string name="automatic">Auto</string>
|
||||
<string name="cast_format">Acteurs: %s</string>
|
||||
<string name="duration_format">%d min</string>
|
||||
<string name="search_hint_site">Rechercher sur %s...</string>
|
||||
<string name="search_hint_site">Rechercher sur %s…</string>
|
||||
<string name="type_re_watching">À re-regarder</string>
|
||||
<string name="sort_copy">Copier</string>
|
||||
<string name="sort_close">Coller</string>
|
||||
<string name="sort_clear">Effacer</string>
|
||||
<string name="sort_save">Enregister</string>
|
||||
<string name="subs_import_text">Importer des polices en les plaçants dans %s</string>
|
||||
<string name="provider_info_meta">Les metadonnées ne sont pas fournies par le site, le chargement de la vidéo va échouer si elle n\'existe pas sur le site.</string>
|
||||
<string name="show_log_cat">Afficher les logs 🐈</string>
|
||||
<string name="chromecast_subtitles_settings">Sous-titres Chromecast</string>
|
||||
<string name="chromecast_subtitles_settings_des">Paramètres des sous-titres Chromecast</string>
|
||||
<string name="double_tap_to_pause_settings_des">Taper au milieu pour mettre en pause</string>
|
||||
<string name="episode_sync_settings">Mettre à jour la progression de visionnage</string>
|
||||
<string name="episode_sync_settings_des">Synchroniser automatiquement votre progression de l\'épisode actuel</string>
|
||||
<string name="restore_settings">Restaurer les données sauvegardées</string>
|
||||
<string name="backup_settings">Sauvegarder les données</string>
|
||||
<string name="restore_success">Fichier de sauvegarde chargé</string>
|
||||
<string name="restore_failed_format">Échec de la restauration des données depuis le fichier</string>
|
||||
<string name="backup_success">Restauration des données réussie</string>
|
||||
<string name="backup_failed">Permission d\'accès au stockage manquante</string>
|
||||
<string name="backup_failed_error_format">Erreur pendant la sauvegarde %s</string>
|
||||
<string name="no_episodes_found">Aucun épisode trouvé</string>
|
||||
<string name="documentaries">Documentaires</string>
|
||||
<string name="ova">OVA</string>
|
||||
|
@ -289,8 +212,117 @@
|
|||
<string name="actor_background">Arrière plan</string>
|
||||
<string name="home_source">Source</string>
|
||||
<string name="home_random">Aléatoire</string>
|
||||
<string name="coming_soon">À venir ...</string>
|
||||
<string name="coming_soon">À venir …</string>
|
||||
<string name="poster_image">Image de l\'affiche</string>
|
||||
<string name="authenticated_user">Connecté %s</string>
|
||||
<string name="action_add_to_bookmarks">Définir le statut de visionage</string>
|
||||
<string name="sort_copy">Copier</string>
|
||||
<string name="sort_close">Fermer</string>
|
||||
<string name="sort_clear">Vider</string>
|
||||
<string name="sort_save">Enregistrer</string>
|
||||
|
||||
|
||||
<string name="subtitles_settings">Paramètres des sous-titres</string>
|
||||
<string name="subs_text_color">Couleur du texte</string>
|
||||
<string name="subs_outline_color">Couleur des contours</string>
|
||||
<string name="subs_background_color">Couleur d\'arrière-plan</string>
|
||||
<string name="subs_window_color">Couleur de la fenêtre</string>
|
||||
<string name="subs_edge_type">Type de bordure</string>
|
||||
<string name="subs_subtitle_elevation">Elevation des sous-titres</string>
|
||||
<string name="subs_font">Police</string>
|
||||
<string name="subs_font_size">Taille de la police</string>
|
||||
|
||||
<string name="search_provider_text_providers">Recherche par fournisseur</string>
|
||||
<string name="search_provider_text_types">Recherche par types</string>
|
||||
|
||||
<string name="benene_count_text">%d Donner une banane aux devs</string>
|
||||
<string name="benene_count_text_none">Aucun Bananes donné</string>
|
||||
|
||||
<string name="subs_auto_select_language">Sélection automatique de la langue</string>
|
||||
<string name="subs_download_languages">Télécharger les langues</string>
|
||||
<string name="subs_subtitle_languages">Langue des sous-titres</string>
|
||||
<string name="subs_hold_to_reset_to_default">Maintenir pour rétablir les valeurs par défaut</string>
|
||||
<string name="subs_import_text" formatted="true">Importez des polices en les plaçant dans %s</string>
|
||||
<string name="continue_watching">Continuer à regarder</string>
|
||||
|
||||
<string name="action_remove_watching">Retirer</string>
|
||||
<string name="action_open_watching">Plus d\'informations</string>
|
||||
<string name="action_open_play">@string/home_play </string>
|
||||
|
||||
<string name="vpn_might_be_needed">Un VPN peut être nécessaire pour que ce fournisseur fonctionne correctement</string>
|
||||
<string name="vpn_torrent">Ce fournisseur est un torrent, un VPN est recommandé</string>
|
||||
|
||||
<string name="provider_info_meta">Les métadonnées ne sont pas fournies par le site, le chargement de la vidéo échouera si elles n\'existent pas sur le site.</string>
|
||||
|
||||
<string name="torrent_plot">Description</string>
|
||||
<string name="normal_no_plot">Aucune trace trouvée</string>
|
||||
<string name="torrent_no_plot">Aucune description trouvée</string>
|
||||
|
||||
<string name="show_log_cat">Afficher le logcat 🐈</string>
|
||||
|
||||
<string name="picture_in_picture">Picture-in-picture</string>
|
||||
<string name="picture_in_picture_des">Poursuite de la lecture dans un lecteur miniature au-dessus d\'autres applications</string>
|
||||
<string name="player_size_settings">Bouton de redimensionnement du lecteur</string>
|
||||
<string name="player_size_settings_des">Supprimer les bordures noires</string>
|
||||
<string name="player_subtitles_settings">Sous-titres</string>
|
||||
<string name="player_subtitles_settings_des">Paramètres des sous-titres du lecteur</string>
|
||||
<string name="chromecast_subtitles_settings">Sous-titres Chromecast</string>
|
||||
<string name="chromecast_subtitles_settings_des">Paramètres des sous-titres Chromecast</string>
|
||||
|
||||
<string name="eigengraumode_settings">Mode Eigengravy</string>
|
||||
<string name="eigengraumode_settings_des">Ajout d\'une option de vitesse dans le lecteur</string>
|
||||
<string name="swipe_to_seek_settings">Balayez pour chercher</string>
|
||||
<string name="swipe_to_seek_settings_des">Balayez vers la gauche ou la droite pour contrôler le temps dans le lecteur vidéo.</string>
|
||||
<string name="swipe_to_change_settings">Balayez pour modifier les paramètres</string>
|
||||
<string name="swipe_to_change_settings_des">Glissez sur le côté gauche ou droit pour modifier la luminosité ou le volume.</string>
|
||||
|
||||
<string name="autoplay_next_settings">Lecture automatique du prochain épisode</string>
|
||||
<string name="autoplay_next_settings_des">Démarrer l\'épisode suivant lorsque l\'épisode en cours se termine</string>
|
||||
|
||||
<string name="double_tap_to_seek_settings">Double tape pour chercher</string>
|
||||
<string name="double_tap_to_pause_settings">Double tape pour mettre en pause</string>
|
||||
<string name="double_tap_to_seek_amount_settings">Player seek amount</string>
|
||||
<string name="double_tap_to_seek_settings_des">Tapez deux fois sur le côté droit ou gauche pour aller en avant ou en arrière.
|
||||
</string>
|
||||
<string name="double_tap_to_pause_settings_des">Tapez au milieu pour mettre en pause</string>
|
||||
<string name="use_system_brightness_settings">Utiliser la luminosité du système</string>
|
||||
<string name="use_system_brightness_settings_des">Utiliser la luminosité du système dans le lecteur d\'applications au lieu du
|
||||
sombre
|
||||
</string>
|
||||
|
||||
<string name="episode_sync_settings">Mise à jour de la progression de la veille</string>
|
||||
<string name="episode_sync_settings_des">Synchronisation automatique de la progression de votre épisode en cours</string>
|
||||
|
||||
<string name="restore_settings">Restaurer des données à partir d\'une sauvegarde</string>
|
||||
|
||||
<string name="backup_settings">Sauvegarde des données</string>
|
||||
<string name="restore_success">Fichier de sauvegarde chargé</string>
|
||||
<string name="restore_failed_format" formatted="true">Échec de la restauration des données du fichier %s</string>
|
||||
<string name="backup_success">Données stockées avec succès</string>
|
||||
<string name="backup_failed">Permissions de stockage manquantes, veuillez réessayer</string>
|
||||
<string name="backup_failed_error_format">Erreur de sauvegarde %s</string>
|
||||
|
||||
<string name="search">Recherche</string>
|
||||
<string name="category_account">Comptes</string>
|
||||
<string name="category_updates">Mises à jour et sauvegarde</string>
|
||||
|
||||
<string name="settings_info">Info</string>
|
||||
<string name="advanced_search">Recherche avancée</string>
|
||||
<string name="advanced_search_des">Vous donne les résultats de la recherche séparés par fournisseur</string>
|
||||
<string name="bug_report_settings_off">Envoi de données uniquement en cas d\'accident</string>
|
||||
<string name="bug_report_settings_on">N\'envoie aucune donnée</string>
|
||||
<string name="show_fillers_settings">Afficher les épisodes spéciaux pour les animés</string>
|
||||
<string name="show_trailers_settings">Montrer les bandes-annonces</string>
|
||||
<string name="kitsu_settings">Montrer les affiches de kitsu</string>
|
||||
<string name="pref_filter_search_quality">Masquer la qualité vidéo sélectionnée dans les résultats de recherche</string>
|
||||
|
||||
<string name="automatic_plugin_updates">Mises à jour automatiques des plugins</string>
|
||||
<string name="updates_settings">Afficher les mises à jour de l\'application</string>
|
||||
<string name="updates_settings_des">Recherche automatique de nouvelles mises à jour au démarrage</string>
|
||||
<string name="uprereleases_settings">Mettre à jour vers une version bêta</string>
|
||||
<string name="uprereleases_settings_des">Recherche pour une mise à jour vers une version bêta au lieu des version complètes seulement</string>
|
||||
<string name="github">Github</string>
|
||||
<string name="lightnovel">Application Light Novel par les mêmes devs</string>
|
||||
<string name="anim">Anime app by the same devs</string>
|
||||
<string name="discord">Rejoignez le Discord</string>
|
||||
</resources>
|
||||
|
|
591
app/src/main/res/values-zh-rTW/strings.xml
Normal file
591
app/src/main/res/values-zh-rTW/strings.xml
Normal file
|
@ -0,0 +1,591 @@
|
|||
<!--https://newbedev.com/concatenate-multiple-strings-in-xml-->
|
||||
<resources>
|
||||
<!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG -->
|
||||
<string name="extra_info_format" formatted="true" translatable="false">%d %s | %s</string>
|
||||
<string name="storage_size_format" formatted="true" translatable="false">%s • %s</string>
|
||||
<string name="download_size_format" formatted="true" translatable="false">%s / %s</string>
|
||||
<string name="episode_name_format" formatted="true" translatable="false">%s %s</string>
|
||||
<string name="ffw_text_format" formatted="true" translatable="false">+%d</string>
|
||||
<string name="rew_text_format" formatted="true" translatable="false">-%d</string>
|
||||
<string name="ffw_text_regular_format" formatted="true" translatable="false">%d</string>
|
||||
<string name="rew_text_regular_format" formatted="true" translatable="false">%d</string>
|
||||
<string name="rating_format" formatted="true" translatable="false">%.1f/10.0</string>
|
||||
<string name="year_format" formatted="true" translatable="false">%d</string>
|
||||
<string name="app_dub_sub_episode_text_format" formatted="true">%s 共 %d 集</string>
|
||||
<string name="cast_format" formatted="true">演員:%s</string>
|
||||
<string name="next_episode_format" formatted="true">第 %d 集即將發佈於</string>
|
||||
<string name="next_episode_time_day_format" formatted="true">%dd %dh %dm</string>
|
||||
<string name="next_episode_time_hour_format" formatted="true">%dh %dm</string>
|
||||
<string name="next_episode_time_min_format" formatted="true">%dm</string>
|
||||
|
||||
<!-- IS NOT NEEDED TO TRANSLATE AS THEY ARE ONLY USED FOR SCREEN READERS AND WONT SHOW UP TO NORMAL USERS -->
|
||||
<string name="result_poster_img_des">封面</string>
|
||||
<string name="search_poster_img_des">@string/result_poster_img_des</string>
|
||||
<string name="episode_poster_img_des">劇集封面</string>
|
||||
<string name="home_main_poster_img_des">主封面</string>
|
||||
<string name="home_next_random_img_des">隨機下一個</string>
|
||||
<string name="episode_play_img_des" translatable="false">@string/play_episode</string>
|
||||
<string name="go_back_img_des">返回</string>
|
||||
<string name="change_providers_img_des" translatable="false">@string/home_change_provider_img_des</string>
|
||||
<string name="home_change_provider_img_des">更改片源</string>
|
||||
<string name="preview_background_img_des">預覽背景</string>
|
||||
|
||||
<!-- TRANSLATE, BUT DON'T FORGET FORMAT -->
|
||||
<string name="player_speed_text_format" formatted="true">速度(%.2fx)</string>
|
||||
<string name="rated_format" formatted="true">評分:%.1f</string>
|
||||
<string name="new_update_format" formatted="true">發現新版本!\n%s -> %s</string>
|
||||
<string name="filler" formatted="true">填充</string>
|
||||
<string name="duration_format" formatted="true">%d 分鐘</string>
|
||||
|
||||
<string name="app_name">CloudStream</string>
|
||||
<string name="play_with_app_name">使用 CloudStream 播放</string>
|
||||
<string name="title_home">主頁</string>
|
||||
<string name="title_search">搜尋</string>
|
||||
<string name="title_downloads">下載</string>
|
||||
<string name="title_settings">設定</string>
|
||||
|
||||
<string name="search_hint">搜尋…</string>
|
||||
<string name="search_hint_site" formatted="true">搜尋 %s…</string>
|
||||
|
||||
<string name="no_data">無資料</string>
|
||||
<string name="episode_more_options_des">更多選項</string>
|
||||
<string name="next_episode">下一集</string>
|
||||
<string name="result_plot" translatable="false">@string/synopsis</string>
|
||||
<string name="result_tags">類型</string>
|
||||
<string name="result_share">分享</string>
|
||||
<string name="result_open_in_browser">在瀏覽器中打開</string>
|
||||
<string name="skip_loading">跳過載入</string>
|
||||
<string name="loading">載入中…</string>
|
||||
|
||||
<string name="type_watching">正在觀看</string>
|
||||
<string name="type_on_hold">暫時擱置</string>
|
||||
<string name="type_completed">觀看完畢</string>
|
||||
<string name="type_dropped">放棄觀看</string>
|
||||
<string name="type_plan_to_watch">計畫觀看</string>
|
||||
<string name="type_none">無</string>
|
||||
<string name="type_re_watching">重新觀看</string>
|
||||
|
||||
<string name="play_movie_button">播放電影</string>
|
||||
<string name="play_livestream_button">播放直播</string>
|
||||
<string name="play_torrent_button">播放種子</string>
|
||||
<string name="pick_source">來源</string>
|
||||
<string name="pick_subtitle">字幕</string>
|
||||
<string name="reload_error">重試連接…</string>
|
||||
<string name="go_back">返回</string>
|
||||
<string name="play_episode">播放劇集</string>
|
||||
<!--<string name="need_storage">允許下載劇集</string>-->
|
||||
|
||||
<string name="download">下載</string>
|
||||
<string name="downloaded">已下載</string>
|
||||
<string name="downloading">下載中</string>
|
||||
<string name="download_paused">下載暫停</string>
|
||||
<string name="download_started">下載開始</string>
|
||||
<string name="download_failed">下載失敗</string>
|
||||
<string name="download_canceled">下載取消</string>
|
||||
<string name="download_done">下載完畢</string>
|
||||
<string name="download_format" translatable="false">%s - %s</string>
|
||||
<string name="stream">播放</string>
|
||||
|
||||
<string name="error_loading_links_toast">載入連結錯誤</string>
|
||||
<string name="download_storage_text">內部存儲</string>
|
||||
|
||||
<string name="app_dubbed_text">配音</string>
|
||||
<string name="app_subbed_text">字幕</string>
|
||||
|
||||
<string name="popup_delete_file">刪除檔案</string>
|
||||
<string name="popup_play_file">播放檔案</string>
|
||||
<string name="popup_resume_download">繼續下載</string>
|
||||
<string name="popup_pause_download">暫停下載</string>
|
||||
|
||||
<string name="pref_disable_acra">禁用自動錯誤報告</string>
|
||||
<string name="home_more_info">更多資訊</string>
|
||||
<string name="home_expanded_hide">隱藏</string>
|
||||
<string name="home_play">播放</string>
|
||||
<string name="home_info">資訊</string>
|
||||
<string name="filter_bookmarks">篩選書籤</string>
|
||||
<string name="error_bookmarks_text">書籤</string>
|
||||
<string name="action_remove_from_bookmarks">移除</string>
|
||||
<string name="action_add_to_bookmarks">設定觀看狀態</string>
|
||||
<string name="sort_apply">套用</string>
|
||||
<string name="sort_cancel">取消</string>
|
||||
<string name="sort_copy">複製</string>
|
||||
<string name="sort_close">關閉</string>
|
||||
<string name="sort_clear">清除</string>
|
||||
<string name="sort_save">保存</string>
|
||||
|
||||
<string name="player_speed">播放速度</string>
|
||||
|
||||
<string name="subtitles_settings">字幕設定</string>
|
||||
<string name="subs_text_color">字體顏色</string>
|
||||
<string name="subs_outline_color">輪廓顏色</string>
|
||||
<string name="subs_background_color">背景顏色</string>
|
||||
<string name="subs_window_color">視窗顏色</string>
|
||||
<string name="subs_edge_type">邊緣類型</string>
|
||||
<string name="subs_subtitle_elevation">字幕高度</string>
|
||||
<string name="subs_font">字體</string>
|
||||
<string name="subs_font_size">字體大小</string>
|
||||
|
||||
<string name="search_provider_text_providers">按片源搜尋</string>
|
||||
<string name="search_provider_text_types">按類型搜尋</string>
|
||||
|
||||
<string name="benene_count_text">送開發者 %d 根香蕉</string>
|
||||
<string name="benene_count_text_none">不送香蕉</string>
|
||||
|
||||
<string name="subs_auto_select_language">自動選擇語言</string>
|
||||
<string name="subs_download_languages">下載語言</string>
|
||||
<string name="subs_subtitle_languages">字幕語言</string>
|
||||
<string name="subs_hold_to_reset_to_default">按住重設為預設值</string>
|
||||
<string name="subs_import_text" formatted="true">將字體導入到 %s</string>
|
||||
<string name="continue_watching">繼續觀看</string>
|
||||
|
||||
<string name="action_remove_watching">移除</string>
|
||||
<string name="action_open_watching">更多資訊</string>
|
||||
<string name="action_open_play">@string/home_play </string>
|
||||
|
||||
<string name="vpn_might_be_needed">此片源可能需要 VPN 才能正常使用</string>
|
||||
<string name="vpn_torrent">此片源是種子,建議使用 VPN</string>
|
||||
|
||||
<string name="provider_info_meta">站點不提供元數據,如果站點上不存在元數據,影片載入將失敗。</string>
|
||||
|
||||
<string name="torrent_plot">簡介</string>
|
||||
<string name="normal_no_plot">未找到簡介</string>
|
||||
<string name="torrent_no_plot">未找到簡介</string>
|
||||
|
||||
<string name="show_log_cat">顯示 logcat 🐈</string>
|
||||
|
||||
<string name="picture_in_picture">字母畫面</string>
|
||||
<string name="picture_in_picture_des">在其他應用程式上的子母畫面中繼續播放</string>
|
||||
<string name="player_size_settings">播放器調整大小按鈕</string>
|
||||
<string name="player_size_settings_des">移除黑色邊框</string>
|
||||
<string name="player_subtitles_settings">字幕</string>
|
||||
<string name="player_subtitles_settings_des">播放器字幕設定</string>
|
||||
<string name="chromecast_subtitles_settings">Chromecast 字幕</string>
|
||||
<string name="chromecast_subtitles_settings_des">Chromecast 字幕設定</string>
|
||||
|
||||
<string name="eigengraumode_settings">播放速度</string>
|
||||
<string name="eigengraumode_settings_des">在播放器中添加播放速度選項</string>
|
||||
<string name="swipe_to_seek_settings">活動控制進度</string>
|
||||
<string name="swipe_to_seek_settings_des">左右滑動控制播放進度</string>
|
||||
<string name="swipe_to_change_settings">滑動更改設定</string>
|
||||
<string name="swipe_to_change_settings_des">上下滑動更改亮度或音量</string>
|
||||
|
||||
<string name="autoplay_next_settings">自動播放下一集</string>
|
||||
<string name="autoplay_next_settings_des">播放完畢後播放下一集</string>
|
||||
|
||||
<string name="double_tap_to_seek_settings">輕按兩下以控制進度</string>
|
||||
<string name="double_tap_to_pause_settings">輕按兩下以暫停</string>
|
||||
<string name="double_tap_to_seek_amount_settings">輕按兩下以控制進度時間</string>
|
||||
<string name="double_tap_to_seek_settings_des">在右側或左側輕按兩次以向前或向後快轉
|
||||
</string>
|
||||
<string name="double_tap_to_pause_settings_des">輕按兩下中間以暫停</string>
|
||||
<string name="use_system_brightness_settings">使用系統亮度</string>
|
||||
<string name="use_system_brightness_settings_des">在應用程序播放器中使用系統亮度替代黑色遮罩</string>
|
||||
|
||||
<string name="episode_sync_settings">更新觀看進度</string>
|
||||
<string name="episode_sync_settings_des">自動同步當前劇集進度</string>
|
||||
|
||||
<string name="restore_settings">從備份中恢復資料</string>
|
||||
|
||||
<string name="backup_settings">備份資料</string>
|
||||
<string name="restore_success">已載入備份資料</string>
|
||||
<string name="restore_failed_format" formatted="true">無法從 %s 檔案中還原資料</string>
|
||||
<string name="backup_success">成功儲存資料</string>
|
||||
<string name="backup_failed">缺少儲存權限,請重試</string>
|
||||
<string name="backup_failed_error_format">備份 %s 錯誤</string>
|
||||
|
||||
<string name="search">搜尋</string>
|
||||
<string name="category_account">帳號</string>
|
||||
<string name="category_updates">更新與備份</string>
|
||||
|
||||
<string name="settings_info">資訊</string>
|
||||
<string name="advanced_search">進階搜尋</string>
|
||||
<string name="advanced_search_des">為您提供按片源分開的搜尋結果</string>
|
||||
<string name="bug_report_settings_off">僅在崩潰時傳送資料</string>
|
||||
<string name="bug_report_settings_on">不傳送資料</string>
|
||||
<string name="show_fillers_settings">顯示動畫外傳</string>
|
||||
<string name="show_trailers_settings">顯示預告片</string>
|
||||
<string name="kitsu_settings">顯示來自 Kitsu 的封面</string>
|
||||
<string name="pref_filter_search_quality">在搜尋結果中隱藏選中的影片畫質</string>
|
||||
|
||||
<string name="automatic_plugin_updates">自動更新外掛程式</string>
|
||||
<string name="updates_settings">顯示應用更新</string>
|
||||
<string name="updates_settings_des">啟動時自動搜尋更新</string>
|
||||
<string name="uprereleases_settings">更新至預覽版</string>
|
||||
<string name="uprereleases_settings_des">搜尋預覽版更新而不是僅搜尋正式版</string>
|
||||
<string name="github">Github</string>
|
||||
<string name="lightnovel">由相同開發者開發的輕小說應用程式</string>
|
||||
<string name="anim">由相同開發者開發的動漫應用程式</string>
|
||||
<string name="discord">加入 Discord</string>
|
||||
<string name="benene">送開發者一根香蕉</string>
|
||||
<string name="benene_des">送香蕉</string>
|
||||
|
||||
<string name="app_language">應用程式語言</string>
|
||||
|
||||
<string name="no_chromecast_support_toast">此片源不支援 Chromecast</string>
|
||||
<string name="no_links_found_toast">未找到連結</string>
|
||||
<string name="copy_link_toast">連結已複製到剪貼簿</string>
|
||||
<string name="play_episode_toast">播放劇集</string>
|
||||
<string name="subs_default_reset_toast">重設為預設值</string>
|
||||
<string name="acra_report_toast">很抱歉,應用崩潰了,將傳送一份匿名錯誤報告給開發者</string>
|
||||
|
||||
<string name="season">季</string>
|
||||
<string name="season_format">%s %d%s</string>
|
||||
<string name="no_season">無季</string>
|
||||
<string name="episode">集</string>
|
||||
<string name="episodes">集</string>
|
||||
<string name="episodes_range">%d-%d</string>
|
||||
<string name="episode_format" formatted="true">%d %s</string>
|
||||
<string name="season_short">S</string>
|
||||
<string name="episode_short">E</string>
|
||||
<string name="no_episodes_found">未找到劇集</string>
|
||||
|
||||
<string name="delete_file">刪除文件</string>
|
||||
<string name="delete">刪除</string>
|
||||
<string name="cancel" translatable="false">@string/sort_cancel</string>
|
||||
<string name="pause">暫停</string>
|
||||
<string name="resume">繼續</string>
|
||||
<string name="go_back_30">-30</string>
|
||||
<string name="go_forward_30">+30</string>
|
||||
<string name="delete_message" formatted="true">這將永遠刪除 %s\n你確定嗎?</string>
|
||||
<string name="resume_time_left" formatted="true">剩餘 %d 分鐘</string>
|
||||
|
||||
|
||||
<string name="status_ongoing">連載中</string>
|
||||
<string name="status_completed">已完結</string>
|
||||
<string name="status">狀態</string>
|
||||
<string name="year">年份</string>
|
||||
<string name="rating">評分</string>
|
||||
<string name="duration">時間</string>
|
||||
<string name="site">網站</string>
|
||||
<string name="synopsis">簡介</string>
|
||||
|
||||
<string name="queued">已加入佇列</string>
|
||||
<string name="no_subtitles">無字幕</string>
|
||||
<string name="default_subtitles">預設</string>
|
||||
|
||||
<string name="free_storage">空閒</string>
|
||||
<string name="used_storage">已使用</string>
|
||||
<string name="app_storage">應用程式</string>
|
||||
|
||||
<!--plural-->
|
||||
<string name="movies">電影</string>
|
||||
<string name="tv_series">電視劇</string>
|
||||
<string name="cartoons">卡通</string>
|
||||
<string name="anime">動漫</string>
|
||||
<string name="torrent">種子</string>
|
||||
<string name="documentaries">紀錄片</string>
|
||||
<string name="ova">原創動畫錄影帶</string>
|
||||
<string name="asian_drama">亞洲劇</string>
|
||||
<string name="livestreams">直播</string>
|
||||
<string name="nsfw">NSFW</string>
|
||||
<string name="others">其他</string>
|
||||
|
||||
<!--singular-->
|
||||
<string name="movies_singular">電影</string>
|
||||
<string name="tv_series_singular">電視劇</string>
|
||||
<string name="cartoons_singular">卡通</string>
|
||||
<string name="anime_singular">@string/anime</string>
|
||||
<string name="ova_singular">@string/ova</string>
|
||||
<string name="torrent_singular">種子</string>
|
||||
<string name="documentaries_singular">紀錄片</string>
|
||||
<string name="asian_drama_singular">亞洲劇</string>
|
||||
<string name="live_singular">直播</string>
|
||||
<string name="nsfw_singular">NSFW</string>
|
||||
<string name="other_singular">其他</string>
|
||||
|
||||
<string name="source_error">來源錯誤</string>
|
||||
<string name="remote_error">遠端錯誤</string>
|
||||
<string name="render_error">渲染器錯誤</string>
|
||||
<string name="unexpected_error">意料之外的播放器錯誤</string>
|
||||
<string name="storage_error">下載錯誤,請檢查儲存權限</string>
|
||||
|
||||
<string name="episode_action_chromecast_episode">Chromecast 劇集</string>
|
||||
<string name="episode_action_chromecast_mirror">Chromecast 鏡像</string>
|
||||
<string name="episode_action_play_in_app">在應用程式中播放</string>
|
||||
<string name="episode_action_play_in_format">在 %s 中播放</string>
|
||||
<string name="episode_action_play_in_browser">在瀏覽器中播放</string>
|
||||
<string name="episode_action_copy_link">複製連結</string>
|
||||
<string name="episode_action_auto_download">自動下載</string>
|
||||
<string name="episode_action_download_mirror">下載鏡像</string>
|
||||
<string name="episode_action_reload_links">重新載入連結</string>
|
||||
<string name="episode_action_download_subtitle">下載字幕</string>
|
||||
|
||||
<string name="show_hd">畫質標籤</string>
|
||||
<string name="show_dub">配音標籤</string>
|
||||
<string name="show_sub">字幕標籤</string>
|
||||
<string name="show_title">標題</string>
|
||||
<string name="show_hd_key" translatable="false">show_hd_key</string>
|
||||
<string name="show_dub_key" translatable="false">show_dub_key</string>
|
||||
<string name="show_sub_key" translatable="false">show_sub_key</string>
|
||||
<string name="show_title_key" translatable="false">show_title_key</string>
|
||||
<string name="poster_ui_settings">封面內容</string>
|
||||
|
||||
<string name="no_update_found">未找到更新</string>
|
||||
<string name="check_for_update">检查更新</string>
|
||||
|
||||
<string name="video_lock">鎖定</string>
|
||||
<string name="video_aspect_ratio_resize">調整大小</string>
|
||||
<string name="video_source">來源</string>
|
||||
<string name="video_skip_op">跳過片頭</string>
|
||||
|
||||
<string name="dont_show_again">不再顯示</string>
|
||||
<string name="skip_update">跳過此更新</string>
|
||||
<string name="update">更新</string>
|
||||
<string name="watch_quality_pref">偏好播放畫質</string>
|
||||
<string name="limit_title">影片播放器標題最大字數</string>
|
||||
<string name="limit_title_rez">影片播放器標題</string>
|
||||
|
||||
<string name="video_buffer_size_settings">影片緩衝大小</string>
|
||||
<string name="video_buffer_length_settings">影片緩衝長度</string>
|
||||
<string name="video_buffer_disk_settings">影片快取存儲</string>
|
||||
<string name="video_buffer_clear_settings">清除影片和圖片快取</string>
|
||||
|
||||
<string name="video_ram_description">如果設定得太高會導致隨機崩潰。 如果您的記憶體不足(例如 Android TV 或舊手機),請不要更改</string>
|
||||
<string name="video_disk_description">如果您將其設定得太高,可能會導致儲存空間不足的系統(例如 Android TV 設備)出現問題</string>
|
||||
|
||||
<string name="dns_pref">DNS over HTTPS</string>
|
||||
<string name="dns_pref_summary">用於繞過網路服務供應商的封鎖</string>
|
||||
|
||||
<string name="add_site_pref">複製片源</string>
|
||||
<string name="remove_site_pref">移除片源</string>
|
||||
<string name="add_site_summary">添加具有不同URL的現有站點複製</string>
|
||||
|
||||
<string name="download_path_pref">下載路徑</string>
|
||||
|
||||
<string name="nginx_url_pref">Nginx 伺服器連結</string>
|
||||
|
||||
<string name="display_subbed_dubbed_settings">顯示有配音/字幕的動漫</string>
|
||||
|
||||
<string name="resize_fit">適應螢幕</string>
|
||||
<string name="resize_fill">拉伸</string>
|
||||
<string name="resize_zoom">縮放</string>
|
||||
|
||||
<string name="legal_notice">免責聲明</string>
|
||||
<string name="legal_notice_key" translatable="false">legal_notice_key</string>
|
||||
<string name="legal_notice_text" translatable="false">Any legal issues regarding the content on this application
|
||||
should be taken up with the actual file hosts and providers themselves as we are not affiliated with them.
|
||||
|
||||
In case of copyright infringement, please directly contact the responsible parties or the streaming websites.
|
||||
|
||||
The app is purely for educational and personal use.
|
||||
|
||||
CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down.
|
||||
CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or
|
||||
manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient,
|
||||
user-friendly interface.
|
||||
|
||||
It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the
|
||||
responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use
|
||||
CloudStream 3 at your own risk.
|
||||
</string>
|
||||
<string name="category_general">通用</string>
|
||||
<string name="random_button_settings">隨機按鈕</string>
|
||||
<string name="random_button_settings_desc">在主頁中顯示隨機按鈕</string>
|
||||
<string name="provider_lang_settings">片源語言</string>
|
||||
<string name="app_layout">應用佈局</string>
|
||||
<string name="preferred_media_settings">偏好類型</string>
|
||||
<string name="enable_nsfw_on_providers">在支援的片源中啟用 NSFW 內容</string>
|
||||
<string name="subtitles_encoding">字幕編碼</string>
|
||||
<string name="category_providers">片源</string>
|
||||
<string name="category_ui">佈局</string>
|
||||
|
||||
<string name="automatic">自動</string>
|
||||
<string name="tv_layout">電視佈局</string>
|
||||
<string name="phone_layout">手機佈局</string>
|
||||
<string name="emulator_layout">模擬器佈局</string>
|
||||
|
||||
<string name="primary_color_settings">主題色</string>
|
||||
<string name="app_theme_settings">應用程式主題</string>
|
||||
<string name="bottom_title_settings">封面標題位置</string>
|
||||
<string name="bottom_title_settings_des">將標題移到封面下方</string>
|
||||
|
||||
|
||||
<!-- account stuff -->
|
||||
<string name="anilist_key" translatable="false">anilist_key</string>
|
||||
<string name="mal_key" translatable="false">mal_key</string>
|
||||
<string name="opensubtitles_key" translatable="false">opensubtitles_key</string>
|
||||
<string name="nginx_key" translatable="false">nginx_key</string>
|
||||
<string name="example_password">密碼</string>
|
||||
<string name="example_username">用戶名</string>
|
||||
<string name="example_email">電子郵件</string>
|
||||
<string name="example_ip">IP</string>
|
||||
<string name="example_site_name">網站名稱</string>
|
||||
<string name="example_site_url">網站連結</string>
|
||||
<string name="example_lang_name">語言代號 (zh_TW)</string>
|
||||
|
||||
<!--
|
||||
<string name="mal_account_settings" translatable="false">MAL</string>
|
||||
<string name="anilist_account_settings" translatable="false">AniList</string>
|
||||
<string name="tmdb_account_settings" translatable="false">TMDB</string>
|
||||
<string name="imdb_account_settings" translatable="false">IMDB</string>
|
||||
<string name="kitsu_account_settings" translatable="false">Kitsu</string>
|
||||
<string name="trakt_account_settings" translatable="false">Trakt</string>
|
||||
-->
|
||||
<string name="login_format" formatted="true">%s %s</string>
|
||||
<string name="account">帳號</string>
|
||||
<string name="logout">登出</string>
|
||||
<string name="login">登入</string>
|
||||
<string name="switch_account">切換帳號</string>
|
||||
<string name="add_account">添加帳號</string>
|
||||
<string name="create_account">創建帳號</string>
|
||||
<string name="add_sync">添加同步</string>
|
||||
<string name="added_sync_format" formatted="true">已添加 %s</string>
|
||||
<string name="upload_sync">同步</string>
|
||||
<string name="sync_score">評分</string>
|
||||
<string name="sync_score_format" formatted="true">%d / 10</string>
|
||||
<string name="sync_total_episodes_none">/??</string>
|
||||
<string name="sync_total_episodes_some" formatted="true">/%d</string>
|
||||
<string name="authenticated_user" formatted="true">已驗證 %s</string>
|
||||
<string name="authenticated_user_fail" formatted="true">驗證 %s 失敗</string>
|
||||
|
||||
<!-- ============ -->
|
||||
<string name="none">無</string>
|
||||
<string name="normal">普通</string>
|
||||
<string name="all">全部</string>
|
||||
<string name="max">最大</string>
|
||||
<string name="min">最小</string>
|
||||
<string name="subtitles_none" translatable="false">@string/none</string>
|
||||
<string name="subtitles_outline">輪廓</string>
|
||||
<string name="subtitles_depressed">凹陷</string>
|
||||
<string name="subtitles_shadow">陰影</string>
|
||||
<string name="subtitles_raised">凸出</string>
|
||||
<string name="subtitle_offset">同步字幕</string>
|
||||
<string name="subtitle_offset_hint">1000ms</string>
|
||||
<string name="subtitle_offset_title">字幕延遲</string>
|
||||
<string name="subtitle_offset_extra_hint_later_format">如果字幕過早顯示 %dms ,請使用此選項</string>
|
||||
<string name="subtitle_offset_extra_hint_before_format">如果字幕過晚顯示 %dms ,請使用此選項</string>
|
||||
<string name="subtitle_offset_extra_hint_none_format">無字幕延遲</string>
|
||||
|
||||
<!--
|
||||
Example text (pangram) can optionally be translated; if you do, include all the letters in the alphabet,
|
||||
see:
|
||||
https://en.wikipedia.org/w/index.php?title=Pangram&oldid=225849300
|
||||
https://en.wikipedia.org/wiki/The_quick_brown_fox_jumps_over_the_lazy_dog
|
||||
-->
|
||||
<string name="subtitles_example_text">The quick brown fox jumps over the lazy dog</string>
|
||||
|
||||
<string name="recommended">推薦</string>
|
||||
<string name="player_loaded_subtitles" formatted="true">已載入 %s</string>
|
||||
<string name="player_load_subtitles">從檔案載入</string>
|
||||
<string name="player_load_subtitles_online">從網路載入</string>
|
||||
<string name="downloaded_file">下載的檔案</string>
|
||||
<string name="actor_main">主角</string>
|
||||
<string name="actor_supporting">配角</string>
|
||||
<string name="actor_background">群演</string>
|
||||
|
||||
<string name="home_source">來源</string>
|
||||
<string name="home_random">隨機</string>
|
||||
|
||||
<string name="coming_soon">即將到來…</string>
|
||||
|
||||
<string name="quality_cam">Cam</string>
|
||||
<string name="quality_cam_rip">Cam</string>
|
||||
<string name="quality_cam_hd">Cam</string>
|
||||
<string name="quality_hq">HQ</string>
|
||||
<string name="quality_hd">HD</string>
|
||||
<string name="quality_ts">TS</string>
|
||||
<string name="quality_tc">TC</string>
|
||||
<string name="quality_blueray">BlueRay</string>
|
||||
<string name="quality_workprint">WP</string>
|
||||
<string name="quality_dvd">DVD</string>
|
||||
<string name="quality_4k">4K</string>
|
||||
<string name="quality_sd">SD</string>
|
||||
<string name="quality_uhd">UHD</string>
|
||||
<string name="quality_hdr">HDR</string>
|
||||
<string name="quality_sdr">SDR</string>
|
||||
<string name="quality_webrip">Web</string>
|
||||
|
||||
<string name="poster_image">封面圖片</string>
|
||||
<string name="category_player">播放器</string>
|
||||
<string name="resolution_and_title">解析度與標題</string>
|
||||
<string name="title">標題</string>
|
||||
<string name="resolution">解析度</string>
|
||||
<string name="error_invalid_id">無效 ID</string>
|
||||
<string name="error_invalid_data">無效資料</string>
|
||||
<string name="error_invalid_url">無效連結</string>
|
||||
<string name="error">錯誤</string>
|
||||
<string name="subtitles_remove_captions">移除隱藏式字幕</string>
|
||||
<string name="subtitles_remove_bloat">移除字幕廣告</string>
|
||||
<string name="subtitles_filter_lang">按偏好片源語言過濾</string>
|
||||
<string name="extras">附加</string>
|
||||
<string name="trailer">預告片</string>
|
||||
<string name="network_adress_example">播放連結</string>
|
||||
<string name="referer">推薦</string>
|
||||
<string name="next">下一個</string>
|
||||
<string name="provider_languages_tip">觀看這些語言的影片</string>
|
||||
<string name="previous">上一個</string>
|
||||
<string name="skip_setup">跳過設定</string>
|
||||
<string name="app_layout_subtext">更改應用程式的外觀以適應你的設備</string>
|
||||
<string name="crash_reporting_title">崩潰報告</string>
|
||||
<string name="preferred_media_subtext">你想要看什麼</string>
|
||||
<string name="setup_done">完成</string>
|
||||
<string name="extensions">擴充功能</string>
|
||||
<string name="add_repository">添加資源庫</string>
|
||||
<string name="repository_name_hint">資源庫名稱</string>
|
||||
<string name="repository_url_hint">資源庫連結</string>
|
||||
<string name="plugin_loaded">外掛程式已載入</string>
|
||||
<string name="plugin_deleted">外掛程式已刪除</string>
|
||||
<string name="plugin_load_fail" formatted="true">載入 %s 失敗</string>
|
||||
<string name="is_adult">18+</string>
|
||||
<string name="batch_download_start_format" formatted="true">開始下載 %d %s</string>
|
||||
<string name="batch_download_finish_format" formatted="true">下載 %d %s 成功</string>
|
||||
<string name="batch_download_nothing_to_download_format" formatted="true">全部 %s 已經下載</string>
|
||||
<string name="batch_download">批次下載</string>
|
||||
<string name="plugin_singular">外掛程式</string>
|
||||
<string name="plugin">外掛程式</string>
|
||||
<string name="delete_repository_plugins">這也將刪除所有資源庫外掛程式</string>
|
||||
<string name="delete_repository">刪除資源庫</string>
|
||||
<string name="setup_extensions_subtext">下載你所需的片源</string>
|
||||
<string name="plugins_downloaded" formatted="true">已下載:%d</string>
|
||||
<string name="plugins_disabled" formatted="true">已禁用:%d</string>
|
||||
<string name="plugins_not_downloaded" formatted="true">未下載:%d</string>
|
||||
<string name="plugins_updated" formatted="true">已更新 %d 外掛程式</string>
|
||||
<string name="blank_repo_message">CloudStream 預設沒有安裝任何片源。您需要從資源庫安裝站點。\n\n由於 Sky Uk Limited 的無腦 DMCA 刪除🤮,我們無法在應用程式中連結資源庫站點。\n\n加入我們的 Discord 獲得連結或自己在網路上搜尋</string>
|
||||
<string name="view_public_repositories_button">查看</string>
|
||||
<string name="view_public_repositories_button_short">公開列表</string>
|
||||
<string name="uppercase_all_subtitles">字幕全大寫</string>
|
||||
|
||||
<string name="download_all_plugins_from_repo">從此資源庫下載所有外掛程式?</string>
|
||||
<string name="single_plugin_disabled" formatted="true">%s (禁用)</string>
|
||||
<string name="tracks">軌道</string>
|
||||
<string name="audio_tracks">音頻軌道</string>
|
||||
<string name="video_tracks">影片軌道</string>
|
||||
<string name="apply_on_restart">重新啟動時生效</string>
|
||||
|
||||
<string name="safe_mode_title">安全模式已啟用</string>
|
||||
<string name="safe_mode_description">發生了不可恢復的崩潰,我們已自動禁用所有外掛程式,因此您可以找到並刪除導致問題的應用程式。</string>
|
||||
<string name="safe_mode_crash_info">查看崩潰資訊</string>
|
||||
|
||||
<string name="extension_rating" formatted="true">評分:%s</string>
|
||||
<string name="extension_description">簡介</string>
|
||||
<string name="extension_version">版本</string>
|
||||
<string name="extension_status">狀態</string>
|
||||
<string name="extension_size">大小</string>
|
||||
<string name="extension_authors">作者</string>
|
||||
<string name="extension_types">類型</string>
|
||||
<string name="extension_language">語言</string>
|
||||
<string name="extension_install_first">請先安裝外掛程式</string>
|
||||
|
||||
<string name="hls_playlist">HLS 播放清單</string>
|
||||
|
||||
<string name="player_pref">偏好影片播放器</string>
|
||||
<string name="player_settings_play_in_app">內部播放器</string>
|
||||
<string name="player_settings_play_in_vlc">VLC</string>
|
||||
<string name="player_settings_play_in_mpv">MPV</string>
|
||||
<string name="player_settings_play_in_web">網路影片播放</string>
|
||||
<string name="player_settings_play_in_browser">瀏覽器</string>
|
||||
<string name="app_not_found_error">未找到應用</string>
|
||||
<string name="all_languages_preference">所有語言</string>
|
||||
|
||||
<string name="skip_type_format" formatted="true">跳過 %s</string>
|
||||
<string name="skip_type_op">片頭</string>
|
||||
<string name="skip_type_ed">片尾</string>
|
||||
<string name="skip_type_recap">前情回顧</string>
|
||||
<string name="skip_type_mixed_ed">混合片尾</string>
|
||||
<string name="skip_type_mixed_op">混合片頭</string>
|
||||
<string name="skip_type_creddits">致謝名單</string>
|
||||
<string name="skip_type_intro">介紹</string>
|
||||
|
||||
<string name="clear_history">清除歷史紀錄</string>
|
||||
<string name="history">歷史紀錄</string>
|
||||
</resources>
|
|
@ -209,6 +209,7 @@
|
|||
<string name="pref_filter_search_quality">在搜索结果中隐藏选中视频画质</string>
|
||||
|
||||
<string name="automatic_plugin_updates">自动更新插件</string>
|
||||
<string name="automatic_plugin_download">自动下载插件</string>
|
||||
<string name="updates_settings">显示应用更新</string>
|
||||
<string name="updates_settings_des">启动时自动搜索更新</string>
|
||||
<string name="uprereleases_settings">更新至预览版</string>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<string name="search_types_list_key" translatable="false">search_type_list</string>
|
||||
<string name="auto_update_key" translatable="false">auto_update</string>
|
||||
<string name="auto_update_plugins_key" translatable="false">auto_update_plugins</string>
|
||||
<string name="auto_download_plugins_key" translatable="false">auto_download_plugins_key</string>
|
||||
<string name="skip_update_key" translatable="false">skip_update_key</string>
|
||||
<string name="prerelease_update_key" translatable="false">prerelease_update</string>
|
||||
<string name="manual_check_update_key" translatable="false">manual_check_update</string>
|
||||
|
@ -269,6 +270,7 @@
|
|||
<string name="pref_filter_search_quality">Hide selected video quality on Search results</string>
|
||||
|
||||
<string name="automatic_plugin_updates">Automatic plugin updates</string>
|
||||
<string name="automatic_plugin_download">Automatically download plugins</string>
|
||||
<string name="updates_settings">Show app updates</string>
|
||||
<string name="updates_settings_des">Automatically search for new updates on start</string>
|
||||
<string name="uprereleases_settings">Update to prereleases</string>
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
android:icon="@drawable/ic_baseline_extension_24"
|
||||
android:key="@string/auto_update_plugins_key"
|
||||
android:title="@string/automatic_plugin_updates" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_baseline_extension_24"
|
||||
android:key="@string/auto_download_plugins_key"
|
||||
android:title="@string/automatic_plugin_download" />
|
||||
<SwitchPreference
|
||||
android:icon="@drawable/ic_baseline_notifications_active_24"
|
||||
android:summary="@string/updates_settings_des"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue