mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2026-03-28 02:29:43 +00:00
Compare commits
63 Commits
getQuantit
...
weblate
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da76ddbf19 | ||
|
|
75ba70ab41 | ||
|
|
6d50fe79b8 | ||
|
|
f8c9ab8b11 | ||
|
|
949f0f3448 | ||
|
|
af08ddcf04 | ||
|
|
09c96159d1 | ||
|
|
2dda39205d | ||
|
|
3112eefb99 | ||
|
|
cf0d7016ec | ||
|
|
b0f2d509e6 | ||
|
|
db61af15e8 | ||
|
|
80a47be218 | ||
|
|
179a713561 | ||
|
|
fa6412a9aa | ||
|
|
3f8d26d33e | ||
|
|
2fec3a3c58 | ||
|
|
08326c64cb | ||
|
|
831425a742 | ||
|
|
fbf3b7a905 | ||
|
|
515bb6e94d | ||
|
|
349000857a | ||
|
|
f1c608b396 | ||
|
|
5f1a270ca4 | ||
|
|
aba2a385fd | ||
|
|
71a3bf2855 | ||
|
|
ebb937934a | ||
|
|
223b240299 | ||
|
|
668af4fc3e | ||
|
|
bfcc31ec89 | ||
|
|
6fa97e17f5 | ||
|
|
0d65733e53 | ||
|
|
9cc6f9fd68 | ||
|
|
79767f95f7 | ||
|
|
21b37b5fa4 | ||
|
|
675d15686d | ||
|
|
54021a96ea | ||
|
|
7c88f06196 | ||
|
|
93f9a52e3e | ||
|
|
d9fd1bf003 | ||
|
|
dc2e4aaea5 | ||
|
|
d5f941ff3d | ||
|
|
05f09c94d1 | ||
|
|
816f5f9aba | ||
|
|
47624a575a | ||
|
|
3b3348e7a1 | ||
|
|
521f60af85 | ||
|
|
d497f1d88e | ||
|
|
dda219a9e9 | ||
|
|
b8ec9bf412 | ||
|
|
e173bf4252 | ||
|
|
9f45aa571c | ||
|
|
e6e5fc70f2 | ||
|
|
8fa6f9670d | ||
|
|
0cdf40cd5f | ||
|
|
0020a02a28 | ||
|
|
1fbf9fc025 | ||
|
|
8b500c7b83 | ||
|
|
98a883d377 | ||
|
|
6dddcf3805 | ||
|
|
bf1633265c | ||
|
|
e358867da8 | ||
|
|
e6daf45c83 |
@@ -11,6 +11,7 @@ plugins {
|
||||
alias(libs.plugins.jetbrains.kotlin.kapt)
|
||||
alias(libs.plugins.google.ksp)
|
||||
alias(libs.plugins.jetbrains.kotlin.parcelize)
|
||||
alias(libs.plugins.jetbrains.kotlinx.serialization)
|
||||
alias(libs.plugins.sonarqube)
|
||||
checkstyle
|
||||
}
|
||||
@@ -44,9 +45,9 @@ configure<ApplicationExtension> {
|
||||
minSdk = 21
|
||||
targetSdk = 35
|
||||
|
||||
versionCode = System.getProperty("versionCodeOverride")?.toInt() ?: 1008
|
||||
versionCode = System.getProperty("versionCodeOverride")?.toInt() ?: 1009
|
||||
|
||||
versionName = "0.28.3"
|
||||
versionName = "0.28.4"
|
||||
System.getProperty("versionNameSuffix")?.let { versionNameSuffix = it }
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
@@ -246,6 +247,12 @@ dependencies {
|
||||
implementation(libs.google.android.material)
|
||||
implementation(libs.androidx.webkit)
|
||||
|
||||
// Coroutines interop
|
||||
implementation(libs.kotlinx.coroutines.rx3)
|
||||
|
||||
// Kotlinx Serialization
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
|
||||
/** Third-party libraries **/
|
||||
implementation(libs.livefront.bridge)
|
||||
implementation(libs.evernote.statesaver.core)
|
||||
|
||||
15
app/proguard-rules.pro
vendored
15
app/proguard-rules.pro
vendored
@@ -44,3 +44,18 @@
|
||||
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
|
||||
<fields>;
|
||||
}
|
||||
|
||||
## Keep Kotlinx Serialization classes
|
||||
-keepclassmembers class kotlinx.serialization.json.** {
|
||||
*** Companion;
|
||||
}
|
||||
-keepclasseswithmembers class kotlinx.serialization.json.** {
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
||||
-keep,includedescriptorclasses class org.schabi.newpipe.**$$serializer { *; }
|
||||
-keepclassmembers class org.schabi.newpipe.** {
|
||||
*** Companion;
|
||||
}
|
||||
-keepclasseswithmembers class org.schabi.newpipe.** {
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
||||
|
||||
@@ -96,14 +96,6 @@
|
||||
android:exported="false"
|
||||
android:label="@string/title_activity_about" />
|
||||
|
||||
<service
|
||||
android:name=".local.subscription.services.SubscriptionsImportService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
|
||||
<service
|
||||
android:name=".local.subscription.services.SubscriptionsExportService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
|
||||
<service
|
||||
android:name=".local.feed.service.FeedLoadService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -996,19 +995,18 @@ public class MainActivity extends AppCompatActivity {
|
||||
"pt", "cs", "sk", "fa", "ar", "tr", "el", "th", "ru", "uk", "ko", "zh", "ja");
|
||||
final var locale = Localization.getAppLocale();
|
||||
final String kaoBaseUrl = "https://keepandroidopen.org/";
|
||||
final String kaoURIString;
|
||||
final String kaoURI;
|
||||
if (supportedLannguages.contains(locale.getLanguage())) {
|
||||
if ("zh".equals(locale.getLanguage())) {
|
||||
kaoURIString = kaoBaseUrl + ("TW".equals(locale.getCountry()) ? "zh-TW" : "zh-CN");
|
||||
kaoURI = kaoBaseUrl + ("TW".equals(locale.getCountry()) ? "zh-TW" : "zh-CN");
|
||||
} else {
|
||||
kaoURIString = kaoBaseUrl + locale.getLanguage();
|
||||
kaoURI = kaoBaseUrl + locale.getLanguage();
|
||||
}
|
||||
} else {
|
||||
kaoURIString = kaoBaseUrl;
|
||||
kaoURI = kaoBaseUrl;
|
||||
}
|
||||
final var kaoURI = Uri.parse(kaoURIString);
|
||||
final var solutionURI = Uri.parse(
|
||||
"https://github.com/woheller69/FreeDroidWarn?tab=readme-ov-file#solutions");
|
||||
final var solutionURI =
|
||||
"https://github.com/woheller69/FreeDroidWarn?tab=readme-ov-file#solutions";
|
||||
|
||||
if (kaoLastCheck.plus(30, ChronoUnit.DAYS).isBefore(now)) {
|
||||
final var dialog = new AlertDialog.Builder(this)
|
||||
@@ -1030,10 +1028,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
// If we use setNeutralButton and etc. dialog will close after pressing the buttons,
|
||||
// but we want it to close only when positive button is pressed
|
||||
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(v ->
|
||||
this.startActivity(new Intent(Intent.ACTION_VIEW, kaoURI))
|
||||
ShareUtils.openUrlInBrowser(this, kaoURI)
|
||||
);
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(v ->
|
||||
this.startActivity(new Intent(Intent.ACTION_VIEW, solutionURI))
|
||||
ShareUtils.openUrlInBrowser(this, solutionURI)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,13 +254,6 @@ class AboutActivity : AppCompatActivity() {
|
||||
"ByteHamster",
|
||||
"https://github.com/ByteHamster/SearchPreference",
|
||||
StandardLicenses.MIT
|
||||
),
|
||||
SoftwareComponent(
|
||||
"FreeDroidWarn",
|
||||
"2026",
|
||||
"woheller69",
|
||||
"https://github.com/woheller69/FreeDroidWarn",
|
||||
StandardLicenses.APACHE2
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.schabi.newpipe.databinding.ActivityErrorBinding
|
||||
import org.schabi.newpipe.util.Localization
|
||||
import org.schabi.newpipe.util.ThemeHelper
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
import org.schabi.newpipe.util.text.setTextWithLinks
|
||||
|
||||
/**
|
||||
* This activity is used to show error details and allow reporting them in various ways.
|
||||
@@ -100,7 +101,7 @@ class ErrorActivity : AppCompatActivity() {
|
||||
|
||||
// normal bugreport
|
||||
buildInfo(errorInfo)
|
||||
binding.errorMessageView.text = errorInfo.getMessage(this)
|
||||
binding.errorMessageView.setTextWithLinks(errorInfo.getMessage(this))
|
||||
binding.errorView.text = formErrorText(errorInfo.stackTraces)
|
||||
|
||||
// print stack trace once again for debugging:
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentExcepti
|
||||
import org.schabi.newpipe.ktx.isNetworkRelated
|
||||
import org.schabi.newpipe.player.mediasource.FailedMediaSource
|
||||
import org.schabi.newpipe.player.resolver.PlaybackResolver
|
||||
import org.schabi.newpipe.util.text.getText
|
||||
|
||||
/**
|
||||
* An error has occurred in the app. This class contains plain old parcelable data that can be used
|
||||
@@ -135,8 +136,8 @@ class ErrorInfo private constructor(
|
||||
return getServiceName(serviceId)
|
||||
}
|
||||
|
||||
fun getMessage(context: Context): String {
|
||||
return message.getString(context)
|
||||
fun getMessage(context: Context): CharSequence {
|
||||
return message.getText(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -146,20 +147,23 @@ class ErrorInfo private constructor(
|
||||
private val stringRes: Int,
|
||||
private vararg val formatArgs: String
|
||||
) : Parcelable {
|
||||
fun getString(context: Context): String {
|
||||
fun getText(context: Context): CharSequence {
|
||||
// Ensure locale aware context via ContextCompat.getContextForLanguage() (just in case context is not AppCompatActivity)
|
||||
val ctx = ContextCompat.getContextForLanguage(context)
|
||||
return if (formatArgs.isEmpty()) {
|
||||
// use ContextCompat.getString() just in case context is not AppCompatActivity
|
||||
ContextCompat.getString(context, stringRes)
|
||||
ctx.getText(stringRes)
|
||||
} else {
|
||||
// ContextCompat.getString() with formatArgs does not exist, so we just
|
||||
// replicate its source code but with formatArgs
|
||||
ContextCompat.getContextForLanguage(context).getString(stringRes, *formatArgs)
|
||||
ctx.resources.getText(stringRes, *formatArgs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val SERVICE_NONE = "<unknown_service>"
|
||||
|
||||
const val YOUTUBE_IP_BAN_FAQ_URL = "https://newpipe.net/FAQ/#ip-banned-youtube"
|
||||
|
||||
private fun getServiceName(serviceId: Int?) = // not using getNameOfServiceById since we want to accept a nullable serviceId and we
|
||||
// want to default to SERVICE_NONE
|
||||
ServiceList.all().firstOrNull { it.serviceId == serviceId }?.serviceInfo?.name
|
||||
@@ -247,7 +251,11 @@ class ErrorInfo private constructor(
|
||||
ErrorMessage(R.string.youtube_music_premium_content)
|
||||
|
||||
throwable is SignInConfirmNotBotException ->
|
||||
ErrorMessage(R.string.sign_in_confirm_not_bot_error, getServiceName(serviceId))
|
||||
ErrorMessage(
|
||||
R.string.sign_in_confirm_not_bot_error,
|
||||
getServiceName(serviceId),
|
||||
YOUTUBE_IP_BAN_FAQ_URL
|
||||
)
|
||||
|
||||
throwable is ContentNotAvailableException ->
|
||||
ErrorMessage(R.string.content_not_available)
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.schabi.newpipe.MainActivity
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.ktx.animate
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
import org.schabi.newpipe.util.text.setTextWithLinks
|
||||
|
||||
class ErrorPanelHelper(
|
||||
private val fragment: Fragment,
|
||||
@@ -64,7 +65,7 @@ class ErrorPanelHelper(
|
||||
|
||||
fun showError(errorInfo: ErrorInfo) {
|
||||
ensureDefaultVisibility()
|
||||
errorTextView.text = errorInfo.getMessage(context)
|
||||
errorTextView.setTextWithLinks(errorInfo.getMessage(context))
|
||||
|
||||
if (errorInfo.recaptchaUrl != null) {
|
||||
showAndSetErrorButtonAction(R.string.recaptcha_solve) {
|
||||
@@ -109,7 +110,7 @@ class ErrorPanelHelper(
|
||||
fun showTextError(errorString: String) {
|
||||
ensureDefaultVisibility()
|
||||
|
||||
errorTextView.text = errorString
|
||||
errorTextView.setTextWithLinks(errorString)
|
||||
|
||||
setRootVisible()
|
||||
}
|
||||
|
||||
@@ -216,9 +216,9 @@ public abstract class BaseDescriptionFragment extends BaseFragment {
|
||||
|| image.getWidth() != Image.WIDTH_UNKNOWN
|
||||
// if even the resolution level is unknown, ?x? will be shown
|
||||
|| image.getEstimatedResolutionLevel() == Image.ResolutionLevel.UNKNOWN) {
|
||||
urls.append(imageSizeToText(image.getHeight()));
|
||||
urls.append('x');
|
||||
urls.append(imageSizeToText(image.getWidth()));
|
||||
urls.append('x');
|
||||
urls.append(imageSizeToText(image.getHeight()));
|
||||
} else {
|
||||
switch (image.getEstimatedResolutionLevel()) {
|
||||
case LOW -> urls.append(getString(R.string.image_quality_low));
|
||||
|
||||
@@ -1,41 +1,63 @@
|
||||
package org.schabi.newpipe.local.subscription;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.os.BundleCompat;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.work.Constraints;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import androidx.work.NetworkType;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.OutOfQuotaPolicy;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
import com.livefront.bridge.Bridge;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionImportInput;
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionImportWorker;
|
||||
|
||||
public class ImportConfirmationDialog extends DialogFragment {
|
||||
protected Intent resultServiceIntent;
|
||||
private static final String EXTRA_RESULT_SERVICE_INTENT = "extra_result_service_intent";
|
||||
private static final String INPUT = "input";
|
||||
|
||||
public static void show(@NonNull final Fragment fragment,
|
||||
@NonNull final Intent resultServiceIntent) {
|
||||
final ImportConfirmationDialog confirmationDialog = new ImportConfirmationDialog();
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_RESULT_SERVICE_INTENT, resultServiceIntent);
|
||||
confirmationDialog.setArguments(args);
|
||||
public static void show(@NonNull final Fragment fragment, final SubscriptionImportInput input) {
|
||||
final var confirmationDialog = new ImportConfirmationDialog();
|
||||
final var arguments = new Bundle();
|
||||
arguments.putParcelable(INPUT, input);
|
||||
confirmationDialog.setArguments(arguments);
|
||||
confirmationDialog.show(fragment.getParentFragmentManager(), null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(requireContext())
|
||||
final var context = requireContext();
|
||||
return new AlertDialog.Builder(context)
|
||||
.setMessage(R.string.import_network_expensive_warning)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
||||
requireContext().startService(resultServiceIntent);
|
||||
final var constraints = new Constraints.Builder()
|
||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||
.build();
|
||||
final var input = BundleCompat.getParcelable(requireArguments(), INPUT,
|
||||
SubscriptionImportInput.class);
|
||||
|
||||
final var req = new OneTimeWorkRequest.Builder(SubscriptionImportWorker.class)
|
||||
.setInputData(input.toData())
|
||||
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
|
||||
.setConstraints(constraints)
|
||||
.build();
|
||||
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniqueWork(SubscriptionImportWorker.WORK_NAME,
|
||||
ExistingWorkPolicy.APPEND_OR_REPLACE, req);
|
||||
|
||||
dismiss();
|
||||
})
|
||||
.create();
|
||||
@@ -45,7 +67,7 @@ public class ImportConfirmationDialog extends DialogFragment {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
resultServiceIntent = requireArguments().getParcelable(EXTRA_RESULT_SERVICE_INTENT);
|
||||
Bridge.restoreInstanceState(this, savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package org.schabi.newpipe.local.subscription
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.view.LayoutInflater
|
||||
@@ -15,8 +13,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.MimeTypeMap
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
@@ -27,9 +23,6 @@ import com.xwray.groupie.GroupAdapter
|
||||
import com.xwray.groupie.Section
|
||||
import com.xwray.groupie.viewbinding.GroupieViewHolder
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity.Companion.GROUP_ALL_ID
|
||||
import org.schabi.newpipe.databinding.DialogTitleBinding
|
||||
@@ -53,13 +46,6 @@ import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem
|
||||
import org.schabi.newpipe.local.subscription.item.GroupsHeader
|
||||
import org.schabi.newpipe.local.subscription.item.Header
|
||||
import org.schabi.newpipe.local.subscription.item.ImportSubscriptionsHintPlaceholderItem
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||
import org.schabi.newpipe.util.NavigationHelper
|
||||
import org.schabi.newpipe.util.OnClickGesture
|
||||
import org.schabi.newpipe.util.ServiceHelper
|
||||
@@ -72,6 +58,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
|
||||
private lateinit var viewModel: SubscriptionViewModel
|
||||
private lateinit var subscriptionManager: SubscriptionManager
|
||||
private lateinit var importExportHelper: SubscriptionsImportExportHelper
|
||||
private val disposables: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private val groupAdapter = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
|
||||
@@ -80,11 +67,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
private lateinit var feedGroupsSortMenuItem: GroupsHeader
|
||||
private val subscriptionsSection = Section()
|
||||
|
||||
private val requestExportLauncher =
|
||||
registerForActivityResult(StartActivityForResult(), this::requestExportResult)
|
||||
private val requestImportLauncher =
|
||||
registerForActivityResult(StartActivityForResult(), this::requestImportResult)
|
||||
|
||||
@State
|
||||
@JvmField
|
||||
var itemsListState: Parcelable? = null
|
||||
@@ -104,6 +86,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
subscriptionManager = SubscriptionManager(requireContext())
|
||||
importExportHelper = SubscriptionsImportExportHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
@@ -143,7 +126,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
// -- Import --
|
||||
val importSubMenu = menu.addSubMenu(R.string.import_from)
|
||||
|
||||
addMenuItemToSubmenu(importSubMenu, R.string.previous_export) { onImportPreviousSelected() }
|
||||
addMenuItemToSubmenu(importSubMenu, R.string.previous_export) { importExportHelper.onImportPreviousSelected() }
|
||||
.setIcon(R.drawable.ic_backup)
|
||||
|
||||
for (service in ServiceList.all()) {
|
||||
@@ -161,7 +144,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
// -- Export --
|
||||
val exportSubMenu = menu.addSubMenu(R.string.export_to)
|
||||
|
||||
addMenuItemToSubmenu(exportSubMenu, R.string.file) { onExportSelected() }
|
||||
addMenuItemToSubmenu(exportSubMenu, R.string.file) { importExportHelper.onExportSelected() }
|
||||
.setIcon(R.drawable.ic_save)
|
||||
}
|
||||
|
||||
@@ -197,51 +180,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
NavigationHelper.openSubscriptionsImportFragment(fragmentManager, serviceId)
|
||||
}
|
||||
|
||||
private fun onImportPreviousSelected() {
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestImportLauncher,
|
||||
StoredFileHelper.getPicker(activity, JSON_MIME_TYPE),
|
||||
TAG,
|
||||
requireContext()
|
||||
)
|
||||
}
|
||||
|
||||
private fun onExportSelected() {
|
||||
val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date())
|
||||
val exportName = "newpipe_subscriptions_$date.json"
|
||||
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestExportLauncher,
|
||||
StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null),
|
||||
TAG,
|
||||
requireContext()
|
||||
)
|
||||
}
|
||||
|
||||
private fun openReorderDialog() {
|
||||
FeedGroupReorderDialog().show(parentFragmentManager, null)
|
||||
}
|
||||
|
||||
private fun requestExportResult(result: ActivityResult) {
|
||||
if (result.data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
activity.startService(
|
||||
Intent(activity, SubscriptionsExportService::class.java)
|
||||
.putExtra(SubscriptionsExportService.KEY_FILE_PATH, result.data?.data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestImportResult(result: ActivityResult) {
|
||||
if (result.data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
ImportConfirmationDialog.show(
|
||||
this,
|
||||
Intent(activity, SubscriptionsImportService::class.java)
|
||||
.putExtra(KEY_MODE, PREVIOUS_EXPORT_MODE)
|
||||
.putExtra(KEY_VALUE, result.data?.data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// Fragment Views
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.schabi.newpipe.local.subscription
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Pair
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
@@ -51,23 +50,16 @@ class SubscriptionManager(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun upsertAll(infoList: List<Pair<ChannelInfo, List<ChannelTabInfo>>>): List<SubscriptionEntity> {
|
||||
val listEntities = subscriptionTable.upsertAll(
|
||||
infoList.map { SubscriptionEntity.from(it.first) }
|
||||
)
|
||||
fun upsertAll(infoList: List<Pair<ChannelInfo, ChannelTabInfo>>) {
|
||||
val listEntities = infoList.map { SubscriptionEntity.from(it.first) }
|
||||
subscriptionTable.upsertAll(listEntities)
|
||||
|
||||
database.runInTransaction {
|
||||
infoList.forEachIndexed { index, info ->
|
||||
info.second.forEach {
|
||||
feedDatabaseManager.upsertAll(
|
||||
listEntities[index].uid,
|
||||
it.relatedItems.filterIsInstance<StreamInfoItem>()
|
||||
)
|
||||
}
|
||||
val streams = info.second.relatedItems.filterIsInstance<StreamInfoItem>()
|
||||
feedDatabaseManager.upsertAll(listEntities[index].uid, streams)
|
||||
}
|
||||
}
|
||||
|
||||
return listEntities
|
||||
}
|
||||
|
||||
fun updateChannelInfo(info: ChannelInfo): Completable = subscriptionTable.getSubscription(info.serviceId, info.url)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.schabi.newpipe.local.subscription
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.fragment.app.Fragment
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionFragment.Companion.JSON_MIME_TYPE
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionExportWorker
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionImportInput
|
||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||
|
||||
/**
|
||||
* This class has to be created in onAttach() or onCreate().
|
||||
*
|
||||
* It contains registerForActivityResult calls and those
|
||||
* calls are only allowed before a fragment/activity is created.
|
||||
*/
|
||||
class SubscriptionsImportExportHelper(
|
||||
val fragment: Fragment
|
||||
) {
|
||||
val context: Context = fragment.requireContext()
|
||||
|
||||
companion object {
|
||||
val TAG: String =
|
||||
SubscriptionsImportExportHelper::class.java.simpleName + "@" + Integer.toHexString(
|
||||
hashCode()
|
||||
)
|
||||
}
|
||||
|
||||
private val requestExportLauncher =
|
||||
fragment.registerForActivityResult(StartActivityForResult(), this::requestExportResult)
|
||||
private val requestImportLauncher =
|
||||
fragment.registerForActivityResult(StartActivityForResult(), this::requestImportResult)
|
||||
|
||||
private fun requestExportResult(result: ActivityResult) {
|
||||
val data = result.data?.data
|
||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
SubscriptionExportWorker.schedule(context, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestImportResult(result: ActivityResult) {
|
||||
val data = result.data?.dataString
|
||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
ImportConfirmationDialog.show(
|
||||
fragment,
|
||||
SubscriptionImportInput.PreviousExportMode(data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onExportSelected() {
|
||||
val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date())
|
||||
val exportName = "newpipe_subscriptions_$date.json"
|
||||
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestExportLauncher,
|
||||
StoredFileHelper.getNewPicker(
|
||||
context,
|
||||
exportName,
|
||||
JSON_MIME_TYPE,
|
||||
null
|
||||
),
|
||||
TAG,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
fun onImportPreviousSelected() {
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestImportLauncher,
|
||||
StoredFileHelper.getPicker(context, JSON_MIME_TYPE),
|
||||
TAG,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
package org.schabi.newpipe.local.subscription;
|
||||
|
||||
import static org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.ContentSource.CHANNEL_URL;
|
||||
import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.CHANNEL_URL_MODE;
|
||||
import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.INPUT_STREAM_MODE;
|
||||
import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE;
|
||||
import static org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
@@ -37,7 +33,7 @@ import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionImportInput;
|
||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
@@ -168,10 +164,8 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
public void onImportUrl(final String value) {
|
||||
ImportConfirmationDialog.show(this, new Intent(activity, SubscriptionsImportService.class)
|
||||
.putExtra(KEY_MODE, CHANNEL_URL_MODE)
|
||||
.putExtra(KEY_VALUE, value)
|
||||
.putExtra(Constants.KEY_SERVICE_ID, currentServiceId));
|
||||
ImportConfirmationDialog.show(this,
|
||||
new SubscriptionImportInput.ChannelUrlMode(currentServiceId, value));
|
||||
}
|
||||
|
||||
public void onImportFile() {
|
||||
@@ -186,16 +180,10 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
private void requestImportFileResult(final ActivityResult result) {
|
||||
if (result.getData() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.getResultCode() == Activity.RESULT_OK && result.getData().getData() != null) {
|
||||
final String data = result.getData() != null ? result.getData().getDataString() : null;
|
||||
if (result.getResultCode() == Activity.RESULT_OK && data != null) {
|
||||
ImportConfirmationDialog.show(this,
|
||||
new Intent(activity, SubscriptionsImportService.class)
|
||||
.putExtra(KEY_MODE, INPUT_STREAM_MODE)
|
||||
.putExtra(KEY_VALUE, result.getData().getData())
|
||||
.putExtra(Constants.KEY_SERVICE_ID, currentServiceId));
|
||||
new SubscriptionImportInput.InputStreamMode(currentServiceId, data));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com>
|
||||
* BaseImportExportService.java is part of NewPipe
|
||||
*
|
||||
* License: GPL-3.0+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.local.subscription.services;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.ErrorUtil;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.functions.Function;
|
||||
import io.reactivex.rxjava3.processors.PublishProcessor;
|
||||
|
||||
public abstract class BaseImportExportService extends Service {
|
||||
protected final String TAG = this.getClass().getSimpleName();
|
||||
|
||||
protected final CompositeDisposable disposables = new CompositeDisposable();
|
||||
protected final PublishProcessor<String> notificationUpdater = PublishProcessor.create();
|
||||
|
||||
protected NotificationManagerCompat notificationManager;
|
||||
protected NotificationCompat.Builder notificationBuilder;
|
||||
protected SubscriptionManager subscriptionManager;
|
||||
|
||||
private static final int NOTIFICATION_SAMPLING_PERIOD = 2500;
|
||||
|
||||
protected final AtomicInteger currentProgress = new AtomicInteger(-1);
|
||||
protected final AtomicInteger maxProgress = new AtomicInteger(-1);
|
||||
protected final ImportExportEventListener eventListener = new ImportExportEventListener() {
|
||||
@Override
|
||||
public void onSizeReceived(final int size) {
|
||||
maxProgress.set(size);
|
||||
currentProgress.set(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemCompleted(final String itemName) {
|
||||
currentProgress.incrementAndGet();
|
||||
notificationUpdater.onNext(itemName);
|
||||
}
|
||||
};
|
||||
|
||||
protected Toast toast;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
subscriptionManager = new SubscriptionManager(this);
|
||||
setupNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
disposeAll();
|
||||
}
|
||||
|
||||
protected void disposeAll() {
|
||||
disposables.clear();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Notification Impl
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected abstract int getNotificationId();
|
||||
|
||||
@StringRes
|
||||
public abstract int getTitle();
|
||||
|
||||
protected void setupNotification() {
|
||||
notificationManager = NotificationManagerCompat.from(this);
|
||||
notificationBuilder = createNotification();
|
||||
startForeground(getNotificationId(), notificationBuilder.build());
|
||||
|
||||
final Function<Flowable<String>, Publisher<String>> throttleAfterFirstEmission = flow ->
|
||||
flow.take(1).concatWith(flow.skip(1)
|
||||
.throttleLast(NOTIFICATION_SAMPLING_PERIOD, TimeUnit.MILLISECONDS));
|
||||
|
||||
disposables.add(notificationUpdater
|
||||
.filter(s -> !s.isEmpty())
|
||||
.publish(throttleAfterFirstEmission)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(this::updateNotification));
|
||||
}
|
||||
|
||||
protected void updateNotification(final String text) {
|
||||
notificationBuilder
|
||||
.setProgress(maxProgress.get(), currentProgress.get(), maxProgress.get() == -1);
|
||||
|
||||
final String progressText = currentProgress + "/" + maxProgress;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
notificationBuilder.setContentText(text + " (" + progressText + ")");
|
||||
}
|
||||
} else {
|
||||
notificationBuilder.setContentInfo(progressText);
|
||||
notificationBuilder.setContentText(text);
|
||||
}
|
||||
|
||||
if (notificationManager.areNotificationsEnabled()) {
|
||||
notificationManager.notify(getNotificationId(), notificationBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
protected void stopService() {
|
||||
postErrorResult(null, null);
|
||||
}
|
||||
|
||||
protected void stopAndReportError(final Throwable throwable, final String request) {
|
||||
stopService();
|
||||
ErrorUtil.createNotification(this, new ErrorInfo(
|
||||
throwable, UserAction.SUBSCRIPTION_IMPORT_EXPORT, request));
|
||||
}
|
||||
|
||||
protected void postErrorResult(final String title, final String text) {
|
||||
disposeAll();
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
|
||||
stopSelf();
|
||||
|
||||
if (title == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String textOrEmpty = text == null ? "" : text;
|
||||
notificationBuilder = new NotificationCompat
|
||||
.Builder(this, getString(R.string.notification_channel_id))
|
||||
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setContentTitle(title)
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(textOrEmpty))
|
||||
.setContentText(textOrEmpty);
|
||||
|
||||
if (notificationManager.areNotificationsEnabled()) {
|
||||
notificationManager.notify(getNotificationId(), notificationBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
protected NotificationCompat.Builder createNotification() {
|
||||
return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
|
||||
.setOngoing(true)
|
||||
.setProgress(-1, -1, true)
|
||||
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setContentTitle(getString(getTitle()));
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Toast
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected void showToast(@StringRes final int message) {
|
||||
showToast(getString(message));
|
||||
}
|
||||
|
||||
protected void showToast(final String message) {
|
||||
if (toast != null) {
|
||||
toast.cancel();
|
||||
}
|
||||
|
||||
toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
|
||||
toast.show();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Error handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected void handleError(@StringRes final int errorTitle, @NonNull final Throwable error) {
|
||||
String message = getErrorMessage(error);
|
||||
|
||||
if (TextUtils.isEmpty(message)) {
|
||||
final String errorClassName = error.getClass().getName();
|
||||
message = getString(R.string.error_occurred_detail, errorClassName);
|
||||
}
|
||||
|
||||
showToast(errorTitle);
|
||||
postErrorResult(getString(errorTitle), message);
|
||||
}
|
||||
|
||||
protected String getErrorMessage(final Throwable error) {
|
||||
String message = null;
|
||||
if (error instanceof SubscriptionExtractor.InvalidSourceException) {
|
||||
message = getString(R.string.invalid_source);
|
||||
} else if (error instanceof FileNotFoundException) {
|
||||
message = getString(R.string.invalid_file);
|
||||
} else if (ExceptionUtils.isNetworkRelated(error)) {
|
||||
message = getString(R.string.network_error);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package org.schabi.newpipe.local.subscription.services;
|
||||
|
||||
public interface ImportExportEventListener {
|
||||
/**
|
||||
* Called when the size has been resolved.
|
||||
*
|
||||
* @param size how many items there are to import/export
|
||||
*/
|
||||
void onSizeReceived(int size);
|
||||
|
||||
/**
|
||||
* Called every time an item has been parsed/resolved.
|
||||
*
|
||||
* @param itemName the name of the subscription item
|
||||
*/
|
||||
void onItemCompleted(String itemName);
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com>
|
||||
* ImportExportJsonHelper.java is part of NewPipe
|
||||
*
|
||||
* License: GPL-3.0+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.local.subscription.services;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.grack.nanojson.JsonAppendableWriter;
|
||||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonParser;
|
||||
import com.grack.nanojson.JsonWriter;
|
||||
|
||||
import org.schabi.newpipe.BuildConfig;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.InvalidSourceException;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A JSON implementation capable of importing and exporting subscriptions, it has the advantage
|
||||
* of being able to transfer subscriptions to any device.
|
||||
*/
|
||||
public final class ImportExportJsonHelper {
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Json implementation
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private static final String JSON_APP_VERSION_KEY = "app_version";
|
||||
private static final String JSON_APP_VERSION_INT_KEY = "app_version_int";
|
||||
|
||||
private static final String JSON_SUBSCRIPTIONS_ARRAY_KEY = "subscriptions";
|
||||
|
||||
private static final String JSON_SERVICE_ID_KEY = "service_id";
|
||||
private static final String JSON_URL_KEY = "url";
|
||||
private static final String JSON_NAME_KEY = "name";
|
||||
|
||||
private ImportExportJsonHelper() { }
|
||||
|
||||
/**
|
||||
* Read a JSON source through the input stream.
|
||||
*
|
||||
* @param in the input stream (e.g. a file)
|
||||
* @param eventListener listener for the events generated
|
||||
* @return the parsed subscription items
|
||||
*/
|
||||
public static List<SubscriptionItem> readFrom(
|
||||
final InputStream in, @Nullable final ImportExportEventListener eventListener)
|
||||
throws InvalidSourceException {
|
||||
if (in == null) {
|
||||
throw new InvalidSourceException("input is null");
|
||||
}
|
||||
|
||||
final List<SubscriptionItem> channels = new ArrayList<>();
|
||||
|
||||
try {
|
||||
final JsonObject parentObject = JsonParser.object().from(in);
|
||||
|
||||
if (!parentObject.has(JSON_SUBSCRIPTIONS_ARRAY_KEY)) {
|
||||
throw new InvalidSourceException("Channels array is null");
|
||||
}
|
||||
|
||||
final JsonArray channelsArray = parentObject.getArray(JSON_SUBSCRIPTIONS_ARRAY_KEY);
|
||||
|
||||
if (eventListener != null) {
|
||||
eventListener.onSizeReceived(channelsArray.size());
|
||||
}
|
||||
|
||||
for (final Object o : channelsArray) {
|
||||
if (o instanceof JsonObject) {
|
||||
final JsonObject itemObject = (JsonObject) o;
|
||||
final int serviceId = itemObject.getInt(JSON_SERVICE_ID_KEY, 0);
|
||||
final String url = itemObject.getString(JSON_URL_KEY);
|
||||
final String name = itemObject.getString(JSON_NAME_KEY);
|
||||
|
||||
if (url != null && name != null && !url.isEmpty() && !name.isEmpty()) {
|
||||
channels.add(new SubscriptionItem(serviceId, url, name));
|
||||
if (eventListener != null) {
|
||||
eventListener.onItemCompleted(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
throw new InvalidSourceException("Couldn't parse json", e);
|
||||
}
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the subscriptions items list as JSON to the output.
|
||||
*
|
||||
* @param items the list of subscriptions items
|
||||
* @param out the output stream (e.g. a file)
|
||||
* @param eventListener listener for the events generated
|
||||
*/
|
||||
public static void writeTo(final List<SubscriptionItem> items, final OutputStream out,
|
||||
@Nullable final ImportExportEventListener eventListener) {
|
||||
final JsonAppendableWriter writer = JsonWriter.on(out);
|
||||
writeTo(items, writer, eventListener);
|
||||
writer.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #writeTo(List, OutputStream, ImportExportEventListener)
|
||||
* @param items the list of subscriptions items
|
||||
* @param writer the output {@link JsonAppendableWriter}
|
||||
* @param eventListener listener for the events generated
|
||||
*/
|
||||
public static void writeTo(final List<SubscriptionItem> items,
|
||||
final JsonAppendableWriter writer,
|
||||
@Nullable final ImportExportEventListener eventListener) {
|
||||
if (eventListener != null) {
|
||||
eventListener.onSizeReceived(items.size());
|
||||
}
|
||||
|
||||
writer.object();
|
||||
|
||||
writer.value(JSON_APP_VERSION_KEY, BuildConfig.VERSION_NAME);
|
||||
writer.value(JSON_APP_VERSION_INT_KEY, BuildConfig.VERSION_CODE);
|
||||
|
||||
writer.array(JSON_SUBSCRIPTIONS_ARRAY_KEY);
|
||||
for (final SubscriptionItem item : items) {
|
||||
writer.object();
|
||||
writer.value(JSON_SERVICE_ID_KEY, item.getServiceId());
|
||||
writer.value(JSON_URL_KEY, item.getUrl());
|
||||
writer.value(JSON_NAME_KEY, item.getName());
|
||||
writer.end();
|
||||
|
||||
if (eventListener != null) {
|
||||
eventListener.onItemCompleted(item.getName());
|
||||
}
|
||||
}
|
||||
writer.end();
|
||||
|
||||
writer.end();
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com>
|
||||
* SubscriptionsExportService.java is part of NewPipe
|
||||
*
|
||||
* License: GPL-3.0+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.local.subscription.services;
|
||||
|
||||
import static org.schabi.newpipe.MainActivity.DEBUG;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.content.IntentCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
|
||||
import org.schabi.newpipe.streams.io.SharpOutputStream;
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.functions.Function;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class SubscriptionsExportService extends BaseImportExportService {
|
||||
public static final String KEY_FILE_PATH = "key_file_path";
|
||||
|
||||
/**
|
||||
* A {@link LocalBroadcastManager local broadcast} will be made with this action
|
||||
* when the export is successfully completed.
|
||||
*/
|
||||
public static final String EXPORT_COMPLETE_ACTION = App.PACKAGE_NAME + ".local.subscription"
|
||||
+ ".services.SubscriptionsExportService.EXPORT_COMPLETE";
|
||||
|
||||
private Subscription subscription;
|
||||
private StoredFileHelper outFile;
|
||||
private OutputStream outputStream;
|
||||
|
||||
@Override
|
||||
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
||||
if (intent == null || subscription != null) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
final Uri path = IntentCompat.getParcelableExtra(intent, KEY_FILE_PATH, Uri.class);
|
||||
if (path == null) {
|
||||
stopAndReportError(new IllegalStateException(
|
||||
"Exporting to a file, but the path is null"),
|
||||
"Exporting subscriptions");
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
try {
|
||||
outFile = new StoredFileHelper(this, path, "application/json");
|
||||
// truncate the file before writing to it, otherwise if the new content is smaller than
|
||||
// the previous file size, the file will retain part of the previous content and be
|
||||
// corrupted
|
||||
outputStream = new SharpOutputStream(outFile.openAndTruncateStream());
|
||||
} catch (final IOException e) {
|
||||
handleError(e);
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
startExport();
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNotificationId() {
|
||||
return 4567;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTitle() {
|
||||
return R.string.export_ongoing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disposeAll() {
|
||||
super.disposeAll();
|
||||
if (subscription != null) {
|
||||
subscription.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void startExport() {
|
||||
showToast(R.string.export_ongoing);
|
||||
|
||||
subscriptionManager.subscriptionTable().getAll().take(1)
|
||||
.map(subscriptionEntities -> {
|
||||
final List<SubscriptionItem> result =
|
||||
new ArrayList<>(subscriptionEntities.size());
|
||||
for (final SubscriptionEntity entity : subscriptionEntities) {
|
||||
result.add(new SubscriptionItem(entity.getServiceId(), entity.getUrl(),
|
||||
entity.getName()));
|
||||
}
|
||||
return result;
|
||||
})
|
||||
.map(exportToFile())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscriber());
|
||||
}
|
||||
|
||||
private Subscriber<StoredFileHelper> getSubscriber() {
|
||||
return new Subscriber<StoredFileHelper>() {
|
||||
@Override
|
||||
public void onSubscribe(final Subscription s) {
|
||||
subscription = s;
|
||||
s.request(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(final StoredFileHelper file) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "startExport() success: file = " + file);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final Throwable error) {
|
||||
Log.e(TAG, "onError() called with: error = [" + error + "]", error);
|
||||
handleError(error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
LocalBroadcastManager.getInstance(SubscriptionsExportService.this)
|
||||
.sendBroadcast(new Intent(EXPORT_COMPLETE_ACTION));
|
||||
showToast(R.string.export_complete_toast);
|
||||
stopService();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Function<List<SubscriptionItem>, StoredFileHelper> exportToFile() {
|
||||
return subscriptionItems -> {
|
||||
ImportExportJsonHelper.writeTo(subscriptionItems, outputStream, eventListener);
|
||||
return outFile;
|
||||
};
|
||||
}
|
||||
|
||||
protected void handleError(final Throwable error) {
|
||||
super.handleError(R.string.subscriptions_export_unsuccessful, error);
|
||||
}
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com>
|
||||
* SubscriptionsImportService.java is part of NewPipe
|
||||
*
|
||||
* License: GPL-3.0+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.local.subscription.services;
|
||||
|
||||
import static org.schabi.newpipe.MainActivity.DEBUG;
|
||||
import static org.schabi.newpipe.streams.io.StoredFileHelper.DEFAULT_MIME;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.IntentCompat;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfo;
|
||||
import org.schabi.newpipe.extractor.channel.tabs.ChannelTabInfo;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
|
||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||
import org.schabi.newpipe.streams.io.SharpInputStream;
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
import io.reactivex.rxjava3.core.Notification;
|
||||
import io.reactivex.rxjava3.functions.Consumer;
|
||||
import io.reactivex.rxjava3.functions.Function;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class SubscriptionsImportService extends BaseImportExportService {
|
||||
public static final int CHANNEL_URL_MODE = 0;
|
||||
public static final int INPUT_STREAM_MODE = 1;
|
||||
public static final int PREVIOUS_EXPORT_MODE = 2;
|
||||
public static final String KEY_MODE = "key_mode";
|
||||
public static final String KEY_VALUE = "key_value";
|
||||
|
||||
/**
|
||||
* A {@link LocalBroadcastManager local broadcast} will be made with this action
|
||||
* when the import is successfully completed.
|
||||
*/
|
||||
public static final String IMPORT_COMPLETE_ACTION = App.PACKAGE_NAME + ".local.subscription"
|
||||
+ ".services.SubscriptionsImportService.IMPORT_COMPLETE";
|
||||
|
||||
/**
|
||||
* How many extractions running in parallel.
|
||||
*/
|
||||
public static final int PARALLEL_EXTRACTIONS = 8;
|
||||
|
||||
/**
|
||||
* Number of items to buffer to mass-insert in the subscriptions table,
|
||||
* this leads to a better performance as we can then use db transactions.
|
||||
*/
|
||||
public static final int BUFFER_COUNT_BEFORE_INSERT = 50;
|
||||
|
||||
private Subscription subscription;
|
||||
private int currentMode;
|
||||
private int currentServiceId;
|
||||
@Nullable
|
||||
private String channelUrl;
|
||||
@Nullable
|
||||
private InputStream inputStream;
|
||||
@Nullable
|
||||
private String inputStreamType;
|
||||
|
||||
@Override
|
||||
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
||||
if (intent == null || subscription != null) {
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
currentMode = intent.getIntExtra(KEY_MODE, -1);
|
||||
currentServiceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, Constants.NO_SERVICE_ID);
|
||||
|
||||
if (currentMode == CHANNEL_URL_MODE) {
|
||||
channelUrl = intent.getStringExtra(KEY_VALUE);
|
||||
} else {
|
||||
final Uri uri = IntentCompat.getParcelableExtra(intent, KEY_VALUE, Uri.class);
|
||||
if (uri == null) {
|
||||
stopAndReportError(new IllegalStateException(
|
||||
"Importing from input stream, but file path is null"),
|
||||
"Importing subscriptions");
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
try {
|
||||
final StoredFileHelper fileHelper = new StoredFileHelper(this, uri, DEFAULT_MIME);
|
||||
inputStream = new SharpInputStream(fileHelper.getStream());
|
||||
inputStreamType = fileHelper.getType();
|
||||
|
||||
if (inputStreamType == null || inputStreamType.equals(DEFAULT_MIME)) {
|
||||
// mime type could not be determined, just take file extension
|
||||
final String name = fileHelper.getName();
|
||||
final int pointIndex = name.lastIndexOf('.');
|
||||
if (pointIndex == -1 || pointIndex >= name.length() - 1) {
|
||||
inputStreamType = DEFAULT_MIME; // no extension, will fail in the extractor
|
||||
} else {
|
||||
inputStreamType = name.substring(pointIndex + 1);
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
handleError(e);
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMode == -1 || currentMode == CHANNEL_URL_MODE && channelUrl == null) {
|
||||
final String errorDescription = "Some important field is null or in illegal state: "
|
||||
+ "currentMode=[" + currentMode + "], "
|
||||
+ "channelUrl=[" + channelUrl + "], "
|
||||
+ "inputStream=[" + inputStream + "]";
|
||||
stopAndReportError(new IllegalStateException(errorDescription),
|
||||
"Importing subscriptions");
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
startImport();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNotificationId() {
|
||||
return 4568;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTitle() {
|
||||
return R.string.import_ongoing;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disposeAll() {
|
||||
super.disposeAll();
|
||||
if (subscription != null) {
|
||||
subscription.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Imports
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void startImport() {
|
||||
showToast(R.string.import_ongoing);
|
||||
|
||||
Flowable<List<SubscriptionItem>> flowable = null;
|
||||
switch (currentMode) {
|
||||
case CHANNEL_URL_MODE:
|
||||
flowable = importFromChannelUrl();
|
||||
break;
|
||||
case INPUT_STREAM_MODE:
|
||||
flowable = importFromInputStream();
|
||||
break;
|
||||
case PREVIOUS_EXPORT_MODE:
|
||||
flowable = importFromPreviousExport();
|
||||
break;
|
||||
}
|
||||
|
||||
if (flowable == null) {
|
||||
final String message = "Flowable given by \"importFrom\" is null "
|
||||
+ "(current mode: " + currentMode + ")";
|
||||
stopAndReportError(new IllegalStateException(message), "Importing subscriptions");
|
||||
return;
|
||||
}
|
||||
|
||||
flowable.doOnNext(subscriptionItems ->
|
||||
eventListener.onSizeReceived(subscriptionItems.size()))
|
||||
.flatMap(Flowable::fromIterable)
|
||||
|
||||
.parallel(PARALLEL_EXTRACTIONS)
|
||||
.runOn(Schedulers.io())
|
||||
.map((Function<SubscriptionItem, Notification<Pair<ChannelInfo,
|
||||
List<ChannelTabInfo>>>>) subscriptionItem -> {
|
||||
try {
|
||||
final ChannelInfo channelInfo = ExtractorHelper
|
||||
.getChannelInfo(subscriptionItem.getServiceId(),
|
||||
subscriptionItem.getUrl(), true)
|
||||
.blockingGet();
|
||||
return Notification.createOnNext(new Pair<>(channelInfo,
|
||||
Collections.singletonList(
|
||||
ExtractorHelper.getChannelTab(
|
||||
subscriptionItem.getServiceId(),
|
||||
channelInfo.getTabs().get(0), true).blockingGet()
|
||||
)));
|
||||
} catch (final Throwable e) {
|
||||
return Notification.createOnError(e);
|
||||
}
|
||||
})
|
||||
.sequential()
|
||||
|
||||
.observeOn(Schedulers.io())
|
||||
.doOnNext(getNotificationsConsumer())
|
||||
|
||||
.buffer(BUFFER_COUNT_BEFORE_INSERT)
|
||||
.map(upsertBatch())
|
||||
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscriber());
|
||||
}
|
||||
|
||||
private Subscriber<List<SubscriptionEntity>> getSubscriber() {
|
||||
return new Subscriber<>() {
|
||||
@Override
|
||||
public void onSubscribe(final Subscription s) {
|
||||
subscription = s;
|
||||
s.request(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(final List<SubscriptionEntity> successfulInserted) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "startImport() " + successfulInserted.size()
|
||||
+ " items successfully inserted into the database");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final Throwable error) {
|
||||
Log.e(TAG, "Got an error!", error);
|
||||
handleError(error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
LocalBroadcastManager.getInstance(SubscriptionsImportService.this)
|
||||
.sendBroadcast(new Intent(IMPORT_COMPLETE_ACTION));
|
||||
showToast(R.string.import_complete_toast);
|
||||
stopService();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Consumer<Notification<Pair<ChannelInfo,
|
||||
List<ChannelTabInfo>>>> getNotificationsConsumer() {
|
||||
return notification -> {
|
||||
if (notification.isOnNext()) {
|
||||
final String name = notification.getValue().first.getName();
|
||||
eventListener.onItemCompleted(!TextUtils.isEmpty(name) ? name : "");
|
||||
} else if (notification.isOnError()) {
|
||||
final Throwable error = notification.getError();
|
||||
final Throwable cause = error.getCause();
|
||||
if (error instanceof IOException) {
|
||||
throw error;
|
||||
} else if (cause instanceof IOException) {
|
||||
throw cause;
|
||||
} else if (ExceptionUtils.isNetworkRelated(error)) {
|
||||
throw new IOException(error);
|
||||
}
|
||||
|
||||
eventListener.onItemCompleted("");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Function<List<Notification<Pair<ChannelInfo, List<ChannelTabInfo>>>>,
|
||||
List<SubscriptionEntity>> upsertBatch() {
|
||||
return notificationList -> {
|
||||
final List<Pair<ChannelInfo, List<ChannelTabInfo>>> infoList =
|
||||
new ArrayList<>(notificationList.size());
|
||||
for (final Notification<Pair<ChannelInfo, List<ChannelTabInfo>>> n : notificationList) {
|
||||
if (n.isOnNext()) {
|
||||
infoList.add(n.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return subscriptionManager.upsertAll(infoList);
|
||||
};
|
||||
}
|
||||
|
||||
private Flowable<List<SubscriptionItem>> importFromChannelUrl() {
|
||||
return Flowable.fromCallable(() -> NewPipe.getService(currentServiceId)
|
||||
.getSubscriptionExtractor()
|
||||
.fromChannelUrl(channelUrl));
|
||||
}
|
||||
|
||||
private Flowable<List<SubscriptionItem>> importFromInputStream() {
|
||||
Objects.requireNonNull(inputStream);
|
||||
Objects.requireNonNull(inputStreamType);
|
||||
|
||||
return Flowable.fromCallable(() -> NewPipe.getService(currentServiceId)
|
||||
.getSubscriptionExtractor()
|
||||
.fromInputStream(inputStream, inputStreamType));
|
||||
}
|
||||
|
||||
private Flowable<List<SubscriptionItem>> importFromPreviousExport() {
|
||||
return Flowable.fromCallable(() -> ImportExportJsonHelper.readFrom(inputStream, null));
|
||||
}
|
||||
|
||||
protected void handleError(@NonNull final Throwable error) {
|
||||
super.handleError(R.string.subscriptions_import_unsuccessful, error);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2018 Mauricio Colli <mauriciocolli@outlook.com>
|
||||
* ImportExportJsonHelper.java is part of NewPipe
|
||||
*
|
||||
* License: GPL-3.0+
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.local.subscription.workers
|
||||
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import kotlinx.serialization.json.encodeToStream
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor.InvalidSourceException
|
||||
|
||||
/**
|
||||
* A JSON implementation capable of importing and exporting subscriptions, it has the advantage
|
||||
* of being able to transfer subscriptions to any device.
|
||||
*/
|
||||
object ImportExportJsonHelper {
|
||||
private val json = Json { encodeDefaults = true }
|
||||
|
||||
/**
|
||||
* Read a JSON source through the input stream.
|
||||
*
|
||||
* @param in the input stream (e.g. a file)
|
||||
* @return the parsed subscription items
|
||||
*/
|
||||
@JvmStatic
|
||||
@Throws(InvalidSourceException::class)
|
||||
fun readFrom(`in`: InputStream?): List<SubscriptionItem> {
|
||||
if (`in` == null) {
|
||||
throw InvalidSourceException("input is null")
|
||||
}
|
||||
|
||||
try {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
return json.decodeFromStream<SubscriptionData>(`in`).subscriptions
|
||||
} catch (e: Throwable) {
|
||||
throw InvalidSourceException("Couldn't parse json", e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the subscriptions items list as JSON to the output.
|
||||
*
|
||||
* @param items the list of subscriptions items
|
||||
* @param out the output stream (e.g. a file)
|
||||
*/
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@JvmStatic
|
||||
fun writeTo(
|
||||
items: List<SubscriptionItem>,
|
||||
out: OutputStream
|
||||
) {
|
||||
json.encodeToStream(SubscriptionData(items), out)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.schabi.newpipe.local.subscription.workers
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.schabi.newpipe.BuildConfig
|
||||
|
||||
@Serializable
|
||||
class SubscriptionData(
|
||||
val subscriptions: List<SubscriptionItem>
|
||||
) {
|
||||
@SerialName("app_version")
|
||||
private val appVersion = BuildConfig.VERSION_NAME
|
||||
|
||||
@SerialName("app_version_int")
|
||||
private val appVersionInt = BuildConfig.VERSION_CODE
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class SubscriptionItem(
|
||||
@SerialName("service_id")
|
||||
val serviceId: Int,
|
||||
val url: String,
|
||||
val name: String
|
||||
)
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.schabi.newpipe.local.subscription.workers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.OutOfQuotaPolicy
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.reactive.awaitFirst
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.schabi.newpipe.BuildConfig
|
||||
import org.schabi.newpipe.NewPipeDatabase
|
||||
import org.schabi.newpipe.R
|
||||
|
||||
class SubscriptionExportWorker(
|
||||
appContext: Context,
|
||||
params: WorkerParameters
|
||||
) : CoroutineWorker(appContext, params) {
|
||||
// This is needed for API levels < 31 (Android S).
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
return createForegroundInfo(applicationContext.getString(R.string.export_ongoing))
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
return try {
|
||||
val uri = inputData.getString(EXPORT_PATH)!!.toUri()
|
||||
val table = NewPipeDatabase.getInstance(applicationContext).subscriptionDAO()
|
||||
val subscriptions =
|
||||
table.getAll()
|
||||
.awaitFirst()
|
||||
.map { SubscriptionItem(it.serviceId, it.url ?: "", it.name ?: "") }
|
||||
|
||||
val qty = subscriptions.size
|
||||
val title = applicationContext.resources.getQuantityString(R.plurals.export_subscriptions, qty, qty)
|
||||
setForeground(createForegroundInfo(title))
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
// Truncate file if it already exists
|
||||
applicationContext.contentResolver.openOutputStream(uri, "wt")?.use {
|
||||
ImportExportJsonHelper.writeTo(subscriptions, it)
|
||||
}
|
||||
}
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.i(TAG, "Exported $qty subscriptions")
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast
|
||||
.makeText(applicationContext, R.string.export_complete_toast, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "Error while exporting subscriptions", e)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast
|
||||
.makeText(applicationContext, R.string.subscriptions_export_unsuccessful, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
return Result.failure()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createForegroundInfo(title: String): ForegroundInfo {
|
||||
val notification =
|
||||
NotificationCompat
|
||||
.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
|
||||
.setOngoing(true)
|
||||
.setProgress(-1, -1, true)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
||||
.setContentTitle(title)
|
||||
.build()
|
||||
val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0
|
||||
return ForegroundInfo(NOTIFICATION_ID, notification, serviceType)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "SubscriptionExportWork"
|
||||
private const val NOTIFICATION_ID = 4567
|
||||
private const val NOTIFICATION_CHANNEL_ID = "newpipe"
|
||||
private const val WORK_NAME = "exportSubscriptions"
|
||||
private const val EXPORT_PATH = "exportPath"
|
||||
|
||||
fun schedule(
|
||||
context: Context,
|
||||
uri: Uri
|
||||
) {
|
||||
val data = workDataOf(EXPORT_PATH to uri.toString())
|
||||
val workRequest =
|
||||
OneTimeWorkRequestBuilder<SubscriptionExportWorker>()
|
||||
.setInputData(data)
|
||||
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
|
||||
.build()
|
||||
|
||||
WorkManager
|
||||
.getInstance(context)
|
||||
.enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, workRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package org.schabi.newpipe.local.subscription.workers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import android.os.Parcelable
|
||||
import android.util.Log
|
||||
import android.webkit.MimeTypeMap
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.Data
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.rx3.await
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.schabi.newpipe.BuildConfig
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
||||
import org.schabi.newpipe.util.ExtractorHelper
|
||||
|
||||
class SubscriptionImportWorker(
|
||||
appContext: Context,
|
||||
params: WorkerParameters
|
||||
) : CoroutineWorker(appContext, params) {
|
||||
// This is needed for API levels < 31 (Android S).
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
return createForegroundInfo(applicationContext.getString(R.string.import_ongoing), null, 0, 0)
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val subscriptions =
|
||||
try {
|
||||
loadSubscriptionsFromInput(SubscriptionImportInput.fromData(inputData))
|
||||
} catch (e: Exception) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "Error while loading subscriptions from path", e)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast
|
||||
.makeText(applicationContext, R.string.subscriptions_import_unsuccessful, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
val mutex = Mutex()
|
||||
var index = 1
|
||||
val qty = subscriptions.size
|
||||
var title =
|
||||
applicationContext.resources.getQuantityString(R.plurals.load_subscriptions, qty, qty)
|
||||
|
||||
val channelInfoList =
|
||||
try {
|
||||
withContext(Dispatchers.IO.limitedParallelism(PARALLEL_EXTRACTIONS)) {
|
||||
subscriptions
|
||||
.map {
|
||||
async {
|
||||
val channelInfo =
|
||||
ExtractorHelper.getChannelInfo(it.serviceId, it.url, true).await()
|
||||
val channelTab =
|
||||
ExtractorHelper.getChannelTab(it.serviceId, channelInfo.tabs[0], true).await()
|
||||
|
||||
val currentIndex = mutex.withLock { index++ }
|
||||
setForeground(createForegroundInfo(title, channelInfo.name, currentIndex, qty))
|
||||
|
||||
channelInfo to channelTab
|
||||
}
|
||||
}.awaitAll()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.e(TAG, "Error while loading subscription data", e)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(applicationContext, R.string.subscriptions_import_unsuccessful, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
title = applicationContext.resources.getQuantityString(R.plurals.import_subscriptions, qty, qty)
|
||||
setForeground(createForegroundInfo(title, null, 0, 0))
|
||||
index = 0
|
||||
|
||||
val subscriptionManager = SubscriptionManager(applicationContext)
|
||||
for (chunk in channelInfoList.chunked(BUFFER_COUNT_BEFORE_INSERT)) {
|
||||
withContext(Dispatchers.IO) {
|
||||
subscriptionManager.upsertAll(chunk)
|
||||
}
|
||||
index += chunk.size
|
||||
setForeground(createForegroundInfo(title, null, index, qty))
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
Toast.makeText(applicationContext, R.string.import_complete_toast, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private suspend fun loadSubscriptionsFromInput(input: SubscriptionImportInput): List<SubscriptionItem> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
when (input) {
|
||||
is SubscriptionImportInput.ChannelUrlMode ->
|
||||
NewPipe.getService(input.serviceId).subscriptionExtractor
|
||||
.fromChannelUrl(input.url)
|
||||
.map { SubscriptionItem(it.serviceId, it.url, it.name) }
|
||||
|
||||
is SubscriptionImportInput.InputStreamMode ->
|
||||
applicationContext.contentResolver.openInputStream(input.url.toUri())?.use {
|
||||
val contentType =
|
||||
MimeTypeMap.getFileExtensionFromUrl(input.url).ifEmpty { DEFAULT_MIME }
|
||||
NewPipe.getService(input.serviceId).subscriptionExtractor
|
||||
.fromInputStream(it, contentType)
|
||||
.map { SubscriptionItem(it.serviceId, it.url, it.name) }
|
||||
}
|
||||
|
||||
is SubscriptionImportInput.PreviousExportMode ->
|
||||
applicationContext.contentResolver.openInputStream(input.url.toUri())?.use {
|
||||
ImportExportJsonHelper.readFrom(it)
|
||||
}
|
||||
} ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createForegroundInfo(
|
||||
title: String,
|
||||
text: String?,
|
||||
currentProgress: Int,
|
||||
maxProgress: Int
|
||||
): ForegroundInfo {
|
||||
val notification =
|
||||
NotificationCompat
|
||||
.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
|
||||
.setOngoing(true)
|
||||
.setProgress(maxProgress, currentProgress, currentProgress == 0)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
||||
.setContentTitle(title)
|
||||
.setContentText(text)
|
||||
.addAction(
|
||||
R.drawable.ic_close,
|
||||
applicationContext.getString(R.string.cancel),
|
||||
WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)
|
||||
).apply {
|
||||
if (currentProgress > 0 && maxProgress > 0) {
|
||||
val progressText = "$currentProgress/$maxProgress"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
setSubText(progressText)
|
||||
} else {
|
||||
setContentInfo(progressText)
|
||||
}
|
||||
}
|
||||
}.build()
|
||||
val serviceType = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC else 0
|
||||
|
||||
return ForegroundInfo(NOTIFICATION_ID, notification, serviceType)
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Log tag length is limited to 23 characters on API levels < 24.
|
||||
private const val TAG = "SubscriptionImport"
|
||||
|
||||
private const val NOTIFICATION_ID = 4568
|
||||
private const val NOTIFICATION_CHANNEL_ID = "newpipe"
|
||||
private const val DEFAULT_MIME = "application/octet-stream"
|
||||
private const val PARALLEL_EXTRACTIONS = 8
|
||||
private const val BUFFER_COUNT_BEFORE_INSERT = 50
|
||||
|
||||
const val WORK_NAME = "SubscriptionImportWorker"
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SubscriptionImportInput : Parcelable {
|
||||
@Parcelize
|
||||
data class ChannelUrlMode(val serviceId: Int, val url: String) : SubscriptionImportInput()
|
||||
|
||||
@Parcelize
|
||||
data class InputStreamMode(val serviceId: Int, val url: String) : SubscriptionImportInput()
|
||||
|
||||
@Parcelize
|
||||
data class PreviousExportMode(val url: String) : SubscriptionImportInput()
|
||||
|
||||
fun toData(): Data {
|
||||
val (mode, serviceId, url) = when (this) {
|
||||
is ChannelUrlMode -> Triple(CHANNEL_URL_MODE, serviceId, url)
|
||||
is InputStreamMode -> Triple(INPUT_STREAM_MODE, serviceId, url)
|
||||
is PreviousExportMode -> Triple(PREVIOUS_EXPORT_MODE, null, url)
|
||||
}
|
||||
return workDataOf("mode" to mode, "service_id" to serviceId, "url" to url)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val CHANNEL_URL_MODE = 0
|
||||
private const val INPUT_STREAM_MODE = 1
|
||||
private const val PREVIOUS_EXPORT_MODE = 2
|
||||
|
||||
fun fromData(data: Data): SubscriptionImportInput {
|
||||
val mode = data.getInt("mode", PREVIOUS_EXPORT_MODE)
|
||||
when (mode) {
|
||||
CHANNEL_URL_MODE -> {
|
||||
val serviceId = data.getInt("service_id", -1)
|
||||
if (serviceId == -1) {
|
||||
throw IllegalArgumentException("No service id provided")
|
||||
}
|
||||
val url = data.getString("url")!!
|
||||
return ChannelUrlMode(serviceId, url)
|
||||
}
|
||||
|
||||
INPUT_STREAM_MODE -> {
|
||||
val serviceId = data.getInt("service_id", -1)
|
||||
if (serviceId == -1) {
|
||||
throw IllegalArgumentException("No service id provided")
|
||||
}
|
||||
val url = data.getString("url")!!
|
||||
return InputStreamMode(serviceId, url)
|
||||
}
|
||||
|
||||
PREVIOUS_EXPORT_MODE -> {
|
||||
val url = data.getString("url")!!
|
||||
return PreviousExportMode(url)
|
||||
}
|
||||
|
||||
else -> throw IllegalArgumentException("Unknown mode: $mode")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ import org.schabi.newpipe.util.NavigationHelper
|
||||
*/
|
||||
class MediaBrowserPlaybackPreparer(
|
||||
private val context: Context,
|
||||
private val setMediaSessionError: BiConsumer<String, Int>, // error string, error code
|
||||
private val setMediaSessionError: BiConsumer<CharSequence, Int>, // error string, error code
|
||||
private val clearMediaSessionError: Runnable,
|
||||
private val onPrepare: Consumer<Boolean>
|
||||
) : PlaybackPreparer {
|
||||
@@ -118,7 +118,7 @@ class MediaBrowserPlaybackPreparer(
|
||||
|
||||
private fun onPrepareError(throwable: Throwable) {
|
||||
setMediaSessionError.accept(
|
||||
ErrorInfo.getMessage(throwable, null, null).getString(context),
|
||||
ErrorInfo.getMessage(throwable, null, null).getText(context),
|
||||
PlaybackStateCompat.ERROR_CODE_APP_ERROR
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
@@ -27,6 +26,7 @@ import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.ErrorUtil;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionsImportExportHelper;
|
||||
import org.schabi.newpipe.settings.export.BackupFileLocator;
|
||||
import org.schabi.newpipe.settings.export.ImportExportManager;
|
||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
|
||||
@@ -34,12 +34,10 @@ import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ZipHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -57,18 +55,22 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
private final ActivityResultLauncher<Intent> requestExportPathLauncher =
|
||||
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
|
||||
this::requestExportPathResult);
|
||||
private SubscriptionsImportExportHelper importExportHelper;
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
importExportHelper = new SubscriptionsImportExportHelper(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable final Bundle savedInstanceState,
|
||||
@Nullable final String rootKey) {
|
||||
final File homeDir = ContextCompat.getDataDir(requireContext());
|
||||
Objects.requireNonNull(homeDir);
|
||||
manager = new ImportExportManager(new BackupFileLocator(homeDir));
|
||||
manager = new ImportExportManager(new BackupFileLocator(requireContext()));
|
||||
|
||||
importExportDataPathKey = getString(R.string.import_export_data_path);
|
||||
|
||||
|
||||
addPreferencesFromResourceRegistry();
|
||||
|
||||
final Preference importDataPreference = requirePreference(R.string.import_data);
|
||||
@@ -123,6 +125,21 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
alertDialog.show();
|
||||
return true;
|
||||
});
|
||||
|
||||
final Preference exportSubsPreference =
|
||||
requirePreference(R.string.export_subscriptions_key);
|
||||
exportSubsPreference.setOnPreferenceClickListener(reference -> {
|
||||
importExportHelper.onExportSelected();
|
||||
return true;
|
||||
});
|
||||
|
||||
final Preference importSubsPreference =
|
||||
requirePreference(R.string.import_subscriptions_key);
|
||||
importSubsPreference.setOnPreferenceClickListener(preference -> {
|
||||
importExportHelper.onImportPreviousSelected();
|
||||
return true;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void requestExportPathResult(final ActivityResult result) {
|
||||
@@ -181,9 +198,7 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
}
|
||||
|
||||
try {
|
||||
if (!manager.ensureDbDirectoryExists()) {
|
||||
throw new IOException("Could not create databases dir");
|
||||
}
|
||||
manager.ensureDbDirectoryExists();
|
||||
|
||||
// replace the current database
|
||||
if (!manager.extractDb(file)) {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package org.schabi.newpipe.settings.export
|
||||
|
||||
import java.io.File
|
||||
import android.content.Context
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.div
|
||||
|
||||
/**
|
||||
* Locates specific files of NewPipe based on the home directory of the app.
|
||||
*/
|
||||
class BackupFileLocator(private val homeDir: File) {
|
||||
class BackupFileLocator(context: Context) {
|
||||
companion object {
|
||||
const val FILE_NAME_DB = "newpipe.db"
|
||||
|
||||
@@ -17,13 +19,8 @@ class BackupFileLocator(private val homeDir: File) {
|
||||
const val FILE_NAME_JSON_PREFS = "preferences.json"
|
||||
}
|
||||
|
||||
val dbDir by lazy { File(homeDir, "/databases") }
|
||||
|
||||
val db by lazy { File(dbDir, FILE_NAME_DB) }
|
||||
|
||||
val dbJournal by lazy { File(dbDir, "$FILE_NAME_DB-journal") }
|
||||
|
||||
val dbShm by lazy { File(dbDir, "$FILE_NAME_DB-shm") }
|
||||
|
||||
val dbWal by lazy { File(dbDir, "$FILE_NAME_DB-wal") }
|
||||
val db: Path = context.getDatabasePath(FILE_NAME_DB).toPath()
|
||||
val dbJournal: Path = db.resolveSibling("$FILE_NAME_DB-journal")
|
||||
val dbShm: Path = db.resolveSibling("$FILE_NAME_DB-shm")
|
||||
val dbWal: Path = db.resolveSibling("$FILE_NAME_DB-wal")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.io.ObjectOutputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlin.io.path.createParentDirectories
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import org.schabi.newpipe.streams.io.SharpOutputStream
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||
import org.schabi.newpipe.util.ZipHelper
|
||||
@@ -28,11 +30,8 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
// previous file size, the file will retain part of the previous content and be corrupted
|
||||
ZipOutputStream(SharpOutputStream(file.openAndTruncateStream()).buffered()).use { outZip ->
|
||||
// add the database
|
||||
ZipHelper.addFileToZip(
|
||||
outZip,
|
||||
BackupFileLocator.FILE_NAME_DB,
|
||||
fileLocator.db.path
|
||||
)
|
||||
val name = BackupFileLocator.FILE_NAME_DB
|
||||
ZipHelper.addFileToZip(outZip, name, fileLocator.db)
|
||||
|
||||
// add the legacy vulnerable serialized preferences (will be removed in the future)
|
||||
ZipHelper.addFileToZip(
|
||||
@@ -61,11 +60,10 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
|
||||
/**
|
||||
* Tries to create database directory if it does not exist.
|
||||
*
|
||||
* @return Whether the directory exists afterwards.
|
||||
*/
|
||||
fun ensureDbDirectoryExists(): Boolean {
|
||||
return fileLocator.dbDir.exists() || fileLocator.dbDir.mkdir()
|
||||
@Throws(IOException::class)
|
||||
fun ensureDbDirectoryExists() {
|
||||
fileLocator.db.createParentDirectories()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,16 +73,13 @@ class ImportExportManager(private val fileLocator: BackupFileLocator) {
|
||||
* @return true if the database was successfully extracted, false otherwise
|
||||
*/
|
||||
fun extractDb(file: StoredFileHelper): Boolean {
|
||||
val success = ZipHelper.extractFileFromZip(
|
||||
file,
|
||||
BackupFileLocator.FILE_NAME_DB,
|
||||
fileLocator.db.path
|
||||
)
|
||||
val name = BackupFileLocator.FILE_NAME_DB
|
||||
val success = ZipHelper.extractFileFromZip(file, name, fileLocator.db)
|
||||
|
||||
if (success) {
|
||||
fileLocator.dbJournal.delete()
|
||||
fileLocator.dbWal.delete()
|
||||
fileLocator.dbShm.delete()
|
||||
fileLocator.dbJournal.deleteIfExists()
|
||||
fileLocator.dbWal.deleteIfExists()
|
||||
fileLocator.dbShm.deleteIfExists()
|
||||
}
|
||||
|
||||
return success
|
||||
|
||||
@@ -6,12 +6,12 @@ import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
@@ -37,9 +37,6 @@ import java.util.zip.ZipOutputStream;
|
||||
*/
|
||||
|
||||
public final class ZipHelper {
|
||||
|
||||
private static final int BUFFER_SIZE = 2048;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface InputStreamConsumer {
|
||||
void acceptStream(InputStream inputStream) throws IOException;
|
||||
@@ -55,17 +52,17 @@ public final class ZipHelper {
|
||||
|
||||
|
||||
/**
|
||||
* This function helps to create zip files. Caution this will overwrite the original file.
|
||||
* This function helps to create zip files. Caution, this will overwrite the original file.
|
||||
*
|
||||
* @param outZip the ZipOutputStream where the data should be stored in
|
||||
* @param nameInZip the path of the file inside the zip
|
||||
* @param fileOnDisk the path of the file on the disk that should be added to zip
|
||||
* @param path the path of the file on the disk that should be added to zip
|
||||
*/
|
||||
public static void addFileToZip(final ZipOutputStream outZip,
|
||||
final String nameInZip,
|
||||
final String fileOnDisk) throws IOException {
|
||||
try (FileInputStream fi = new FileInputStream(fileOnDisk)) {
|
||||
addFileToZip(outZip, nameInZip, fi);
|
||||
final Path path) throws IOException {
|
||||
try (var inputStream = Files.newInputStream(path)) {
|
||||
addFileToZip(outZip, nameInZip, inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,13 +77,13 @@ public final class ZipHelper {
|
||||
final String nameInZip,
|
||||
final OutputStreamConsumer streamConsumer) throws IOException {
|
||||
final byte[] bytes;
|
||||
try (ByteArrayOutputStream byteOutput = new ByteArrayOutputStream()) {
|
||||
try (var byteOutput = new ByteArrayOutputStream()) {
|
||||
streamConsumer.acceptStream(byteOutput);
|
||||
bytes = byteOutput.toByteArray();
|
||||
}
|
||||
|
||||
try (ByteArrayInputStream byteInput = new ByteArrayInputStream(bytes)) {
|
||||
ZipHelper.addFileToZip(outZip, nameInZip, byteInput);
|
||||
try (var byteInput = new ByteArrayInputStream(bytes)) {
|
||||
addFileToZip(outZip, nameInZip, byteInput);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,49 +94,26 @@ public final class ZipHelper {
|
||||
* @param nameInZip the path of the file inside the zip
|
||||
* @param inputStream the content to put inside the file
|
||||
*/
|
||||
public static void addFileToZip(final ZipOutputStream outZip,
|
||||
final String nameInZip,
|
||||
final InputStream inputStream) throws IOException {
|
||||
final byte[] data = new byte[BUFFER_SIZE];
|
||||
try (BufferedInputStream bufferedInputStream =
|
||||
new BufferedInputStream(inputStream, BUFFER_SIZE)) {
|
||||
final ZipEntry entry = new ZipEntry(nameInZip);
|
||||
outZip.putNextEntry(entry);
|
||||
int count;
|
||||
while ((count = bufferedInputStream.read(data, 0, BUFFER_SIZE)) != -1) {
|
||||
outZip.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
private static void addFileToZip(final ZipOutputStream outZip,
|
||||
final String nameInZip,
|
||||
final InputStream inputStream) throws IOException {
|
||||
outZip.putNextEntry(new ZipEntry(nameInZip));
|
||||
inputStream.transferTo(outZip);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will extract data from ZipInputStream. Caution this will overwrite the original file.
|
||||
* This will extract data from ZipInputStream. Caution, this will overwrite the original file.
|
||||
*
|
||||
* @param zipFile the zip file to extract from
|
||||
* @param nameInZip the path of the file inside the zip
|
||||
* @param fileOnDisk the path of the file on the disk where the data should be extracted to
|
||||
* @param path the path of the file on the disk where the data should be extracted to
|
||||
* @return will return true if the file was found within the zip file
|
||||
*/
|
||||
public static boolean extractFileFromZip(final StoredFileHelper zipFile,
|
||||
final String nameInZip,
|
||||
final String fileOnDisk) throws IOException {
|
||||
return extractFileFromZip(zipFile, nameInZip, input -> {
|
||||
// delete old file first
|
||||
final File oldFile = new File(fileOnDisk);
|
||||
if (oldFile.exists()) {
|
||||
if (!oldFile.delete()) {
|
||||
throw new IOException("Could not delete " + fileOnDisk);
|
||||
}
|
||||
}
|
||||
|
||||
final byte[] data = new byte[BUFFER_SIZE];
|
||||
try (FileOutputStream outFile = new FileOutputStream(fileOnDisk)) {
|
||||
int count;
|
||||
while ((count = input.read(data)) != -1) {
|
||||
outFile.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
});
|
||||
final Path path) throws IOException {
|
||||
return extractFileFromZip(zipFile, nameInZip, input ->
|
||||
Files.copy(input, path, StandardCopyOption.REPLACE_EXISTING));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -186,7 +186,15 @@ object ImageStrategy {
|
||||
fun dbUrlToImageList(url: String?): List<Image> {
|
||||
return when (url) {
|
||||
null -> listOf()
|
||||
else -> listOf(Image(url, -1, -1, ResolutionLevel.UNKNOWN))
|
||||
|
||||
else -> listOf(
|
||||
Image(
|
||||
url,
|
||||
Image.HEIGHT_UNKNOWN,
|
||||
Image.WIDTH_UNKNOWN,
|
||||
ResolutionLevel.UNKNOWN
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.schabi.newpipe.util.text
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.text.SpannableString
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.util.Linkify
|
||||
import android.util.Patterns
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.text.toHtml
|
||||
import androidx.core.text.toSpanned
|
||||
|
||||
/**
|
||||
* Takes in a CharSequence [text]
|
||||
* and makes raw HTTP URLs and HTML anchor tags clickable
|
||||
*/
|
||||
fun TextView.setTextWithLinks(text: CharSequence) {
|
||||
val spanned = SpannableString(text)
|
||||
// Using the pattern overload of addLinks since the one with the int masks strips all spans from the text before applying new ones
|
||||
Linkify.addLinks(spanned, Patterns.WEB_URL, null)
|
||||
this.text = spanned
|
||||
this.movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets text from string resource with [id] while preserving styling and allowing string format value substitution of [formatArgs]
|
||||
*/
|
||||
fun Resources.getText(@StringRes id: Int, vararg formatArgs: Any?): CharSequence = getText(id).toSpanned().toHtml().format(*formatArgs).parseAsHtml()
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="main_bg_subtitle">Uka luparu ch’allt’aña qalltañataki.</string>
|
||||
</resources>
|
||||
@@ -823,6 +823,26 @@
|
||||
<string name="player_http_403">Oynadarkən serverdən alınan HTTP xətası 403, çox güman ki, yayım URL-si müddətinin bitməsi və ya IP qadağası ilə bağlıdır</string>
|
||||
<string name="player_http_invalid_status">HTTP xətası %1$s oynadarkən serverdən alındı</string>
|
||||
<string name="youtube_player_http_403">HTTP xətası 403 oynadarkən serverdən alındı, ehtimal ki, IP qadağası və ya yayım URL-nin deobfuscation problemləri ilə bağlıdır</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s sorğuçunun bot olmadığını təsdiqləmək üçün giriş tələb edərək data təmin etməkdən imtina etdi.\n\nIP-niz %1$s tərəfindən müvəqqəti şəkildə qadağan oluna bilər, bir müddət gözləyə və ya başqa IP-yə keçə bilərsiniz (məsələn, VPN-i açıb/qapatmaqla və ya WiFi-dan mobil dataya keçməklə).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s sorğuçunun bot olmadığını təsdiqləmək üçün giriş tələb edərək data təmin etməkdən imtina etdi.\n\nIP-niz %1$s tərəfindən müvəqqəti şəkildə qadağan oluna bilər, bir müddət gözləyə və ya başqa IP-yə keçə bilərsiniz (məsələn, VPN-i açıb/qapatmaqla və ya WiFi-dan mobil dataya keçməklə).\n\nDaha çox məlumat üçün xahiş olunur <a href="%2$s">bu Tez-tez Verilən Suallar qeydinə</a> baxın.</string>
|
||||
<string name="unsupported_content_in_country">Bu məzmun hazırda seçilən məzmun ölkəsi üçün əlçatan deyil. \n\nSeçiminizi \"Tənzimləmələr > Məzmun > İlkin məzmun ölkəsi\"- dən dəyişin.</string>
|
||||
<string name="kao_dialog_warning">2025 avqustunda, Google 2026-cı ilin sentyabrından etibarən tətbiqlərin quraşdırılması Play Store xaricində quraşdırılanlar daxil olmaqla, sertifikatlaşdırılan cihazlardakı bütün Android tətbiqləri üçün tərtibatçı təsdiqlənməsini tələb edəcək deyə bəyan etdi. NewPipe tərtibatçıları bu tələblə razılaşmadığı üçün NewPipe bu vaxtdan sonra artıq sertifikatlaşdırılan Android cihazlarında işləməyəcək.</string>
|
||||
<string name="kao_dialog_more_info">Təfərrüatlar</string>
|
||||
<string name="kao_solution">Həll olunma</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">%d abunəlik ixrac olunur…</item>
|
||||
<item quantity="other">%d abunəlik ixrac olunur…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">%d abunəlik yüklənilir…</item>
|
||||
<item quantity="other">%d abunəlik yüklənilir…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">%d abunəlik idxal olunur…</item>
|
||||
<item quantity="other">%d abunəlik idxal olunur…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Abunəlikləri idxal et</string>
|
||||
<string name="export_subscriptions_title">Abunəlikləri ixrac et</string>
|
||||
<string name="import_subscriptions_summary">Əvvəlki .json ixracından abunəlikləri idxal et</string>
|
||||
<string name="export_subscriptions_summary">Abunəliklərinizi .json faylına köçürün</string>
|
||||
<string name="import_from_previous_export">Əvvəlki köçürmədən idxal et</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
@@ -830,6 +830,26 @@
|
||||
<string name="player_http_403">HTTP грешка 403, получена от сървъра по време на възпроизвеждане, вероятно причинена от изтичане на URL адреса за стрийминг или забрана на IP адреса</string>
|
||||
<string name="player_http_invalid_status">HTTP грешка %1$s получена от сървъра по време на възпроизвеждане</string>
|
||||
<string name="youtube_player_http_403">HTTP грешка 403, получена от сървъра по време на възпроизвеждане, вероятно причинена от забрана на IP адреса или проблеми с деобфускацията на URL адреси за стрийминг</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s отказа да предостави данни, като поиска вход, за да потвърди, че заявителят не е бот.\n\nВашият IP адрес може да е временно забранен от %1$s. Можете да изчакате известно време или да превключите към друг IP адрес (например като включите/изключите VPN или като превключите от WiFi към мобилни данни).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s отказа да предостави данни, като поиска вход, за да потвърди, че заявителят не е бот.\n\nВашият IP адрес може да е временно забранен от %1$s. Можете да изчакате известно време или да превключите към друг IP адрес (например като включите/изключите VPN или като превключите от WiFi към мобилни данни).\n\nМоля, вижте <a href="%2$s">тази статия с ЧЗВ</a> за повече информация.</string>
|
||||
<string name="unsupported_content_in_country">Това съдържание не е налично за текущо избраната държава на съдържанието.\n\nПроменете избора си от \"Настройки > Съдържание > Държава на съдържанието по подразбиране\".</string>
|
||||
<string name="kao_dialog_warning">През август 2025 г. Google обяви, че от септември 2026 г. инсталирането на приложения ще изисква проверка от разработчика за всички приложения за Android на сертифицирани устройства, включително тези, инсталирани извън Play Store. Тъй като разработчиците на NewPipe не са съгласни с това изискване, NewPipe вече няма да работи на сертифицирани устройства с Android след този период.</string>
|
||||
<string name="kao_dialog_more_info">Детайли</string>
|
||||
<string name="kao_solution">Решение</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Изнасяне на %d абонамент…</item>
|
||||
<item quantity="other">Изнасяне на %d абонаменти…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Зареждане на %d абонамент…</item>
|
||||
<item quantity="other">Зареждане на %d абонаменти…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Внасяне на %d абонамент…</item>
|
||||
<item quantity="other">Внасяне на %d абонаменти…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Внасяне на абонаменти</string>
|
||||
<string name="export_subscriptions_title">Изнасяне на абонаменти</string>
|
||||
<string name="import_subscriptions_summary">Внасяне на абонаменти от предишен .json файл</string>
|
||||
<string name="export_subscriptions_summary">Изнесете абонаментите си в .json файл</string>
|
||||
<string name="import_from_previous_export">Внасяне от предишно изнасяне</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -859,9 +859,32 @@
|
||||
<string name="player_http_403">Během přehrávání byla ze serveru přijata chyba HTTP 403, pravděpodobně způsobená vypršením platnosti streamingové adresy URL nebo zákazem IP adresy</string>
|
||||
<string name="player_http_invalid_status">Chyba HTTP %1$s obdržená ze serveru během přehrávání</string>
|
||||
<string name="youtube_player_http_403">Chyba HTTP 403 obdržená od serveru během přehrávání, pravděpodobně způsobená zákazem IP adresy nebo problémy s deobfuskací streamovací adresy URL</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s odmítl poskytnout data, žádá o přihlášení k potvrzení, že žadatel není bot.\n\nVaše IP adresa mohla být dočasně zakázána %1$s, můžete nějakou dobu počkat nebo přepnout na jinou IP adresu (například zapnutím/vypnutím VPN nebo přepnutím z WiFi na mobilní data).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s odmítl poskytnout data, žádá o přihlášení k potvrzení, že žadatel není bot.\n\nVaše IP adresa mohla být dočasně zablokována službou %1$s, můžete nějakou dobu počkat nebo přepnout na jinou IP adresu (například zapnutím/vypnutím VPN nebo přepnutím z Wi-Fi na mobilní data).\n\nPro více informací si přečtěte <a href="%2$s">tento záznam v FAQ</a>.</string>
|
||||
<string name="unsupported_content_in_country">Tento obsah není pro aktuálně vybranou zemi obsahu dostupný.\n\nZměňte výběr v nabídce \"Nastavení > Obsah > Výchozí země obsahu\".</string>
|
||||
<string name="kao_dialog_warning">Společnost Google oznámila, že od roku 2026/2027 budou všechny aplikace na certifikovaných zařízeních Android vyžadovat, aby vývojář odeslal své osobní identifikační údaje přímo společnosti Google. Jelikož vývojáři této aplikace s tímto požadavkem nesouhlasí, aplikace po tomto datu přestane na certifikovaných zařízeních Android fungovat.</string>
|
||||
<string name="kao_dialog_more_info">Podrobnosti</string>
|
||||
<string name="kao_solution">Řešení</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Exportování %d odběru…</item>
|
||||
<item quantity="few">Exportování %d odběrů…</item>
|
||||
<item quantity="many">Exportování %d odběrů…</item>
|
||||
<item quantity="other">Exportování %d odběrů…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Načítání %d odběru…</item>
|
||||
<item quantity="few">Načítání %d odběrů…</item>
|
||||
<item quantity="many">Načítání %d odběrů…</item>
|
||||
<item quantity="other">Načítání %d odběrů…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importování %d odběru…</item>
|
||||
<item quantity="few">Importování %d odběrů…</item>
|
||||
<item quantity="many">Importování %d odběrů…</item>
|
||||
<item quantity="other">Importování %d odběrů…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Importovat odběry</string>
|
||||
<string name="export_subscriptions_title">Exportovat odběry</string>
|
||||
<string name="import_subscriptions_summary">Importovat odběry z předchozího exportu .json</string>
|
||||
<string name="export_subscriptions_summary">Exportovat odběry do souboru .json</string>
|
||||
<string name="import_from_previous_export">Importovat z předchozího exportu</string>
|
||||
</resources>
|
||||
|
||||
@@ -242,8 +242,8 @@
|
||||
<string name="caption_auto_generated">Automatisch erzeugt</string>
|
||||
<string name="import_from">Import von</string>
|
||||
<string name="export_to">Export nach</string>
|
||||
<string name="import_ongoing">Importiere …</string>
|
||||
<string name="export_ongoing">Exportiere …</string>
|
||||
<string name="import_ongoing">Wird importiert …</string>
|
||||
<string name="export_ongoing">Wird exportiert …</string>
|
||||
<string name="import_file_title">Datei importieren</string>
|
||||
<string name="previous_export">Vorheriger Export</string>
|
||||
<string name="import_network_expensive_warning">Beachte, dass diese Aktion das Netzwerk stark belasten kann.
|
||||
@@ -845,9 +845,26 @@
|
||||
<string name="player_http_403">HTTP-Fehler 403 vom Server während der Wiedergabe erhalten, wahrscheinlich verursacht durch Ablauf der Streaming-URL oder eine IP-Sperre</string>
|
||||
<string name="player_http_invalid_status">HTTP-Fehler %1$s vom Server während der Wiedergabe erhalten</string>
|
||||
<string name="youtube_player_http_403">HTTP-Fehler 403 vom Server während der Wiedergabe erhalten, wahrscheinlich verursacht durch eine IP-Sperre oder Probleme beim Entschlüsseln der Streaming-URL</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s hat die Datenbereitstellung verweigert und verlangt eine Anmeldung, um zu bestätigen, dass es sich bei dem Anfragenden nicht um einen Bot handelt.\n\nDeine IP-Adresse wurde möglicherweise vorübergehend von %1$s gesperrt. Du kannst einige Zeit warten oder zu einer anderen IP-Adresse wechseln (z. B. durch Ein- und Ausschalten eines VPNs oder durch Wechseln von WLAN zu mobilen Daten).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s hat die Datenbereitstellung verweigert und verlangt eine Anmeldung, um zu bestätigen, dass es sich bei dem Anfragenden nicht um einen Bot handelt.\n\nDeine IP-Adresse wurde möglicherweise vorübergehend von %1$s gesperrt. Du kannst einige Zeit warten oder zu einer anderen IP-Adresse wechseln (z. B. durch Ein- und Ausschalten eines VPNs oder durch Wechseln von WLAN zu mobilen Daten).\n\nWeitere Informationen findest du unter <a href="%2$s">diesem FAQ-Eintrag</a>.</string>
|
||||
<string name="unsupported_content_in_country">Dieser Inhalt ist für das aktuell ausgewählte Land des Inhalts nicht verfügbar.\n\nÄndere die Auswahl unter „Einstellungen > Inhalt > Bevorzugtes Land des Inhalts“.</string>
|
||||
<string name="kao_dialog_warning">Google hat angekündigt, dass ab 2026/2027 alle Apps auf zertifizierten Android-Geräten nur noch funktionieren, wenn die Entwickler ihre persönlichen Identitätsdaten direkt an Google übermitteln. Da die Entwickler dieser App dieser Anforderung nicht zustimmen, wird diese App ab diesem Zeitpunkt auf zertifizierten Android-Geräten nicht mehr funktionieren.</string>
|
||||
<string name="kao_dialog_warning">Im August 2025 gab Google bekannt, dass ab September 2026 für die Installation von Apps eine Entwicklerüberprüfung für alle Android-Apps auf zertifizierten Geräten erforderlich sein wird, einschließlich derjenigen, die außerhalb des Play Store installiert wurden. Da die Entwickler von NewPipe dieser Forderung nicht nachkommen, wird NewPipe nach diesem Zeitpunkt auf zertifizierten Android-Geräten nicht mehr funktionieren.</string>
|
||||
<string name="kao_dialog_more_info">Details</string>
|
||||
<string name="kao_solution">Lösung</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">%d Abonnement wird exportiert …</item>
|
||||
<item quantity="other">%d Abonnements werden exportiert …</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">%d Abonnement wird geladen …</item>
|
||||
<item quantity="other">%d Abonnements werden geladen …</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">%d Abonnement wird importiert …</item>
|
||||
<item quantity="other">%d Abonnements werden importiert …</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Abonnements importieren</string>
|
||||
<string name="export_subscriptions_title">Abonnements exportieren</string>
|
||||
<string name="import_subscriptions_summary">Importieren von Abonnements aus einem früheren .json-Export</string>
|
||||
<string name="export_subscriptions_summary">Exportiere deine Abonnements in eine .json-Datei</string>
|
||||
<string name="import_from_previous_export">Aus vorherigem Export importieren</string>
|
||||
</resources>
|
||||
|
||||
@@ -845,6 +845,26 @@
|
||||
<string name="player_http_403">Σφάλμα HTTP 403 που ελήφθη από τον διακομιστή κατά την αναπαραγωγή, πιθανώς λόγω λήξης διεύθυνσης URL ροής ή αποκλεισμού IP</string>
|
||||
<string name="player_http_invalid_status">Σφάλμα HTTP %1$s ελήφθη από τον διακομιστή κατά την αναπαραγωγή</string>
|
||||
<string name="youtube_player_http_403">Σφάλμα HTTP 403 ελήφθη από τον διακομιστή κατά την αναπαραγωγή, πιθανώς λόγω αποκλεισμού IP ή προβλημάτων απεμπλοκής URL ροής</string>
|
||||
<string name="sign_in_confirm_not_bot_error">Ο %1$s αρνήθηκε να παράσχει δεδομένα, ζητώντας σύνδεση για να επιβεβαιώσει ότι ο αιτών δεν είναι bot.\n\nΗ IP σας ενδέχεται να έχει αποκλειστεί προσωρινά από τον %1$s. Μπορείτε να περιμένετε λίγο ή να αλλάξετε IP (για παράδειγμα, ενεργοποιώντας/απενεργοποιώντας ένα VPN ή αλλάζοντας από WiFi σε δεδομένα κινητής τηλεφωνίας).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">Ο %1$s αρνήθηκε να παράσχει δεδομένα, ζητώντας σύνδεση για να επιβεβαιώσει ότι ο αιτών δεν είναι bot.\n\nΗ IP σας ενδέχεται να έχει αποκλειστεί προσωρινά από τον %1$s. Μπορείτε να περιμένετε λίγο ή να αλλάξετε IP (για παράδειγμα, ενεργοποιώντας/απενεργοποιώντας ένα VPN ή αλλάζοντας από WiFi σε δεδομένα κινητής τηλεφωνίας).\n\nΑνατρέξτε σε<a href="%2$s">αυτήν την καταχώρηση στις Συχνές Ερωτήσεις</a> για περισσότερες πληροφορίες.</string>
|
||||
<string name="unsupported_content_in_country">Αυτό το περιεχόμενο δεν είναι διαθέσιμο για την τρέχουσα επιλεγμένη χώρα περιεχομένου.\n\nΑλλάξτε την επιλογή σας από \"Ρυθμίσεις > Περιεχόμενο > Προεπιλεγμένη χώρα περιεχομένου\".</string>
|
||||
<string name="kao_dialog_more_info">Λεπτομέρειες</string>
|
||||
<string name="kao_solution">Λύση</string>
|
||||
<string name="kao_dialog_warning">Τον Αύγουστο του 2025, η Google ανακοίνωσε ότι από τον Σεπτέμβριο του 2026, η εγκατάσταση εφαρμογών θα απαιτεί επαλήθευση προγραμματιστή για όλες τις εφαρμογές Android σε πιστοποιημένες συσκευές, συμπεριλαμβανομένων εκείνων που είναι εγκατεστημένες εκτός του Play Store. Δεδομένου ότι οι προγραμματιστές του NewPipe δεν συμφωνούν με αυτήν την απαίτηση, το NewPipe δεν θα λειτουργεί πλέον σε πιστοποιημένες συσκευές Android μετά από αυτό το χρονικό διάστημα.</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Εξαγωγή %d συνδρομής…</item>
|
||||
<item quantity="other">Εξαγωγή %d συνδρομών…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Φόρτωση %d συνδρομής…</item>
|
||||
<item quantity="other">Φόρτωση %d συνδρομών…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Εισαγωγή %d συνδρομής…</item>
|
||||
<item quantity="other">Εισαγωγή %d συνδρομών…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Εισαγωγή συνδρομών</string>
|
||||
<string name="export_subscriptions_title">Εξαγωγή συνδρομών</string>
|
||||
<string name="import_subscriptions_summary">Εισαγωγή συνδρομών από προηγούμενη εξαγωγή</string>
|
||||
<string name="export_subscriptions_summary">Εξαγωγή των συνδρομών σας σε αρχείο .json</string>
|
||||
<string name="import_from_previous_export">Εισαγωγή από προηγούμενη εξαγωγή</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -851,7 +851,7 @@
|
||||
<string name="short_billion">%sMM</string>
|
||||
<string name="unsupported_content_in_country">Este contenido no está disponible para el país seleccionado actualmente.\n\nCambia tu selección en «Ajustes > Contenido > País predefinido del contenido».</string>
|
||||
<string name="permission_display_over_apps_message">Para usar el reproductor emergente, seleccione %1$s en el siguiente menú de la configuración de Android y habilite %2$s.</string>
|
||||
<string name="kao_dialog_warning">Google ha anunciado que, a partir de 2026/2027, todas las aplicaciones en dispositivos Android certificados requerirán que los desarrolladores envíen sus datos personales de identidad directamente a Google. Como los desarrolladores de esta aplicación no están de acuerdo con este requisito, la aplicación dejará de funcionar en dispositivos Android certificados después de esa fecha.</string>
|
||||
<string name="kao_dialog_warning">En Agosto de 2025, Google ha anunciado que, a partir de 2026/2027, todas las aplicaciones en dispositivos Android certificados requerirán que los desarrolladores envíen sus datos personales de identidad directamente a Google. Como los desarrolladores de NewPipe no están de acuerdo con este requisito, la aplicación dejará de funcionar en dispositivos Android certificados después de esa fecha.</string>
|
||||
<string name="kao_dialog_more_info">Detalles</string>
|
||||
<string name="kao_solution">Solución</string>
|
||||
</resources>
|
||||
|
||||
@@ -831,5 +831,25 @@
|
||||
<string name="player_http_invalid_status">Esitamise ajal lisas server andmevoogu HTTP oleku %1$s</string>
|
||||
<string name="youtube_player_http_403">Esitamise ajal lisas server andmevoogu HTTP oleku 403 ning tavaliselt tähendab see, et sinu seadme IP-aadress on keelatud või voogedastuse võrguaadressi hägustamisvastastes meetmetes on viga</string>
|
||||
<string name="unsupported_content_in_country">See sisu pole saadaval hetkel kehtvas riigis.\n\nRiiki saad muuta: Seadistused > Sisu > Sisu vaikimisi riik.</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s keeldus andmete edastamisest ning eeldab sisselogimist tuvastamaks, et tegemist pole robotiga.\n\nLisaks võib olla juhtunud, et %1$s on lisanud sinu seadme ip-aadressi ajutisse keelunimekirja. Sa võid oodata natuke aega või vahetada võrguühendus viisi (näiteks lülitades VPN sisse/välja või kasutades WiFi asemel mobiilset internetiühendust).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s keeldus andmete edastamisest ning eeldab sisselogimist tuvastamaks, et tegemist pole robotiga.\n\nLisaks võib olla juhtunud, et %1$s on lisanud sinu seadme ip-aadressi ajutisse keelunimekirja. Sa võid oodata natuke aega või vahetada võrguühendus viisi (näiteks lülitades VPN sisse/välja või kasutades WiFi asemel mobiilset internetiühendust).\n\nLisateavet leiad <a href="%2$s">siit korduva kippumate küsimuste</a> alajaotusest.</string>
|
||||
<string name="kao_dialog_warning">2025. aasta augustis teatas Google, et alates septembrist 2026 uute rakenduste paigaldamine kõikides uutes Androidi seadmetes eeldab arendajate verifitseerimist, sealhulgas juhtudel, kui selline rakendus on paigaldatud väljastpoolt Google Play rakendustepoodi. Kuna NewPipe\'i arendajad pole sellise nõudmisega nõus, siis sellise aja saabumisel NewPipe enam ei toimi sertifitseeritud Androidi seadmetes.</string>
|
||||
<string name="kao_dialog_more_info">Üksikasjad</string>
|
||||
<string name="kao_solution">Lahendus</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Eksportimisel on %d tellimus…</item>
|
||||
<item quantity="other">Eksportimisel on %d tellimust…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Laadimisel on %d tellimus…</item>
|
||||
<item quantity="other">Laadimisel on %d tellimust…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importimisel on %d tellimus…</item>
|
||||
<item quantity="other">Importimisel on %d tellimust…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Impordi tellimusi</string>
|
||||
<string name="export_subscriptions_title">Ekspordi tellimusi</string>
|
||||
<string name="import_subscriptions_summary">Impordi tellimusi varasemeksporditud json-failist</string>
|
||||
<string name="export_subscriptions_summary">Ekspirdi oma tellimused json-faili</string>
|
||||
<string name="import_from_previous_export">Impordi tellimusi varasemeksporditud failist</string>
|
||||
</resources>
|
||||
|
||||
@@ -861,9 +861,29 @@
|
||||
<string name="player_http_403">Erreur HTTP 403 reçue du serveur pendant la lecture, probablement causée par l\'expiration de l\'URL de streaming ou une interdiction d\'IP</string>
|
||||
<string name="player_http_invalid_status">Erreur HTTP %1$s reçue du serveur pendant la lecture</string>
|
||||
<string name="youtube_player_http_403">Erreur HTTP 403 reçue du serveur pendant la lecture, probablement causée par un bannissement d\'IP ou des problèmes de désobfuscation de l\'URL de streaming</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s a refusé de fournir des données et a demandé un identifiant pour confirmer que le demandeur n\'est pas un robot.\n\nVotre adresse IP a peut-être été temporairement bannie par %1$s. Vous pouvez patienter un peu ou changer d\'adresse IP (par exemple en activant/désactivant un VPN, ou en passant du Wi-Fi aux données mobiles).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s a refusé de fournir des données et a demandé un identifiant pour confirmer que l\'auteur de la requête n\'est pas un robot.\n\nVotre adresse IP a peut-être été temporairement bloquée par %1$s. Vous pouvez patienter ou essayer une autre adresse IP (par exemple, en activant/désactivant un VPN ou en passant du Wi-Fi aux données mobiles).\n\nPour plus d\'informations, veuillez consulter <a href="%2$s">cette FAQ</a>.</string>
|
||||
<string name="unsupported_content_in_country">Ce contenu n\'est pas disponible pour le pays actuellement sélectionné.\n\nModifiez votre sélection dans « Paramètres > Contenu > Pays par défaut ».</string>
|
||||
<string name="kao_dialog_warning">Google a annoncé qu’à partir de 2026/2027, toutes les applications sur les appareils Android certifiés exigeront que les développeurs transmettent leurs informations d’identité personnelles directement à Google. Comme les développeurs de cette application n’acceptent pas cette exigence, l’application cessera de fonctionner sur les appareils Android certifiés après cette date.</string>
|
||||
<string name="kao_dialog_warning">En août 2025, Google a annoncé qu\'à compter de septembre 2026, l\'installation d\'applications nécessiterait une vérification par le développeur pour toutes les applications Android sur les appareils certifiés, y compris celles installées en dehors du Play Store. Les développeurs de NewPipe refusant cette exigence, NewPipe ne fonctionnera plus sur les appareils Android certifiés après cette date.</string>
|
||||
<string name="kao_dialog_more_info">Détails</string>
|
||||
<string name="kao_solution">Solution</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Exportation de l\'abonnement %d…</item>
|
||||
<item quantity="many">Exportation de %d abonnements…</item>
|
||||
<item quantity="other">Exportation de %d abonnements…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Chargement de l\'abonnement %d…</item>
|
||||
<item quantity="many">Chargement de %d abonnements…</item>
|
||||
<item quantity="other">Chargement de %d abonnements…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importation de l\'abonnement %d…</item>
|
||||
<item quantity="many">Importation de %d abonnements…</item>
|
||||
<item quantity="other">Importation de %d abonnements…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Importer des abonnements</string>
|
||||
<string name="export_subscriptions_title">Exporter les abonnements</string>
|
||||
<string name="import_subscriptions_summary">Importer des abonnements à partir d\'une exportation .json précédente</string>
|
||||
<string name="export_subscriptions_summary">Exportez vos abonnements dans un fichier .json</string>
|
||||
<string name="import_from_previous_export">Importer à partir d\'une exportation précédente</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="no_player_found">aucun streamer trouvé . Installez VLC?</string>
|
||||
<string name="no">non</string>
|
||||
<string name="open_in_browser">ouvrir dans le browser</string>
|
||||
<string name="open_in_popup_mode">ouvrir dans le popup mode</string>
|
||||
<string name="open_with">ouvrir avec</string>
|
||||
<string name="share">partagez</string>
|
||||
<string name="controls_download_desc">installer le fichier stream</string>
|
||||
<string name="search">chercher</string>
|
||||
<string name="settings">parameters</string>
|
||||
<string name="download">installer</string>
|
||||
<string name="install">Installer</string>
|
||||
<string name="mark_as_watched">marquer comme vu</string>
|
||||
<string name="upload_date_text">"publié le %1$s"</string>
|
||||
<string name="no_player_found_toast">aucun joueur de stream n\'est trouvé ( vous pouvez installez VLC pour jouer)</string>
|
||||
<string name="cancel">Annuler</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="yes">Oui</string>
|
||||
</resources>
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
@@ -369,7 +369,7 @@
|
||||
<string name="feed_notification_loading">Cargando transmisión…</string>
|
||||
<string name="feed_subscription_not_loaded_count">Non se cargou: %d</string>
|
||||
<string name="feed_oldest_subscription_update">Actualizada a última información: %s</string>
|
||||
<string name="feed_groups_header_title">Grupos da canle</string>
|
||||
<string name="feed_groups_header_title">Grupos da canles</string>
|
||||
<plurals name="days">
|
||||
<item quantity="one">%d día</item>
|
||||
<item quantity="other">%d días</item>
|
||||
@@ -388,7 +388,7 @@
|
||||
</plurals>
|
||||
<string name="new_seek_duration_toast">Debido ás restricións de ExoPlayer, a duración da busca estableceuse en %d segundos</string>
|
||||
<string name="remove_watched_popup_partially_watched_streams">Si, e visualizou parcialmente estes vídeos</string>
|
||||
<string name="remove_watched_popup_warning">Eliminaranse os vídeos vistos antes e despois de seren engadidos á lista de reprodución. \nEstás seguro? Isto non se pode desfacer.!</string>
|
||||
<string name="remove_watched_popup_warning">Eliminaranse as emisións vistas antes e despois de seren engadidas á lista de reprodución.\nEstás seguro?</string>
|
||||
<string name="remove_watched_popup_title">Borrar todos os vídeos vistos?</string>
|
||||
<string name="remove_watched">Eliminar o visto</string>
|
||||
<string name="systems_language">Sistema predeterminado</string>
|
||||
@@ -812,4 +812,11 @@
|
||||
<string name="channel_tab_tracks">Pistas</string>
|
||||
<string name="feed_fetch_channel_tabs_summary">Lapelas a recuperar ao actualizar o feed. Esta opción non ten efecto se a canle se actualiza no modo rápido.</string>
|
||||
<string name="always_use_exoplayer_set_output_surface_workaround_summary">Esta solución alternativa libera os códecs de video e os re-instancia cando muda a máscara, no canto de configurar a máscara directamente no códec. ExoPlayer xa emprega esta configuración nalgúns dispositivos con este problema e só afecta a Android 6 e versións posteriores.\n\nActivar esta opción pode minimizar erros de reprodución ao mudar o reprodutor de video actual ou mudar ao modo de pantalla completa</string>
|
||||
<string name="short_thousand">%sK</string>
|
||||
<string name="short_million">%sM</string>
|
||||
<string name="short_billion">%sMM</string>
|
||||
<string name="search_with_service_name">Procurar %1$s</string>
|
||||
<string name="search_with_service_name_and_filter">Procurar %1$s (%2$s)</string>
|
||||
<string name="tab_bookmarks_short">Listas de reprodución</string>
|
||||
<string name="feed_group_page_summary">Páxina do grupo de canles</string>
|
||||
</resources>
|
||||
|
||||
@@ -483,7 +483,7 @@
|
||||
<item quantity="one">%d सेकेंड</item>
|
||||
<item quantity="other">%d सेकंड्स</item>
|
||||
</plurals>
|
||||
<string name="remove_watched_popup_title">देखे गए वीडियो हटायें?</string>
|
||||
<string name="remove_watched_popup_title">देखे गए स्ट्रीम्स हटाएँ?</string>
|
||||
<string name="remove_watched">देखे गए को हटा दें</string>
|
||||
<string name="systems_language">सिस्टम डिफ़ॉल्ट</string>
|
||||
<string name="app_language_title">ऐप की भाषा</string>
|
||||
@@ -529,7 +529,7 @@
|
||||
<string name="auto_device_theme_title">ऑटोमैटिक (डिवाइस थीम)</string>
|
||||
<string name="night_theme_summary">अपनी पसंदीदा नाइट थीम चुने — %s</string>
|
||||
<string name="select_night_theme_toast">आप अपनी पसंदीदा नाइट थीम नीचे चुन सकते हैं</string>
|
||||
<string name="download_has_started">डाउनलोड शुरू हो गया है</string>
|
||||
<string name="download_has_started">डाउनलोड शुरू हुआ</string>
|
||||
<string name="restricted_video_no_stream">यह वीडियो आयु-प्रतिबंधित है।
|
||||
\nयूट्यूब की नई नीतियों के कारण न्यूपाइप किसी भी आयु प्रतिबंधित वीडियो स्ट्रीम का इस्तेमाल नहीं कर सकता है और इस कारण इसे वीडियो को प्ले करने में असमर्थ है।</string>
|
||||
<string name="peertube_instance_url_title">पियरट्यूब इंसटैंस</string>
|
||||
@@ -669,7 +669,7 @@
|
||||
<string name="show_channel_details">चैनल विवरण दिखाएं</string>
|
||||
<string name="show_original_time_ago_title">आइटम्स का असल अपलोड समय दिखाएं</string>
|
||||
<string name="show_original_time_ago_summary">सेवाओं से मूल पाठ स्ट्रीम आइटम में दिखाई देंगे</string>
|
||||
<string name="remove_watched_popup_warning">प्लेलिस्ट में शामिल, पहले और बाद में देखे जा चुके वीडियो हटा दिए जाएंगे। \nक्या यक़ीनन आप ऐसा चाह्ते हैं? इसे असंपादित नहीं किया जा सकेगा!</string>
|
||||
<string name="remove_watched_popup_warning">जो स्ट्रीम्स प्लेलिस्ट में जोड़ने से पहले या बाद में देखी जा चुकी हैं, उन्हें हटा दिया जाएगा।\nक्या यक़ीनन आप ऐसा चाह्ते हैं?</string>
|
||||
<plurals name="minutes">
|
||||
<item quantity="one">%d मिनट</item>
|
||||
<item quantity="other">%d मिनट्स</item>
|
||||
@@ -845,9 +845,9 @@
|
||||
<string name="player_http_403">पले करते समय सर्वर से HTTP error 403 मिला, शायद स्ट्रीमिंग URL एक्सपायर होने या IP बैन की वजह से हुआ</string>
|
||||
<string name="player_http_invalid_status">पले करते समय सर्वर से HTTP error %1$s मिला</string>
|
||||
<string name="youtube_player_http_403">पले करते समय सर्वर से HTTP error 403 मिला, जो शायद IP बैन या स्ट्रीमिंग URL डीओबफस्केशन की दिक्कतों की वजह से हुआ है</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s ने डेटा देने से मना कर दिया, और यह कन्फर्म करने के लिए लॉगिन मांगा कि रिक्वेस्ट करने वाला बोट नहीं है।\n\nहो सकता है कि %1$s ने आपके IP को कुछ समय के लिए बैन कर दिया हो, आप कुछ समय इंतज़ार कर सकते हैं या किसी दूसरे IP पर स्विच कर सकते हैं (जैसे VPN ऑन/ऑफ करके, या WiFi से मोबाइल डेटा पर स्विच करके)।</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s ने डेटा देने से मना कर दिया, और यह कन्फर्म करने के लिए लॉगिन मांगा कि रिक्वेस्ट करने वाला बोट नहीं है।\n\nहो सकता है कि %1$s ने आपके IP को कुछ समय के लिए बैन कर दिया हो, आप कुछ समय इंतज़ार कर सकते हैं या किसी दूसरे IP पर स्विच कर सकते हैं (जैसे VPN ऑन/ऑफ करके, या WiFi से मोबाइल डेटा पर स्विच करके)।\n\nअधिक जानकारी के लिए कृपया <a href="%2$s">यह FAQ एंट्री</a> देखें।</string>
|
||||
<string name="unsupported_content_in_country">यह कंटेंट अभी चुने गए देश के कंटेंट के लिए उपलब्ध नहीं है।\n\n\"सेटिंग्स > कंटेंट > डिफ़ॉल्ट कंटेंट देश\" से अपना चुनाव बदलें।</string>
|
||||
<string name="kao_dialog_warning">Google ने घोषणा की है कि 2026/2027 से, प्रमाणित Android डिवाइसों पर सभी ऐप्स के लिए डेवलपर्स को अपनी व्यक्तिगत पहचान संबंधी जानकारी सीधे Google को जमा करनी होगी। चूँकि इस ऐप के डेवलपर्स इस आवश्यकता से सहमत नहीं हैं, यह ऐप उस समय के बाद प्रमाणित Android डिवाइसों पर काम नहीं करेगा।</string>
|
||||
<string name="kao_dialog_warning">अगस्त 2025 में, Google ने घोषणा की कि सितंबर 2026 से, सर्टिफाइड डिवाइस पर सभी Android ऐप्स जिनमें Play Store के बाहर से इंस्टॉल किए गए ऐप्स भी शामिल हैं, को इंस्टॉल करने के लिए डेवलपर वेरिफिकेशन ज़रूरी होगा। चूंकि NewPipe के डेवलपर्स इस शर्त से सहमत नहीं हैं, इसलिए उस समय के बाद NewPipe सर्टिफाइड Android डिवाइस पर काम नहीं करेगा।</string>
|
||||
<string name="kao_dialog_more_info">विवरण</string>
|
||||
<string name="kao_solution">समाधान</string>
|
||||
</resources>
|
||||
|
||||
@@ -816,9 +816,26 @@
|
||||
<string name="player_http_403">A lejátszás közben a kiszolgáló 403-as HTTP-hibát adott vissza, valószínűleg a közvetítési hivatkozás érvényessége lejárt vagy a IP-tiltás miatt</string>
|
||||
<string name="player_http_invalid_status">HTTP-hiba (%1$s) érkezett a kiszolgálótól a lejátszás során</string>
|
||||
<string name="youtube_player_http_403">HTTP 403-as hiba érkezett a kiszolgálótól a lejátszás közben, valószínűleg IP-tiltás vagy a közvetítési hivatkozás feloldási problémák miatt</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s visszautasította az adatok szolgáltatását, és bejelentkezést kér annak megerősítésére, hogy a kérés nem robot által érkezik.\n\nElőfordulhat, hogy az IP-címét ideiglenesen letiltotta %1$s, várhat egy keveset, vagy váltson egy másik IP-címre (például VPN be-/kikapcsolásával, vagy Wi-Fi-ről mobiladat-forgalomra váltva).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s visszautasította az adatok szolgáltatását, és bejelentkezést kér annak megerősítésére, hogy a kérés nem robot által érkezik.\n\nElőfordulhat, hogy az IP-címét ideiglenesen letiltotta %1$s, várhat egy keveset, vagy váltson egy másik IP-címre (például VPN be-/kikapcsolásával, vagy Wi-Fi-ről mobiladat-forgalomra váltva).\n\nTovábbi információért tekintse meg <a href="%2$s">ezt a GYIK-bejegyzést</a>.</string>
|
||||
<string name="unsupported_content_in_country">Ez a tartalom a jelenleg kiválasztott tartalom országában nem elérhető.\n\nVáltoztassa meg a „Beállítások > Tartalom >Tartalom alapértelmezett országa” menüpontban.</string>
|
||||
<string name="kao_dialog_warning">A Google bejelentette, hogy 2026/2027-től minden alkalmazás a hitelesített Android-eszközökön meg fogja követelni, hogy a fejlesztők személyes azonosító adataikat közvetlenül a Google-nek adják át. Mivel ennek az alkalmazásnak a fejlesztői nem értenek egyet ezzel a követelménnyel, az alkalmazás ezen időpont után nem fog működni a hitelesített Android-eszközökön.</string>
|
||||
<string name="kao_dialog_warning">2025 augusztusában a Google bejelentette, hogy 2026 szeptemberétől az alkalmazások telepítéséhez fejlesztői ellenőrzésre lesz szükség a tanúsított eszközökön található összes Android-alkalmazáshoz, beleértve a Play Áruházon kívül telepített alkalmazásokat is. Mivel a NewPipe fejlesztői nem értenek egyet ezzel a követelménnyel, a NewPipe ezután nem fog működni a tanúsított Android-eszközökön.</string>
|
||||
<string name="kao_dialog_more_info">Részletek</string>
|
||||
<string name="kao_solution">Megoldás</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">%d feliratkozás exportálása…</item>
|
||||
<item quantity="other">%d feliratkozások exportálása…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">%d feliratkozás betöltése…</item>
|
||||
<item quantity="other">%d feliratkozások betöltése…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">%d feliratkozás importálása…</item>
|
||||
<item quantity="other">%d feliratkozások importálása…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Feliratkozások importálása</string>
|
||||
<string name="export_subscriptions_title">Feliratkozások exportálása</string>
|
||||
<string name="import_subscriptions_summary">Feliratkozások importálása korábbi .json-fájlból</string>
|
||||
<string name="export_subscriptions_summary">Feliratkozások exportálása .json-fájlba</string>
|
||||
<string name="import_from_previous_export">Importálás korábbi exportból</string>
|
||||
</resources>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<string name="ok">Լավ</string>
|
||||
<string name="delete">Ջնջել</string>
|
||||
<string name="start">Սկսել</string>
|
||||
<string name="detail_likes_img_view_description">Հավանում եմ</string>
|
||||
<string name="detail_likes_img_view_description">Հավանումներ</string>
|
||||
<string name="detail_dislikes_img_view_description">Չեմ հավանում</string>
|
||||
<string name="clear">Մաքրել</string>
|
||||
<string name="upload_date_text">Հրապարակվել է %1$s</string>
|
||||
@@ -228,7 +228,7 @@
|
||||
<string name="sort">Դասավորել</string>
|
||||
<string name="detail_pinned_comment_view_description">Գամված մեկնաբանություն</string>
|
||||
<string name="account_terminated">Հաշիվը կասեցված է</string>
|
||||
<string name="channel_tab_about"/>
|
||||
<string name="channel_tab_about">Մասին</string>
|
||||
<string name="channel_tab_albums">Ալբոմներ</string>
|
||||
<string name="yes">Այո</string>
|
||||
<string name="no">Ոչ</string>
|
||||
@@ -243,4 +243,39 @@
|
||||
<string name="unknown_audio_track">Անհայտ</string>
|
||||
<string name="did_you_mean">Նկատի ունե՞ս «%1$s»</string>
|
||||
<string name="volume">Բարձրություն</string>
|
||||
<string name="kao_solution">Լուծում</string>
|
||||
<string name="kao_dialog_more_info">Մանրամասներ</string>
|
||||
<plurals name="replies">
|
||||
<item quantity="one">%s պատասխան</item>
|
||||
<item quantity="other">%s պատասխաններ</item>
|
||||
</plurals>
|
||||
<string name="share_playlist">Կիսվել նվագացանկով</string>
|
||||
<string name="forward">Առաջ տանել</string>
|
||||
<string name="play">Նվագել</string>
|
||||
<string name="duration">Տևողություն</string>
|
||||
<string name="rewind">Հետ տանել</string>
|
||||
<string name="open_play_queue">Բացել նվագացանկը</string>
|
||||
<string name="channel_tab_likes">Հավանումներ</string>
|
||||
<string name="channel_tab_shorts">Կարճեր</string>
|
||||
<string name="feed_show_partially_watched">Մասնակի դիտված</string>
|
||||
<string name="feed_show_watched">Ամբողչովին դիտված</string>
|
||||
<string name="on">Միացված</string>
|
||||
<string name="off">Անջատված</string>
|
||||
<string name="metadata_subscribers">Բաժանորդագրվածներ</string>
|
||||
<string name="metadata_privacy_internal">Ներքին</string>
|
||||
<string name="metadata_privacy_private">Անձնական</string>
|
||||
<string name="downloads_storage_ask_title">Հարցնել որտեղ ներբեռնել</string>
|
||||
<string name="any_network">Կամայական ցանցով</string>
|
||||
<string name="playlist_creation_success">Նվագացանկը ստեղծվեց</string>
|
||||
<string name="create_playlist">Նոր նվագացանկ</string>
|
||||
<string name="albums">Ալբոմներ</string>
|
||||
<string name="artists">Արվեստագետներ</string>
|
||||
<string name="donation_title">Նվիրել</string>
|
||||
<string name="dismiss">Անտեսել</string>
|
||||
<string name="short_thousand">%sՀզր</string>
|
||||
<string name="short_million">%sՄլն</string>
|
||||
<string name="short_billion">%sԲլն</string>
|
||||
<string name="error_snackbar_action">Ազդարարել</string>
|
||||
<string name="invalid_directory">Այդպիսի պանակ չկա</string>
|
||||
<string name="tab_bookmarks_short">Նվագացանկեր</string>
|
||||
</resources>
|
||||
|
||||
@@ -434,7 +434,7 @@
|
||||
<string name="delete_downloaded_files">Hapus berkas yang diunduh</string>
|
||||
<string name="permission_display_over_apps">Izinkan untuk ditampilkan di atas aplikasi lain</string>
|
||||
<string name="app_language_title">Bahasa apl</string>
|
||||
<string name="systems_language">Default sistem</string>
|
||||
<string name="systems_language">Bawaan sistem</string>
|
||||
<string name="done">Selesai</string>
|
||||
<string name="seek_duration_title">Durasi maju/mundur cepat</string>
|
||||
<string name="subtitle_activity_recaptcha">Tekan \"Selesai\" saat selesai</string>
|
||||
@@ -746,7 +746,7 @@
|
||||
<string name="show_channel_tabs">Tab saluran</string>
|
||||
<string name="channel_tab_shorts">Shorts</string>
|
||||
<string name="loading_metadata_title">Memuat Metadata…</string>
|
||||
<string name="feed_fetch_channel_tabs">Dapatjan tab saluran</string>
|
||||
<string name="feed_fetch_channel_tabs">Dapatkan tab saluran</string>
|
||||
<string name="channel_tab_about">Tentang</string>
|
||||
<string name="channel_tab_albums">Album</string>
|
||||
<string name="feed_fetch_channel_tabs_summary">Tab untuk didapatkan ketika memperarui umpan. Opsi ini tidak memiliki efek jika saluran diperbarui menggunakan mode cepat.</string>
|
||||
@@ -828,9 +828,12 @@
|
||||
<string name="player_http_403">Kesalahan HTTP 403 diterima dari server saat memutar, dapat disebabkan oleh URL streaming kedaluwarsa atau pemblokiran IP</string>
|
||||
<string name="player_http_invalid_status">Kesalahan HTTP %1$s diterima dari server saat memutar</string>
|
||||
<string name="youtube_player_http_403">Kesalahan HTTP 403 diterima dari server saat memutar, dapat disebabkan oleh pemblokiran IP atau masalah deobfuskasi URL streaming</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s menolak memberikan data, meminta login untuk memastikan peminta bukan bot.\n\nAlamat IP Anda mungkin telah diblokir sementara oleh %1$s, Anda dapat menunggu beberapa saat atau beralih ke alamat IP yang berbeda (misalnya dengan mengaktifkan/menonaktifkan VPN, atau beralih dari WiFi ke data seluler).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s menolak memberikan data, meminta login untuk memastikan peminta bukan bot.\n\nAlamat IP Anda mungkin telah diblokir sementara oleh %1$s, Anda dapat menunggu beberapa saat atau beralih ke alamat IP yang berbeda (misalnya dengan mengaktifkan/menonaktifkan VPN, atau beralih dari WiFi ke data seluler).\n\nHarap lihat <a href=\"%2$s\"></a>entri Pertanyaan ini</a> untuk informasi lebih lanjut.</string>
|
||||
<string name="unsupported_content_in_country">Konten ini tidak tersedia untuk negara konten yang saat ini dipilih.\n\nUbah pilihan Anda dari “Pengaturan > Konten > Negara konten bawaan”.</string>
|
||||
<string name="short_thousand">%sK</string>
|
||||
<string name="short_million">%sM</string>
|
||||
<string name="short_billion">%sB</string>
|
||||
<string name="kao_dialog_warning">Pada Agustus 2025, Google mengumumkan bahwa mulai September 2026, pemasangan aplikasi akan memerlukan verifikasi pengembang untuk semua aplikasi Android pada perangkat bersertifikasi, termasuk yang dipasang di luar Play Store. Karena pengembang NewPipe tidak menyetujui persyaratan ini, NewPipe tidak akan lagi berfungsi pada perangkat Android bersertifikasi setelah waktu tersebut.</string>
|
||||
<string name="kao_dialog_more_info">Rincian</string>
|
||||
<string name="kao_solution">Solusi</string>
|
||||
</resources>
|
||||
|
||||
@@ -859,9 +859,29 @@
|
||||
<string name="player_http_403">Errore HTTP 403 ricevuto dal server durante la riproduzione, probabilmente causato dalla scadenza dell\'URL in streaming o da un divieto dell\'IP</string>
|
||||
<string name="player_http_invalid_status">Errore HTTP %1$s ricevuto dal server durante la riproduzione</string>
|
||||
<string name="youtube_player_http_403">Errore HTTP 403 ricevuto dal server durante la riproduzione, probabilmente causato da un divieto dell\'IP o problemi di de-offuscamento dell\'URL in streaming</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s ha rifiutato di fornire i dati, chiedendo un accesso per confermare che il richiedente non sia un bot.\n\nIl tuo IP potrebbe essere stato temporaneamente vietato da %1$s, puoi aspettare un po\' di tempo o passare ad un IP diverso (ad esempio accendendo/spegnendo una VPN, o passando dal WiFi ai dati mobili).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s ha rifiutato di fornire i dati, chiedendo un accesso per confermare che il richiedente non sia un bot.\n\nIl tuo IP potrebbe essere stato temporaneamente vietato da %1$s, puoi aspettare un po\' di tempo o passare ad un IP diverso (ad esempio accendendo/spegnendo una VPN, o passando dal WiFi ai dati mobili).\n\nLeggi <a href="%2$s">questa voce nelle FAQ</a> per maggiori informazioni.</string>
|
||||
<string name="unsupported_content_in_country">Questo contenuto non è disponibile per il Paese dei contenuti attualmente selezionato.\n\nModifica la selezione da \"Impostazioni > Contenuti > Paese dei contenuti predefinito\".</string>
|
||||
<string name="kao_dialog_warning">Google ha annunciato che, a partire dal 2026/2027, tutte le app sui dispositivi Android certificati richiederanno agli sviluppatori di fornire i propri dati personali di identità direttamente a Google. Poiché gli sviluppatori di questa app non accettano tale requisito, l’app smetterà di funzionare sui dispositivi Android certificati dopo quella data.</string>
|
||||
<string name="kao_dialog_warning">Ad agosto 2025, Google ha annunciato che a partire da settembre 2026, l\'installazione di app richiederà la verifica dello sviluppatore per tutte le app Android su dispositivi certificati, compresi quelli installati al di fuori del Play Store. Poiché gli sviluppatori di NewPipe non sono d\'accordo con questo requisito, NewPipe non funzionerà più su dispositivi Android certificati dopo quel mese.</string>
|
||||
<string name="kao_dialog_more_info">Dettagli</string>
|
||||
<string name="kao_solution">Soluzione</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Esportazione di %d iscrizione…</item>
|
||||
<item quantity="many">Esportazione di %d iscrizioni…</item>
|
||||
<item quantity="other">Esportazione di %d iscrizioni…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Caricamento di %d iscrizione…</item>
|
||||
<item quantity="many">Caricamento di %d iscrizioni…</item>
|
||||
<item quantity="other">Caricamento di %d iscrizioni…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importazione di %d iscrizione…</item>
|
||||
<item quantity="many">Importazione di %d iscrizioni…</item>
|
||||
<item quantity="other">Importazione di %d iscrizioni…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Importa iscrizioni</string>
|
||||
<string name="export_subscriptions_title">Esporta iscrizioni</string>
|
||||
<string name="import_subscriptions_summary">Importa iscrizioni da un\'esportazione .json precedente</string>
|
||||
<string name="export_subscriptions_summary">Esporta le tue iscrizioni su un file .json</string>
|
||||
<string name="import_from_previous_export">Importa da un\'esportazione precedente</string>
|
||||
</resources>
|
||||
|
||||
@@ -807,4 +807,5 @@
|
||||
<string name="kao_dialog_warning">Google は、2026/2027 年から、認定 Android デバイス上のすべてのアプリについて、開発者が個人の身元情報を直接 Google に提出することを必須にすると発表しました。本アプリの開発者はこの要件に同意していないため、このアプリはその時点以降、認定 Android デバイス上で動作しなくなります。</string>
|
||||
<string name="kao_dialog_more_info">詳細</string>
|
||||
<string name="kao_solution">解決</string>
|
||||
<string name="short_billion">%sB</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
@@ -223,4 +223,12 @@
|
||||
<string name="metadata_tags">Tibzimin</string>
|
||||
<string name="blank_page_summary">Asebter d ilem</string>
|
||||
<string name="settings_category_exoplayer_title">Iɣewwaṛen n ExoPlayer</string>
|
||||
<plurals name="days">
|
||||
<item quantity="one">%d n wass</item>
|
||||
<item quantity="other">%d n wussan</item>
|
||||
</plurals>
|
||||
<plurals name="videos">
|
||||
<item quantity="one">%s n tvidyut</item>
|
||||
<item quantity="other">%s n tvidyutin</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -831,9 +831,23 @@
|
||||
<string name="player_http_403">재생 중 서버에서 HTTP 403 오류를 수신했으며, 스트리밍 URL이 만료되었거나 IP 차단으로 인해 발생했을 수 있습니다</string>
|
||||
<string name="player_http_invalid_status">재생 중 서버에서 HTTP %1$s 오류를 수신했습니다</string>
|
||||
<string name="youtube_player_http_403">재생 중 서버에서 HTTP 403 오류를 수신했으며, 스트리밍 URL 역난독화 문제나 IP 차단 때문일 수 있습니다</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s에서 데이터 제공을 거부하고, 요청자가 봇이 아닌지 확인하기 위해 로그인을 요청하고 있습니다.\n\n아마 IP가 %1$s에서 임시 차단되었을 것이며, 잠시 기다리거나 다른 IP로 전환할 수 있습니다 (예를 들자면 VPN을 켜/끄거나, WiFi를 모바일 데이터로 바꾸세요).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s에서 데이터 제공을 거부하고, 요청자가 봇이 아닌지 확인하기 위해 로그인을 요청하고 있습니다.\n\n아마 IP가 %1$s에서 임시 차단되었을 것이며, 잠시 기다리거나 다른 IP로 전환할 수 있습니다 (예를 들어 VPN을 켜/끄거나, WiFi를 모바일 데이터로 바꿔 보세요).\n\n자세한 정보는 <a href="%2$s">여기 FAQ</a>를 확인하세요.</string>
|
||||
<string name="unsupported_content_in_country">이 콘텐츠는 현재 선택한 콘텐츠 지역에서 이용할 수 없습니다.\n\n\"설정 > 콘텐츠 > 기본 콘텐츠 국가\"에서 지역을 바꾸세요.</string>
|
||||
<string name="kao_dialog_warning">Google은 2026/2027년부터 인증된 Android 기기에서 모든 앱이 개발자가 본인의 개인 신원 정보를 Google에 직접 제출해야 한다고 발표했습니다. 이 앱의 개발자들은 해당 요구 사항에 동의하지 않으므로, 이 앱은 그 시점 이후 인증된 Android 기기에서 더 이상 작동하지 않습니다.</string>
|
||||
<string name="kao_dialog_warning">2025년 8월, Google은 2026년 9월부터 인증된 기기에 앱을 설치하려면 Play 스토어 외 앱을 포함한 모든 Android 앱에 대해 개발자 인증을 받아야 한다고 발표했습니다. NewPipe 개발자는 이 요구 사항에 동의하지 않으므로, 이 이후 NewPipe는 더 이상 인증된 Android 기기에서 동작하지 않을 것입니다.</string>
|
||||
<string name="kao_dialog_more_info">자세히</string>
|
||||
<string name="kao_solution">해결책</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="other">구독 %d건 내보내는 중…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="other">구독 %d건 불러오는 중…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="other">구독 %d건 가져오는 중…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">구독 가져오기</string>
|
||||
<string name="export_subscriptions_title">구독 내보내기</string>
|
||||
<string name="import_subscriptions_summary">이전에 내보낸 .json에서 구독을 가져옵니다</string>
|
||||
<string name="export_subscriptions_summary">구독 현황을 .json 파일로 내보냅니다</string>
|
||||
<string name="import_from_previous_export">이전 내보내기에서 가져오기</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -2,8 +2,8 @@
|
||||
<resources>
|
||||
<string name="caption_none">Nav Subtitri</string>
|
||||
<string name="playlist_thumbnail_change_success">Atskaņošanas saraksta attēls nomainīts.</string>
|
||||
<string name="playlist_creation_success">Atskaņošanas saraksts radīts</string>
|
||||
<string name="delete_playlist_prompt">Dzēst atskaņošanas sarakstu\?</string>
|
||||
<string name="playlist_creation_success">Atskaņošanas saraksts izveidots</string>
|
||||
<string name="delete_playlist_prompt">Vai tiešām vēlaties dzēst šo atskaņošanas sarakstu?</string>
|
||||
<string name="set_as_playlist_thumbnail">Iestatīt, kā atskaņošanas saraksta attēlu</string>
|
||||
<string name="add_to_playlist">Pievienot atskaņošanas sarakstam</string>
|
||||
<string name="name">Nosaukums</string>
|
||||
@@ -29,10 +29,10 @@
|
||||
<string name="new_and_hot">Jauns un populārs</string>
|
||||
<string name="top_50">Top 50</string>
|
||||
<string name="error_unable_to_load_comments">Nevarēja ielādēt komentārus</string>
|
||||
<string name="import_settings">Vai jūs vēlaties ievietot arī iestatījumus?</string>
|
||||
<string name="override_current_data">Šis pārrakstīt jūsu tagadējo uzstādījumu.</string>
|
||||
<string name="import_settings">Vai vēlaties ievietot arī iestatījumus?</string>
|
||||
<string name="override_current_data">Pašreizējie dati tiks aizstāti.</string>
|
||||
<string name="could_not_import_all_files">Uzmanību: Ne visas datnes varēja ievietot.</string>
|
||||
<string name="no_valid_zip_file">Nav derīgs ZIP fails</string>
|
||||
<string name="no_valid_zip_file">Nederīga ZIP datne</string>
|
||||
<string name="import_complete_toast">Ievietošana pabeigta</string>
|
||||
<string name="export_complete_toast">Eksportēts</string>
|
||||
<string name="select_a_kiosk">Atlasiet kiosku</string>
|
||||
@@ -47,16 +47,15 @@
|
||||
<string name="main_page_content_summary">Kādas cilnes rādīt galvenajā lapā</string>
|
||||
<string name="main_page_content">Galvenā lapa</string>
|
||||
<string name="title_most_played">Visvairāk Atskaņotais</string>
|
||||
<string name="title_last_played">Pēdējais Atskaņotais</string>
|
||||
<string name="delete_item_search_history">Vai jūs tiešām vēlaties izdzēst šo meklējumu no vēstures?</string>
|
||||
<string name="title_last_played">Pēdējais atskaņotais</string>
|
||||
<string name="delete_item_search_history">Vai tiešām vēlaties izdzēst šo vaicājumu no meklēšanas vēstures?</string>
|
||||
<string name="action_history">Vēsture</string>
|
||||
<string name="title_activity_history">Vēsture</string>
|
||||
<string name="read_full_license">Izlasīt licenci</string>
|
||||
<string name="app_license">Newpipe ir bezmaksas programmatūra: jūs varat izmantot, izpētīt, dalīties un uzlabot to jebkurā brīdī. Tieši jūs varat kopīgot un/ vai modificēt to saskaņā ar GNU Vispārējās Publiskās Licences noteikumiem, ko publicējusi Brīvās Programmatūras Fonds, vai nu 3. licences versija, vai (pēc jūsu izvēles) jebkura vēlāka versija.</string>
|
||||
<string name="app_license_title">NewPipe Licence</string>
|
||||
<string name="read_privacy_policy">Izslasīt privātuma politiku</string>
|
||||
<string name="privacy_policy_encouragement">NewPipe projekts uztver jūsu privātumu ļoti nopietni . Tāpēc lietotne nesavāc datus bez jūsu piekrišanas.
|
||||
\nNewPipe privātuma politika sīki izskaidro, kādi dati tiek nosūtīti un uzglabāti, nosūtot kļūdas ziņojumu.</string>
|
||||
<string name="privacy_policy_encouragement">Datu aizsardzība ir ļoti svarīga NewPipe projektam. Tāpēc lietotne neapkopo datus bez jūsu piekrišanas.\nNewPipe konfidencialitātes politika sīki izskaidro, kādi dati tiek nosūtīti un uzglabāti, kad nosūtiet avārijas ziņojumu.</string>
|
||||
<string name="privacy_policy_title">NewPipe Privātuna Politika</string>
|
||||
<string name="website_encouragement">Apmeklēt NewPipe mājaslapu, lai iegūtu vairāk informācijas un ziņu.</string>
|
||||
<string name="website_title">Mājaslapa</string>
|
||||
@@ -69,7 +68,7 @@
|
||||
<string name="app_description">Libre, viegla atskaņošana uz Android.</string>
|
||||
<string name="tab_licenses">Licences</string>
|
||||
<string name="tab_about">Par un BUJ</string>
|
||||
<string name="title_licenses">Trešo pušu Licences</string>
|
||||
<string name="title_licenses">Trešo pušu licences</string>
|
||||
<string name="title_activity_about">Par NewPipe</string>
|
||||
<string name="charset_most_special_characters">Lielākā daļa īpašo rakstzīmju</string>
|
||||
<string name="charset_letters_and_digits">Burti un cipari</string>
|
||||
@@ -81,7 +80,7 @@
|
||||
<string name="recaptcha_request_toast">reCAPTCHA izaicinājums dots</string>
|
||||
<string name="subtitle_activity_recaptcha">Nospiediet \"Pabeigts\", kad to atrisinat</string>
|
||||
<string name="title_activity_recaptcha">reCAPTCHA izaicinājums</string>
|
||||
<string name="one_item_deleted">1 lieta izdzēsta.</string>
|
||||
<string name="one_item_deleted">1 vienums dzēsts.</string>
|
||||
<string name="msg_popup_permission">Šī atļauja ir nepieciešama, lai
|
||||
\natvērtu popup režīmā</string>
|
||||
<string name="no_available_dir">Lūdzu nosakiet lejupielādes mapi iestatījumos vēlāk</string>
|
||||
@@ -92,13 +91,13 @@
|
||||
<string name="msg_running">NewPipe lejupielādē</string>
|
||||
<string name="msg_error">Kļūda</string>
|
||||
<string name="msg_threads">Procesi</string>
|
||||
<string name="msg_name">Faila nosaukums</string>
|
||||
<string name="msg_name">Datnes nosaukums</string>
|
||||
<string name="ok">Labi</string>
|
||||
<string name="rename">Pārsaukt</string>
|
||||
<string name="dismiss">Noraidīt</string>
|
||||
<string name="checksum">Kontrolsumma</string>
|
||||
<string name="delete">Izdzēst</string>
|
||||
<string name="create">Radīt</string>
|
||||
<string name="delete">Dzēst</string>
|
||||
<string name="create">Izveidot / Saglabāt</string>
|
||||
<string name="pause">Pauzēt</string>
|
||||
<string name="start">Sākt</string>
|
||||
<string name="no_comments">Nav komentāru</string>
|
||||
@@ -154,10 +153,10 @@
|
||||
<string name="info_labels">Kas:\nRequest:\nContent Valoda:\nContent Valsts:\nApp Valoda:\nService:\nGMT Laiks:\nPackage:\nVersion:\nOS versija:</string>
|
||||
<string name="hash_channel_description">Paziņojumi video apstrādes progresam</string>
|
||||
<string name="hash_channel_name">Video haša paziņojums</string>
|
||||
<string name="popup_remember_size_pos_summary">Atcerēties pēdējo uznirstošā loga izmēru un pozīciju</string>
|
||||
<string name="popup_remember_size_pos_summary">Atceras pēdējo uznirstošā loga izmēru un pozīciju</string>
|
||||
<string name="popup_remember_size_pos_title">Atcerēties uznirstošā loga īpašības</string>
|
||||
<string name="default_popup_resolution_title">Uznirstošā loga noklusējuma izšķirtspēja</string>
|
||||
<string name="controls_popup_title">Uznirstošs logs</string>
|
||||
<string name="default_popup_resolution_title">Noklusējuma uznirstošā loga izšķirtspēja</string>
|
||||
<string name="controls_popup_title">Skatīt uznirstošā logā</string>
|
||||
<string name="open_in_popup_mode">Atvērt uznirstošā logā</string>
|
||||
<string name="what_happened_headline">Kas notika:</string>
|
||||
<string name="what_device_headline">Informācija:</string>
|
||||
@@ -169,16 +168,16 @@
|
||||
<string name="error_report_button_text">Ziņojiet pa e-pastu</string>
|
||||
<string name="sorry_string">Piedotiet, tam nevajadzēja notikt.</string>
|
||||
<string name="permission_display_over_apps">Dot atļauju rādīt pāri citām aplikācijām</string>
|
||||
<string name="restore_defaults_confirmation">Vai jūs vēlaties atjaunot noklusējumus\?</string>
|
||||
<string name="restore_defaults">Atjaunot noklusējumus</string>
|
||||
<string name="restore_defaults_confirmation">Vai tiešām vēlaties atjaunot noklusējuma vērtības?</string>
|
||||
<string name="restore_defaults">Atjaunot noklusējuma vērtības</string>
|
||||
<string name="saved_tabs_invalid_json">Nevarēja nolasīt saglabātās cilnes, tādēļ izmanto noklusējuma</string>
|
||||
<string name="no_streams_available_download">Neviens video nav pieejams lejupielādei</string>
|
||||
<string name="error_occurred_detail">Notika kļūda: %1$s</string>
|
||||
<string name="file_name_empty_error">Faila nosaukums nevar būt tukšs</string>
|
||||
<string name="invalid_file">Fails neeksistē, vai atļauja to lasīt vai rakstīt, nav dota</string>
|
||||
<string name="invalid_source">Tāds fails/saturs neeksistē</string>
|
||||
<string name="file_name_empty_error">Datnes nosaukums nevar būt tukšs</string>
|
||||
<string name="invalid_file">Datne neeksistē vai nav dota atļauja to lasīt vai rakstīt</string>
|
||||
<string name="invalid_source">Tāda datne/saturs neeksistē</string>
|
||||
<string name="invalid_directory">Tāda mape neeksistē</string>
|
||||
<string name="missing_file">Fails pārvietots vai izdzēsts</string>
|
||||
<string name="missing_file">Datne pārvietota vai dzēsta</string>
|
||||
<string name="audio_streams_empty">Netika atrasts audio</string>
|
||||
<string name="video_streams_empty">Netika atrasti video</string>
|
||||
<string name="external_player_unsupported_link_type">Ārējie atskaņotāj neatbalsta šāda tipa saites</string>
|
||||
@@ -191,26 +190,26 @@
|
||||
<string name="parsing_error">Nevarēja apstrādāt mājaslapu</string>
|
||||
<string name="could_not_load_thumbnails">Nevarēja ielādēt visus video attēlus</string>
|
||||
<string name="network_error">Tīkla kļūda</string>
|
||||
<string name="download_to_sdcard_error_message">Lejupielādēt uz SD karti nav iespējams. Atiestatīt lejupielāžu mapes lokāciju\?</string>
|
||||
<string name="download_to_sdcard_error_message">Lejupielāde ārējā SD kartē nav iespējama. Vai tiešām vēlaties atiestatīt lejupielāžu mapi?</string>
|
||||
<string name="download_to_sdcard_error_title">Ārējā krātuve nepieejama</string>
|
||||
<string name="general_error">Kļūda</string>
|
||||
<string name="search_history_deleted">Meklēšanas vēsture izdzēsta</string>
|
||||
<string name="delete_search_history_alert">Vai tiešām izdzēst visu meklēšanas vēsturi?</string>
|
||||
<string name="clear_search_history_summary">Izdzēš meklēto vārdu vēsturi</string>
|
||||
<string name="search_history_deleted">Meklēšanas vēsture dzēsta</string>
|
||||
<string name="delete_search_history_alert">Vai tiešām vēlaties izdzēst visu meklēšanas vēsturi?</string>
|
||||
<string name="clear_search_history_summary">Izdzēš visus meklēšanas vaicājumus</string>
|
||||
<string name="clear_search_history_title">Notīrīt meklēšanas vēsturi</string>
|
||||
<string name="watch_history_states_deleted">Atskaņošanas pozīcikas izdzēstas</string>
|
||||
<string name="delete_playback_states_alert">Izdzēst visas atskaņošanas pozīcijas\?</string>
|
||||
<string name="watch_history_states_deleted">Atskaņošanas pozīcijas dzēstas</string>
|
||||
<string name="delete_playback_states_alert">Vai tiešām vēlaties dzēst visas atskaņošanas pozīcijas?</string>
|
||||
<string name="clear_playback_states_summary">Izdzēš visas atskaņošanas pozīcijas</string>
|
||||
<string name="clear_playback_states_title">Izdzēst atskaņošanas pozīcijas</string>
|
||||
<string name="watch_history_deleted">Skatīšanās vēsture izdzēsta</string>
|
||||
<string name="delete_view_history_alert">Izdzēst visu skatīšanās vēsturi\?</string>
|
||||
<string name="clear_views_history_summary">Izdzēš atskaņoto videoklipu un atskaņošanas pozīciju vēsturi</string>
|
||||
<string name="clear_playback_states_title">Notīrīt atskaņošanas pozīcijas</string>
|
||||
<string name="watch_history_deleted">Skatīšanās vēsture dzēsta</string>
|
||||
<string name="delete_view_history_alert">Vai tiešām vēlaties dzēst visu skatīšanās vēsturi?</string>
|
||||
<string name="clear_views_history_summary">Izdzēš atskaņoto video / audio un atskaņošanas pozīciju vēsturi</string>
|
||||
<string name="clear_views_history_title">Notīrīt skatīšanās vēsturi</string>
|
||||
<string name="clear_cookie_summary">Notīrīt sīkfailus , kurus NewPipe saglabā, kad jūs atrisinat reCAPTCHA</string>
|
||||
<string name="clear_cookie_summary">Izdzēš sīkdatnes, kuras NewPipe uzglabā, kad jūs atrisiniet reCAPTCHA</string>
|
||||
<string name="export_data_summary">Eksportēt vēsturi, abonementus, atskaņošanas sarakstus un iestatījumus</string>
|
||||
<string name="import_data_summary">Aizstās jūsu pašreizējo vēsturi, abonementus, atskaņošanas sarakstus un (pēc izvēles) iestatījumus</string>
|
||||
<string name="recaptcha_cookies_cleared">reCAPTCHA sīkfaili tika izdzēsti</string>
|
||||
<string name="clear_cookie_title">Izdzēst reCAPTCHA sīkfailus</string>
|
||||
<string name="recaptcha_cookies_cleared">reCAPTCHA sīkdatnes dzēstas</string>
|
||||
<string name="clear_cookie_title">Notīrīt reCAPTCHA sīkdatnes</string>
|
||||
<string name="export_data_title">Eksportēt datubāzi</string>
|
||||
<string name="import_data_title">Ievietot datubāzi</string>
|
||||
<string name="switch_to_main">Pārslēgt uz Galveno</string>
|
||||
@@ -218,14 +217,14 @@
|
||||
<string name="switch_to_background">Pārslēgt uz Fonu</string>
|
||||
<string name="unknown_content">[Nezināms]</string>
|
||||
<string name="app_update_notification_channel_description">Paziņojumi par jaunām NewPipe versijām</string>
|
||||
<string name="app_update_notification_channel_name">Aplikācijas atjauninājuma paziņojums</string>
|
||||
<string name="app_update_notification_channel_name">Lietotnes atjauninājuma paziņojums</string>
|
||||
<string name="notification_channel_description">Paziņojumi priekš NewPipe atskaņotāja</string>
|
||||
<string name="notification_channel_name">NewPipe paziņojums</string>
|
||||
<string name="file">Fails</string>
|
||||
<string name="file">Datne</string>
|
||||
<string name="just_once">Tikai Vienreiz</string>
|
||||
<string name="always">Vienmēr</string>
|
||||
<string name="play_all">Atskaņot Visu</string>
|
||||
<string name="file_deleted">Fails izdzēsts</string>
|
||||
<string name="file_deleted">Datne dzēsta</string>
|
||||
<string name="undo">Atsaukt</string>
|
||||
<string name="best_resolution">Labākā izšķirtspēja</string>
|
||||
<string name="clear">Notīrīt</string>
|
||||
@@ -281,17 +280,7 @@
|
||||
<string name="content_not_supported">NewPipe šo saturu vēl neatbalsta.
|
||||
\n
|
||||
\nCerams, ka to atbalstīs nākamajā versijā.</string>
|
||||
<string name="feed_use_dedicated_fetch_method_help_text">Vai jūs domājat, ka plūsmas atjaunināšana ir pārāk lēna\? Ja tā, mēģiniet iespējot ātro atjaunināšanu (to var mainīt iestatījumos vai nospiežot pogu zemāk).
|
||||
\n
|
||||
\nNewPipe piedāvā divas plūsmas atjaunināšanas stratēģijas:
|
||||
\n• Notiek visa abonēšanas kanāla iegūšana, kas ir lēna, bet pabeigta.
|
||||
\n• izmantojot īpašu servisu, kas ir ātrs, bet parasti nav pilnīgs.
|
||||
\n
|
||||
\nAtšķirība starp abiem ir tā, ka ātrajā parasti trūkst informācijas, piemēram, video ilgums vai veids (nevar atšķirt tiešraides video no parastajiem), un tas var atgriezt mazāk vienumu.
|
||||
\n
|
||||
\nYouTube ir pakalpojuma piemērs, kas piedāvā šo ātro metodi ar savu RSS plūsmu.
|
||||
\n
|
||||
\nTātad izvēle sakrīt ar vēlamo: ātrums vai precīza informācija.</string>
|
||||
<string name="feed_use_dedicated_fetch_method_help_text">Vai jūs domājat, ka plūsmas atjaunināšana ir pārāk lēna? Ja tā, mēģiniet iespējot ātro atjaunināšanu (to var mainīt iestatījumos vai nospiežot pogu zemāk). \n \nNewPipe piedāvā divas plūsmas atjaunināšanas stratēģijas: \n• Notiek visa abonēšanas kanāla iegūšana, kas ir lēna, bet pabeigta. \n• izmantojot īpašu servisu, kas ir ātrs, bet parasti nav pilnīgs. \n \nAtšķirība starp abiem ir tā, ka ātrajā parasti trūkst informācijas, piemēram, video ilgums vai veids (nevar atšķirt tiešraides video no parastajiem), un tas var atgriezt mazāk vienumu. \n \nYouTube ir pakalpojuma piemērs, kas piedāvā šo ātro metodi ar savu RSS plūsmu. \n \nTātad izvēle sakrīt ar vēlamo: ātrums vai precīza informācija.</string>
|
||||
<string name="feed_use_dedicated_fetch_method_disable_button">Izslēgt ātro režīmu</string>
|
||||
<string name="feed_use_dedicated_fetch_method_enable_button">Ieslēgt ātro režīmu</string>
|
||||
<string name="feed_use_dedicated_fetch_method_summary">Pieejams dažos pakalpojumos, tas parasti ir daudz ātrāk, taču var atgriezt ierobežotu daudzumu informācijas un bieži arī nepilnīgu informāciju (piemēram, nav video ilguma, vienuma veida, nav tiešraides statusa)</string>
|
||||
@@ -314,7 +303,7 @@
|
||||
<string name="feed_processing_message">Notiek plūsmas apstrāde …</string>
|
||||
<string name="feed_notification_loading">Notiek plūsmas ielāde…</string>
|
||||
<string name="feed_subscription_not_loaded_count">Nav ielādēts: %d</string>
|
||||
<string name="feed_oldest_subscription_update">Plūsma pēdējoreiz atjaunināta: %s</string>
|
||||
<string name="feed_oldest_subscription_update">Atjaunināta: %s</string>
|
||||
<string name="feed_groups_header_title">Abonementu grupas</string>
|
||||
<string name="fragment_feed_title">Kas jauns</string>
|
||||
<plurals name="days">
|
||||
@@ -337,10 +326,10 @@
|
||||
<item quantity="one">%d sekundi</item>
|
||||
<item quantity="other">%d sekundes</item>
|
||||
</plurals>
|
||||
<string name="new_seek_duration_toast">ExoPlayer ierobežojumu dēļ meklēšanas ilgums tika iestatīts uz %d sekundēm</string>
|
||||
<string name="remove_watched_popup_partially_watched_streams">Jā, un daļēji skatītos video</string>
|
||||
<string name="remove_watched_popup_warning">Tiešraides, kas pirms tam skatītas un pēc tam pievienotas atskaņošanas sarakstam, tiks noņemtas. \nVai tiešām turpināt?</string>
|
||||
<string name="remove_watched_popup_title">Vai tiešām noņemt skatītās tiešraides?</string>
|
||||
<string name="new_seek_duration_toast">ExoPlayer ierobežojumu dēļ tīšanas solis tika iestatīts uz %d sekundēm</string>
|
||||
<string name="remove_watched_popup_partially_watched_streams">Jā, un daļēji skatītos</string>
|
||||
<string name="remove_watched_popup_warning">Tiešraides, kas iepriekš noskatītas un pēc tam pievienotas atskaņošanas sarakstam, tiks noņemtas. \nVai tiešām turpināt?</string>
|
||||
<string name="remove_watched_popup_title">Vai tiešām vēlaties noņemt skatītās tiešraides?</string>
|
||||
<string name="remove_watched">Noņemt skatīto</string>
|
||||
<string name="systems_language">System default</string>
|
||||
<string name="app_language_title">Lietotnes valoda</string>
|
||||
@@ -360,17 +349,17 @@
|
||||
<string name="max_retry_desc">Maksimālais mēģinājumu skaits pirms lejupielādes atcelšanas</string>
|
||||
<string name="max_retry_msg">Maksimālais atkārtoto mēģinājumu skaits</string>
|
||||
<string name="stop">Stop</string>
|
||||
<string name="delete_downloaded_files">Dzēst lejupielādētos failus</string>
|
||||
<string name="confirm_prompt">Vai vēlaties notīrīt lejupielāžu vēsturi vai izdzēst visus lejupielādētos failus\?</string>
|
||||
<string name="delete_downloaded_files">Dzēst lejupielādētās datnes</string>
|
||||
<string name="confirm_prompt">Vai tiešām vēlaties dzēst lejupielāžu vēsturi un visas lejupielādētās datnes?</string>
|
||||
<string name="clear_download_history">Notīrīt lejupielāžu vēsturi</string>
|
||||
<string name="error_download_resource_gone">Nevar atgūt šo lejupielādi</string>
|
||||
<string name="error_timeout">Savienojums pārtraukts</string>
|
||||
<string name="error_progress_lost">Progress zaudēts, jo fails tika izdzēsts</string>
|
||||
<string name="error_progress_lost">Progress zaudēts, jo datne tika dzēsta</string>
|
||||
<string name="error_insufficient_storage_left">Ierīcē nav vietas</string>
|
||||
<string name="error_postprocessing_stopped">Strādājot ar failu, NewPipe tika aizvērts</string>
|
||||
<string name="error_postprocessing_failed">Pēcapstrāde neizdevās</string>
|
||||
<string name="error_http_not_found">Nav atrasts</string>
|
||||
<string name="error_http_unsupported_range">Serveris nepieņem vairāku procesu lejupielādes, mēģiniet vēlreiz ar @ string / msg_threads = 1</string>
|
||||
<string name="error_http_unsupported_range">Serveris nepieņem daudzpavedienu lejupielādes, mēģiniet vēlreiz ar @string/msg_threads = 1</string>
|
||||
<string name="error_http_no_content">Serveris nesūta datus</string>
|
||||
<string name="error_connect_host">Nevar izveidot savienojumu ar serveri</string>
|
||||
<string name="error_unknown_host">Nevarēja atrast serveri</string>
|
||||
@@ -380,9 +369,9 @@
|
||||
<string name="show_error">Rādīt kļūdu</string>
|
||||
<string name="download_already_pending">Ir gaidāma lejupielāde ar šo nosaukumu</string>
|
||||
<string name="download_already_running">Notiek lejupielāde ar šo nosaukumu</string>
|
||||
<string name="overwrite_failed">nevar pārrakstīt failu</string>
|
||||
<string name="overwrite_finished_warning">Lejupielādēts fails ar šo nosaukumu jau pastāv</string>
|
||||
<string name="overwrite_unrelated_warning">Fails ar šo nosaukumu jau pastāv</string>
|
||||
<string name="overwrite_failed">nevar pārrakstīt datni</string>
|
||||
<string name="overwrite_finished_warning">Lejupielādētā datne ar šādu nosaukumu jau pastāv</string>
|
||||
<string name="overwrite_unrelated_warning">Datne ar šādu nosaukumu jau pastāv</string>
|
||||
<string name="overwrite">Pārrakstīt</string>
|
||||
<string name="generate_unique_name">Ģenerēt unikālu nosaukumu</string>
|
||||
<string name="permission_denied">Darbību noraidīja sistēma</string>
|
||||
@@ -394,11 +383,9 @@
|
||||
<string name="minimize_on_exit_summary">Darbība, pārslēdzoties uz citu lietotni no galvenā video atskaņotāja — %s</string>
|
||||
<string name="minimize_on_exit_title">Minimizēt, pārslēdzot aplikāciju</string>
|
||||
<string name="playback_step">Solis</string>
|
||||
<string name="skip_silence_checkbox">Klusuma laikā patīt uz priekšu</string>
|
||||
<string name="skip_silence_checkbox">Klusuma brīžos patīt uz priekšu</string>
|
||||
<string name="unhook_checkbox">Atvienot (var izraisīt traucējumus)</string>
|
||||
<string name="import_network_expensive_warning">Paturiet prātā, ka šī darbība var pieprasīt lielu datu daudzumu
|
||||
\n
|
||||
\nVai vēlaties turpināt\?</string>
|
||||
<string name="import_network_expensive_warning">Paturiet prātā, ka šī darbība var pieprasīt lielu datu daudzumu\n\nVai vēlaties turpināt?</string>
|
||||
<string name="drawer_close">Aizvērt Atvilkni</string>
|
||||
<string name="drawer_open">Atvērt Atvilkni</string>
|
||||
<string name="most_liked">Vispopulārākais</string>
|
||||
@@ -431,7 +418,7 @@
|
||||
<string name="paused">Pausēts</string>
|
||||
<string name="missions_header_pending">Gaida</string>
|
||||
<string name="missions_header_finished">Pabeigts</string>
|
||||
<string name="app_update_available_notification_title">Ir pieejams Newpipe atjauninājums!</string>
|
||||
<string name="app_update_available_notification_title">Pieejama jauna NewPipe versija!</string>
|
||||
<string name="auto">Automātiski</string>
|
||||
<string name="grid">Tīkls</string>
|
||||
<string name="list">Saraksts</string>
|
||||
@@ -446,8 +433,7 @@
|
||||
<string name="limit_data_usage_none_description">Nav ierobežojuma</string>
|
||||
<string name="decline">Nepiekrist</string>
|
||||
<string name="accept">Piekrist</string>
|
||||
<string name="start_accept_privacy_policy">Lai ievērotu Eiropas Vispārējās datu aizsardzības regulu (GDPR), mēs pievēršam jūsu uzmanību NewPipe privātuma politikai. Lūdzu, rūpīgi izlasiet to.
|
||||
\nJums ir ta jāpieņem, lai nosūtītu mums kļūdas ziņojumu.</string>
|
||||
<string name="start_accept_privacy_policy">Lai ievērotu Eiropas Vispārīgo datu aizsardzības regulu (GDPR), mēs vēršam jūsu uzmanību NewPipe konfidencialitātes politikai. Lūdzu, rūpīgi izlasiet to.\nJums tā ir jāpieņem, lai nosūtītu mums kļūdas ziņojumu.</string>
|
||||
<string name="playback_reset">Atiestatīt</string>
|
||||
<string name="playback_pitch">Tonis</string>
|
||||
<string name="playback_tempo">Temps</string>
|
||||
@@ -464,46 +450,46 @@
|
||||
<string name="show_original_time_ago_title">Rādīt oriģinālo laiku uz lietām</string>
|
||||
<string name="show_memory_leaks">Rādīt atmiņas noplūdes</string>
|
||||
<string name="caption_setting_title">Subtitri</string>
|
||||
<string name="caption_auto_generated">Automātiski radīti</string>
|
||||
<string name="caption_auto_generated">Automātiski izveidots</string>
|
||||
<string name="resize_zoom">Pietuvināt</string>
|
||||
<string name="resize_fill">Piepildīt</string>
|
||||
<string name="resize_fit">Pielāgot</string>
|
||||
<string name="content_language_title">Noklusējuma satura valoda</string>
|
||||
<string name="default_content_country_title">Noklusējuma satura valsts</string>
|
||||
<string name="unsupported_url_dialog_message">Nevarēja atpazīt saites URL. Atvērt ar citu aplikāciju\?</string>
|
||||
<string name="unsupported_url_dialog_message">Nevarēja atpazīt saites URL. Vai atvērt citā lietotnē?</string>
|
||||
<string name="unsupported_url">Neatbalstīts saites URL</string>
|
||||
<string name="show_hold_to_append_summary">Rādīt padomu, kad nospiežat fona vai popup pogu pie video \"Informācija:\"</string>
|
||||
<string name="show_hold_to_append_title">Rādīt \"Nospiediet, lai pievienotu\" padomu</string>
|
||||
<string name="autoplay_title">Automātiski atskaņot</string>
|
||||
<string name="download_dialog_title">Lejupielādēt</string>
|
||||
<string name="resume_on_audio_focus_gain_summary">Turpināt atskaņošanu pēc pārtraukumiem (piemēram, telefona zvana)</string>
|
||||
<string name="resume_on_audio_focus_gain_summary">Turpina atskaņot video pēc pārtraukumiem (piemēram, telefona zvana)</string>
|
||||
<string name="resume_on_audio_focus_gain_title">Turpināt atskaņošanu</string>
|
||||
<string name="enable_watch_history_summary">Uzglabāt skatīto video vēsturi</string>
|
||||
<string name="settings_category_clear_data_title">Dzēst datus</string>
|
||||
<string name="enable_playback_state_lists_summary">Rādīt atskaņošanas pozīcijas indikatoru sarakstos</string>
|
||||
<string name="enable_watch_history_summary">Uzglabā skatīto video vēsturi</string>
|
||||
<string name="settings_category_clear_data_title">Notīrīt datus</string>
|
||||
<string name="enable_playback_state_lists_summary">Rāda atskaņošanas pozīcijas indikatoru sarakstos</string>
|
||||
<string name="enable_playback_state_lists_title">Atskaņošanas pozīcija sarakstos</string>
|
||||
<string name="enable_playback_resume_summary">Saglabāt pēdējo atskaņošanas pozīciju</string>
|
||||
<string name="enable_playback_resume_title">Atsākt atskaņošanu</string>
|
||||
<string name="enable_watch_history_title">Skatīšanās vēsture</string>
|
||||
<string name="enable_search_history_summary">Glabāt meklēšanas vēsturi lokāli (ierīces krātuvē)</string>
|
||||
<string name="enable_search_history_title">Meklēšanas vēsture</string>
|
||||
<string name="show_search_suggestions_summary">Izvēlieties, kādus ieteikumus rādīt, rakstot meklēšanas joslā</string>
|
||||
<string name="show_search_suggestions_summary">Atlasīt, kādus ieteikumus rādīt, ievadot vaicājumu meklēšanas joslā</string>
|
||||
<string name="show_search_suggestions_title">Meklēšanas ieteikumi</string>
|
||||
<string name="auto_queue_toggle">Automātiski atskaņot</string>
|
||||
<string name="auto_queue_summary">Turpināt atskaņot videoklipus, automātiski pievienojot līdzīgus videoklipus</string>
|
||||
<string name="auto_queue_title">Automātiski atskaņot nākošo videoklipu</string>
|
||||
<string name="metadata_cache_wipe_complete_notice">Kešatmiņas metadati notīrīti</string>
|
||||
<string name="auto_queue_toggle">Automātiski pievienot</string>
|
||||
<string name="auto_queue_summary">Pievieno līdzīgus video atskaņošanas rindai, kad atskaņo pēdējo video, ja vien nav iespējota atkārtotā, malt uz riņķi, atskaņošana</string>
|
||||
<string name="auto_queue_title">Automātiski pievienot nākamo video</string>
|
||||
<string name="metadata_cache_wipe_complete_notice">Metadatu kešatmiņa notīrīta</string>
|
||||
<string name="metadata_cache_wipe_summary">Izdzēš visus kešatmiņā glabātos vietnes datus</string>
|
||||
<string name="metadata_cache_wipe_title">Notīrīt kešatmiņas metadatus</string>
|
||||
<string name="metadata_cache_wipe_title">Notīrīt kešatmiņā saglabātos metadatus</string>
|
||||
<string name="thumbnail_cache_wipe_complete_notice">Attēlu kešatmiņa notīrīta</string>
|
||||
<string name="show_meta_info_summary">Izslēdziet, lai paslēptu papildus informācijas laukus par video autoru, video saturu vai meklēšanas vaicājuma rezultātu</string>
|
||||
<string name="show_meta_info_summary">Izslēdziet, ja nevēlaties redzēt papildus informācijas laukus - video autoru, video saturu vai meklēšanas vaicājuma rezultātu</string>
|
||||
<string name="show_meta_info_title">Rādīt papildus informāciju</string>
|
||||
<string name="show_description_summary">Izslēdziet, ja nevēlaties redzēt video aprakstu un papildus informāciju</string>
|
||||
<string name="show_description_title">Rādīt video aprakstu</string>
|
||||
<string name="show_next_and_similar_title">Rādīt \'Nākošos\' un \'Līdzīgos\' videoklipus</string>
|
||||
<string name="show_comments_summary">Izslēdziet, lai paslēptu komentārus</string>
|
||||
<string name="show_next_and_similar_title">Rādīt \'Nākamos\' un \'Līdzīgos\' video</string>
|
||||
<string name="show_comments_summary">Izslēdziet, ja vēlaties paslēpt komentārus</string>
|
||||
<string name="show_comments_title">Rādīt komentārus</string>
|
||||
<string name="clear_queue_confirmation_description">Tagadējā atskaņošanas rinda tiks aizvietota</string>
|
||||
<string name="clear_queue_confirmation_description">Pašreizējā atskaņošanas rinda tiks aizstāta/pārrakstīta</string>
|
||||
<string name="clear_queue_confirmation_summary">Mainot vienu atskaņotāju uz citu, jūsu atskaņošanas rinda var tikt aizstāta/pārrakstīta</string>
|
||||
<string name="clear_queue_confirmation_title">Prasīt apstiprinājumu, pirms notīrīt atskaņošanas rindu</string>
|
||||
<string name="seek_duration_title">Ātrās uz priekšu/atpakaļ tīšanas solis</string>
|
||||
@@ -516,61 +502,61 @@
|
||||
<string name="default_video_format_title">Noklusējuma video formāts</string>
|
||||
<string name="default_audio_format_title">Noklusējuma audio formāts</string>
|
||||
<string name="play_audio">Audio</string>
|
||||
<string name="notification_colorize_summary">Ļaut Android pielāgot paziņojuma krāsu atbilstoši galvenajai krāsai video attēlā (ņemiet vērā, ka tas nav pieejams visās ierīcēs)</string>
|
||||
<string name="notification_colorize_summary">Ļauj Android pielāgot paziņojuma krāsu atbilstoši galvenajai krāsai video attēlā (ņemiet vērā, ka tas nav pieejams visās ierīcēs)</string>
|
||||
<string name="share">Kopīgot</string>
|
||||
<string name="open_with">Atvērt ar</string>
|
||||
<string name="open_in_browser">Atvērt pārlūkā</string>
|
||||
<string name="cancel">Atcelt</string>
|
||||
<string name="install">Uzstādīt</string>
|
||||
<string name="no_player_found_toast">Netika atrasts video atskaņotājs (jūs variet uzstādīt VLC, lai to atskaņotu).</string>
|
||||
<string name="no_player_found">Netika atrasts video atskaņotājs. Uzstādīt VLC?</string>
|
||||
<string name="no_player_found">Netika atrasts video atskaņotājs. Vai uzstādīt VLC?</string>
|
||||
<string name="upload_date_text">Publicēts %1$s</string>
|
||||
<string name="main_bg_subtitle">Nospiediet uz meklēšanas ikonas, lai sāktu.</string>
|
||||
<string name="main_bg_subtitle">Nospiediet uz meklēšanas ikonas, lai atrastu vēlamo saturu.</string>
|
||||
<string name="notification_colorize_title">Pielāgot paziņojumu krāsu</string>
|
||||
<string name="notification_action_nothing">Nekas</string>
|
||||
<string name="notification_action_nothing">Neko</string>
|
||||
<string name="notification_action_buffering">Ielādējas</string>
|
||||
<string name="notification_action_shuffle">Sajaukt</string>
|
||||
<string name="notification_action_repeat">Atkārtot</string>
|
||||
<string name="notification_actions_at_most_three">Jūs varat izvēlēties ne vairāk kā 3 darbības, kuras rādīs kompaktajā paziņojumā!</string>
|
||||
<string name="notification_actions_summary">Rediģējiet katru paziņojuma darbību, pieskaroties tai. Izvēlieties trīs darbības, kuras rādīs kompaktā paziņojumā, izmantojot rūtiņas labajā pusē.</string>
|
||||
<string name="notification_actions_at_most_three">Jūs variet atlasīt ne vairāk kā 3 darbības, ko rādīt kompaktajā paziņojumā!</string>
|
||||
<string name="notification_actions_summary">Rediģējiet katru zemāk redzamo paziņojuma darbību, pieskaroties tai. Atķeksējiet izvēles rūtiņas labajā pusē, lai atlasītu līdz pat trīm darbībām, kuras rādīt kompaktajā paziņojumā.</string>
|
||||
<string name="notification_action_4_title">Piektā darbības poga</string>
|
||||
<string name="notification_action_3_title">Ceturtā darbības poga</string>
|
||||
<string name="notification_action_2_title">Trešā darbības poga</string>
|
||||
<string name="notification_action_1_title">Otrā darbības poga</string>
|
||||
<string name="notification_action_0_title">Pirmā darbības poga</string>
|
||||
<string name="notification_scale_to_square_image_summary">Apgriezt video attēlu, kuru rāda paziņojumā, no 16:9 uz 1:1 proporciju (iespējams, attēls būs izstiepts)</string>
|
||||
<string name="notification_scale_to_square_image_title">Apgriezt video attēlu uz 1:1 proporciju</string>
|
||||
<string name="show_play_with_kodi_summary">Rādīt opciju atskaņot video ar Kodi mediju centru</string>
|
||||
<string name="show_play_with_kodi_title">Rādīt \"Atskaņot ar Kodi\" opciju</string>
|
||||
<string name="kore_not_found">Uzstādīt trūkstošo Kore lietotni?</string>
|
||||
<string name="play_with_kodi_title">Atskaņot ar Kodi</string>
|
||||
<string name="show_higher_resolutions_summary">Tikai dažas ierīcas var atskaņot 2K/4K videoklipus</string>
|
||||
<string name="notification_scale_to_square_image_summary">Apgriež paziņojumā redzamo video sīkattēlu no 16:9 uz 1:1 malu attiecību (iespējams, attēls būs izstiepts)</string>
|
||||
<string name="notification_scale_to_square_image_title">Apgriezt video sīkattēlu uz 1:1 malu attiecību</string>
|
||||
<string name="show_play_with_kodi_summary">Rādīt opciju atskaņot video Kodi mediju centrā</string>
|
||||
<string name="show_play_with_kodi_title">Rādīt \"Atskaņot Kodi\" opciju</string>
|
||||
<string name="kore_not_found">Uzstādīt trūkstošo Kore, tālvadības pults, lietotni?</string>
|
||||
<string name="play_with_kodi_title">Atskaņot Kodi</string>
|
||||
<string name="show_higher_resolutions_summary">Ne visas ierīcas var atskaņot 2K/4K izšķirtspējas video</string>
|
||||
<string name="show_higher_resolutions_title">Rādīt augstākas izšķirtspējas</string>
|
||||
<string name="default_resolution_title">Noklusējuma izšķirtspēja</string>
|
||||
<string name="download_path_audio_dialog_title">Izvēlieties lejupielādes mapi priekš audio failiem</string>
|
||||
<string name="download_path_audio_summary">Lejupielādētie audio faili tiek glabāti šeit</string>
|
||||
<string name="download_path_audio_dialog_title">Atlasīt lejupielādes mapi, kur glabāt audio datnes</string>
|
||||
<string name="download_path_audio_summary">Lejupielādētās audio datnes tiek glabātas šeit</string>
|
||||
<string name="download_path_audio_title">Audio lejupielādes mape</string>
|
||||
<string name="download_path_dialog_title">Izvēlaties lejupielādes mapi priekš video failiem</string>
|
||||
<string name="download_path_dialog_title">Atlasīt lejupielādes mapi, kur glabāt video datnes</string>
|
||||
<string name="download_path_summary">Lejupielādētās video datnes tiek glabātas šeit</string>
|
||||
<string name="download_path_title">Video lejupielādes mape</string>
|
||||
<string name="controls_add_to_playlist_title">Pievienot</string>
|
||||
<string name="controls_background_title">Klausīties fonā</string>
|
||||
<string name="controls_background_title">Klausīt fonā</string>
|
||||
<string name="tab_choose">Atlasiet cilni</string>
|
||||
<string name="tab_bookmarks">Saglabātie saraksti</string>
|
||||
<string name="tab_subscriptions">Abonementi</string>
|
||||
<string name="show_info">Rādīt informāciju</string>
|
||||
<string name="subscription_update_failed">Abonementu nevarēja atjaunināt</string>
|
||||
<string name="subscription_change_failed">Nevarēja mainīt abonementu</string>
|
||||
<string name="subscription_change_failed">Abonementu nevarēja mainīt</string>
|
||||
<string name="channel_unsubscribed">Atcelts kanāla abonements</string>
|
||||
<string name="unsubscribe">Atcelt abonementu</string>
|
||||
<string name="subscribed_button_title">Abonēts</string>
|
||||
<string name="subscribe_button_title">Abonēt</string>
|
||||
<string name="use_external_audio_player_title">Izmantot ārējo audio atskaņotāju</string>
|
||||
<string name="use_external_video_player_summary">Noņem skaņu dažās izšķirtspējās</string>
|
||||
<string name="use_external_video_player_summary">Dažās izšķirtspējās nav pieejami skaņas celiņi</string>
|
||||
<string name="use_external_video_player_title">Izmantot ārējo video atskaņotāju</string>
|
||||
<string name="share_dialog_title">Kopīgot ar</string>
|
||||
<string name="search_showing_result_for">Tiek rādīti %s rezultāti</string>
|
||||
<string name="did_you_mean">Vai jūs domājāt \"%1$s\"\?</string>
|
||||
<string name="search_showing_result_for">Tiek rādīti %s vaicājuma rezultāti</string>
|
||||
<string name="did_you_mean">Varbūt jūs gribējāt meklēt \"%1$s\"?</string>
|
||||
<string name="settings">Iestatījumi</string>
|
||||
<string name="search">Meklēt</string>
|
||||
<string name="controls_download_desc">Lejupielādēt video datni</string>
|
||||
@@ -600,7 +586,7 @@
|
||||
<string name="metadata_language">Valoda</string>
|
||||
<string name="metadata_age_limit">Vecuma ierobežojums</string>
|
||||
<string name="metadata_licence">License</string>
|
||||
<string name="metadata_tags">Tagi</string>
|
||||
<string name="metadata_tags">Birkas</string>
|
||||
<string name="metadata_category">Kategorija</string>
|
||||
<string name="downloads_storage_ask_summary_no_saf_notice">Jums tiks jautāts, kur saglabāt katru lejupielādi</string>
|
||||
<string name="dont_show">Nerādīt</string>
|
||||
@@ -613,18 +599,18 @@
|
||||
<string name="disable_media_tunneling_title">Izslēgt multivides tuneļošanu</string>
|
||||
<string name="disable_media_tunneling_summary">Izslēdziet multivides tuneļošanu, ja jums video atskaņošanas laikā parādās melns ekrāns vai aizķeršanās.</string>
|
||||
<string name="description_select_enable">Ieslēgt teksta atlasīšanu video aprakstā</string>
|
||||
<string name="no_dir_yet">Lejupielādes mape vēl nav iestatīta, izvēlieties noklusējuma lejupielādes mapi</string>
|
||||
<string name="no_dir_yet">Lejupielādes mape vēl nav iestatīta, atlasiet noklusējuma lejupielādes mapi tagad</string>
|
||||
<string name="main_page_content_swipe_remove">Pavelciet atlasīto elementu pa kreisi vai labi, lai to aizvāktu</string>
|
||||
<string name="local_search_suggestions">Lokālie meklēšanas ieteikumi</string>
|
||||
<string name="local_search_suggestions">Lokālos meklēšanas ieteikumus</string>
|
||||
<string name="high_quality_larger">Augstas kvalitātes (lielāks)</string>
|
||||
<string name="check_for_updates">Pārbaudīt atjauninājumus</string>
|
||||
<string name="manual_update_description">Pašrocīgi pārbaudīt jaunas versijas pieejamību</string>
|
||||
<string name="manual_update_description">Pašrocīgi veikt jaunas versijas pārbaudi</string>
|
||||
<string name="seekbar_preview_thumbnail_title">Video atskaņošanas joslas sīktēla priekšskatījums</string>
|
||||
<string name="checking_updates_toast">Pārbauda, vai ir atjauninājumi…</string>
|
||||
<string name="checking_updates_toast">Notiek atjauninājumu pārbaude…</string>
|
||||
<string name="downloads_storage_use_saf_summary_api_29">Sākot ar Android 10, tikai“Krātuves Piekļuves Sistēma” ir atbalstīta</string>
|
||||
<string name="feed_load_error_account_info">Nevarēja ielādēt straumi priekš \'%s\'.</string>
|
||||
<string name="feed_load_error">Kļūda lādējot plūsmu</string>
|
||||
<string name="feed_load_error_terminated">Autora konts tika slēgts.\nNewPipe turpmāk vairs nevarēs ielādēt šī kanāla plūsmas saturu.\nVai tiešām atteikties no šī kanāla abonēšanas?</string>
|
||||
<string name="feed_load_error_terminated">Autora konts tika slēgts.\nNewPipe turpmāk vairs nevarēs ielādēt šī kanāla saturu.\nVai tiešām vēlaties atteikties no šī kanāla abonēšanas?</string>
|
||||
<string name="feed_load_error_fast_unknown">Ātrās straumes režīms nesniedz vairāk informācijas par šo.</string>
|
||||
<string name="description_select_disable">Izslēgt teksta atlasīšanu video aprakstā</string>
|
||||
<string name="metadata_privacy_internal">Iekšeji</string>
|
||||
@@ -635,20 +621,20 @@
|
||||
<string name="metadata_privacy">Privātums</string>
|
||||
<string name="metadata_privacy_unlisted">Sarakstā neiekļauts</string>
|
||||
<string name="metadata_host">Uzņēmums</string>
|
||||
<string name="remote_search_suggestions">Servera meklēšanas ieteikumi</string>
|
||||
<string name="remote_search_suggestions">Servera meklēšanas ieteikumus</string>
|
||||
<string name="mark_as_watched">Atzīmēt kā noskatītu</string>
|
||||
<string name="processing_may_take_a_moment">Apstrādā... Var aizņemt kādu laiku</string>
|
||||
<plurals name="deleted_downloads_toast">
|
||||
<item quantity="zero">Izdzēsa %1$s lejupielāžu</item>
|
||||
<item quantity="one">Izdzēsa %1$s lejupielādi</item>
|
||||
<item quantity="other">Izdzēsa %1$s lejupielādes</item>
|
||||
<item quantity="zero">Dzēstas %1$s lejupielādes</item>
|
||||
<item quantity="one">Dzēsta %1$s lejupielāde</item>
|
||||
<item quantity="other">Dzēstas %1$s lejupielādes</item>
|
||||
</plurals>
|
||||
<plurals name="download_finished_notification">
|
||||
<item quantity="zero">%s lejupielādes pabeigtas</item>
|
||||
<item quantity="one">%s lejupielāde pabeigta</item>
|
||||
<item quantity="other">%s lejupielādes pabeigtas</item>
|
||||
</plurals>
|
||||
<string name="description_select_note">Tagad varat atlasīt tekstu video aprakstā.</string>
|
||||
<string name="description_select_note">Tagad variet atlasīt tekstu video aprakstā.</string>
|
||||
<string name="notifications">Paziņojumi</string>
|
||||
<string name="crash_the_player">Avarēt atskaņotāju</string>
|
||||
<string name="settings_category_player_notification_summary">Pielāgojiet pašlaik atskaņotās plūsmas paziņojumu</string>
|
||||
@@ -660,13 +646,13 @@
|
||||
<item quantity="one">%s jauna tiešraide</item>
|
||||
<item quantity="other">%s jaunas tiešraides</item>
|
||||
</plurals>
|
||||
<string name="streams_notification_channel_description">Paziņojumi par jaunām tiešraidēm abonementos</string>
|
||||
<string name="streams_notification_channel_description">\@string/enable_streams_notifications_summary</string>
|
||||
<string name="faq_title">Bieži uzdotie jautājumi</string>
|
||||
<string name="error_report_channel_description">Paziņojumi, lai ziņotu par kļūdām</string>
|
||||
<string name="error_report_channel_name">Kļūdas ziņojuma paziņojums</string>
|
||||
<string name="progressive_load_interval_title">Atskaņošanas ielādes intervāla lielums</string>
|
||||
<string name="error_report_notification_title">NewPipe radās kļūdu, pieskarieties, lai ziņotu</string>
|
||||
<string name="left_gesture_control_title">Kreisā žesta darbība</string>
|
||||
<string name="left_gesture_control_title">Kreisās puses žesta darbība</string>
|
||||
<string name="msg_failed_to_copy">Neizdevās kopēt starpliktuvē</string>
|
||||
<string name="unset_playlist_thumbnail">Noņemt pastāvīgo sīktēlu</string>
|
||||
<string name="check_new_streams">Pārbaudīt, vai nav jaunas tiešraides</string>
|
||||
@@ -677,21 +663,21 @@
|
||||
<string name="leak_canary_not_available">LeakCanary nav pieejams</string>
|
||||
<string name="create_error_notification">Izveidot kļūdas paziņojumu</string>
|
||||
<string name="any_network">Jebkurš tīkls</string>
|
||||
<string name="app_update_unavailable_toast">Jums ir jaunākā NewPipe versija</string>
|
||||
<string name="ignore_hardware_media_buttons_summary">Noderīgi, piemēram, lietojot austiņas ar bojātām pogām</string>
|
||||
<string name="prefer_descriptive_audio_summary">Atskaņos skaņu celiņu ar audio aprakstiem vājredzīgajiem, ja tāds ir pieejams</string>
|
||||
<string name="ignore_hardware_media_buttons_title">Ignorēt ierīces multimēdiju pogas</string>
|
||||
<string name="delete_downloaded_files_confirm">Izdzēst visus lejupielādētos failus\?</string>
|
||||
<string name="app_update_unavailable_toast">Jūs jau izmantojiet jaunāko NewPipe versiju</string>
|
||||
<string name="ignore_hardware_media_buttons_summary">Noder, piemēram, kad lietojiet austiņas ar bojātām pogām</string>
|
||||
<string name="prefer_descriptive_audio_summary">Atskaņos skaņas celiņu ar audio aprakstiem vājredzīgajiem, ja tāds ir pieejams</string>
|
||||
<string name="ignore_hardware_media_buttons_title">Ignorēt pieslēgtās ierīces multimēdiju pogas</string>
|
||||
<string name="delete_downloaded_files_confirm">Vai tiešām vēlaties dzēst visas lejupielādētās datnes?</string>
|
||||
<string name="feed_new_items">Jaunumi kanālā</string>
|
||||
<string name="prefer_original_audio_title">Dot priekšroku oriģinālajai skaņai</string>
|
||||
<string name="prefer_original_audio_summary">Atskaņos oriģinālo skaņu celiņu neatkarīgi no valodas</string>
|
||||
<string name="prefer_original_audio_summary">Atskaņos oriģinālo skaņas celiņu neatkarīgi no iestatītās valodas</string>
|
||||
<string name="prefer_descriptive_audio_title">Dot priekšroku skaņu celiņam ar audio aprakstu</string>
|
||||
<string name="left_gesture_control_summary">Izvēlēties žestu kreisajai atskaņotāja ekrāna pusei</string>
|
||||
<string name="right_gesture_control_summary">Izvēlēties žestu labajai atskaņotāja ekrāna pusei</string>
|
||||
<string name="right_gesture_control_title">Labējā žesta darbība</string>
|
||||
<string name="brightness">Spilgtums</string>
|
||||
<string name="volume">Skaļums</string>
|
||||
<string name="none">Nekā</string>
|
||||
<string name="left_gesture_control_summary">Atlasiet žestu atskaņotāja ekrāna kreisajai pusei</string>
|
||||
<string name="right_gesture_control_summary">Atlasiet žestu atskaņotāja ekrāna labajai pusei</string>
|
||||
<string name="right_gesture_control_title">Labās puses žesta darbība</string>
|
||||
<string name="brightness">Regulēt spilgtumu</string>
|
||||
<string name="volume">Regulēt skaļumu</string>
|
||||
<string name="none">Darīt neko</string>
|
||||
<string name="import_subscriptions_hint">Abonementus var ievietot vai izgūt, izmantojot 3-punktoto izvēlni augšējā labajā ekrāna stūrī</string>
|
||||
<string name="faq_description">Ja Jums rodas problēmas ar lietotni, noteikti apskatiet šīs atbildes bieži uzdotiem jautājumiem!</string>
|
||||
<string name="faq">Skatīt tīkla vietnē</string>
|
||||
@@ -701,18 +687,18 @@
|
||||
<string name="playlist_add_stream_success_duplicate">Dublikāts pievienots %d reizi(-es)</string>
|
||||
<string name="show_crash_the_player_title">Rādīt \"avarēt atskaņotāju\"</string>
|
||||
<string name="card">Karte</string>
|
||||
<string name="app_update_available_notification_text">Spiediet, lai lejupielādētu %s</string>
|
||||
<string name="remove_duplicates_title">Dzēst dublikātus\?</string>
|
||||
<string name="remove_duplicates_message">Vai vēlaties dzēst visus tiešraižu dublikātus šajā sarakstā\?</string>
|
||||
<string name="app_update_available_notification_text">Nospiediet, lai lejupielādētu %s</string>
|
||||
<string name="remove_duplicates_title">Vai tiešām vēlaties dzēst dublikātus?</string>
|
||||
<string name="remove_duplicates_message">Vai tiešām vēlaties noņemt visus dublētos vienumus šajā atskaņošanas sarakstā?</string>
|
||||
<string name="feed_show_hide_streams">Rādīt/slēpt tiešraides</string>
|
||||
<string name="fast_mode">Ātrais režīms</string>
|
||||
<string name="enable_streams_notifications_summary">Paziņot par jaunām tiešraidēm no abonementiem</string>
|
||||
<string name="enable_streams_notifications_summary">Informē, ja pieejami jauni video / audio abonementos</string>
|
||||
<string name="percent">Procenti</string>
|
||||
<string name="semitone">Pustonis</string>
|
||||
<string name="enable_streams_notifications_title">Paziņojumi par jaunām tiešraidēm</string>
|
||||
<string name="enable_streams_notifications_title">Paziņot par jauniem video / audio</string>
|
||||
<string name="streams_notifications_interval_title">Pārbaužu biežums</string>
|
||||
<string name="main_tabs_position_summary">Galvenās cilnes atlasītāja pārvietošana uz apakšu</string>
|
||||
<string name="notification_actions_summary_android13">Rediģējiet katru turpmāk norādīto paziņojuma darbību, pieskaroties tai. Pirmās trīs darbības (atskaņošana/pauze, iepriekšējais un nākamais) ir iestatītas sistēmā, un tās nevar pielāgot.</string>
|
||||
<string name="notification_actions_summary_android13">Rediģējiet katru zemāk redzamo paziņojuma darbību, pieskaroties tai. Pirmās trīs darbības (atskaņot/pauze, iepriekšējais un nākamais) ir sistēmas iestatītas, un tās nevar pielāgot.</string>
|
||||
<string name="progressive_load_interval_summary">Mainīt progresīvā satura ielādes intervāla lielumu (pašlaik %s). Mazāka vērtība var paātrināt to sākotnējo ielādi</string>
|
||||
<string name="yes">Jā</string>
|
||||
<string name="no">Nē</string>
|
||||
@@ -726,16 +712,14 @@
|
||||
<string name="channel_tab_about">Par</string>
|
||||
<string name="metadata_thumbnails">Sīkattēli</string>
|
||||
<string name="sort">Kārtot</string>
|
||||
<string name="auto_update_check_description">NewPipe var pati automātiski pārbaudīt jaunas versijas pieejamību laiku pa laikam un informēt jūs, kad tā ir pieejama.\nVai jūs tiešām gribiet ieslēgt šo funkciju?</string>
|
||||
<string name="auto_update_check_description">NewPipe pati var veikt jaunas versijas pārbaudi laiku pa laikam un informēt jūs, kad tā ir pieejama.\nVai tiešām vēlaties ieslēgt šo funkciju?</string>
|
||||
<string name="no_appropriate_file_manager_message">Netika atrasts atbilstošs failu pārvaldnieks šai darbībai.
|
||||
\nLūdzu instalējiet failu pārvaldnieku vai pamēģiniet atspējot \'%s\' lejuplādēšanas iestatījumos</string>
|
||||
<string name="audio_track_type_original">oriģinālais</string>
|
||||
<string name="streams_notifications_network_title">Nepieciešams tīkla savienojums</string>
|
||||
<string name="reset_settings_summary">Atiestatīt visus iestatījumus uz to sākotnējām vērtībām</string>
|
||||
<string name="reset_settings_summary">Atiestata visus iestatījumus uz to sākotnējām vērtībām</string>
|
||||
<string name="reset_settings_title">Atiestatīt iestatījumus</string>
|
||||
<string name="reset_all_settings">Visu iestatījumu atiestatošana atmetīs visus jūsu izvēlētos iestatījumus un restartēs aplikāciju.
|
||||
\n
|
||||
\nVai jūs esat droši, ka vēlaties turpināt?</string>
|
||||
<string name="reset_all_settings">Atiestatot iestatījumus, visi jūsu iestatītie iestatījumi tiks atmesti uz to noklusētajām vērtībām un lietotne palaista pa jaunu.\n\nVai tiešām vēlaties turpināt?</string>
|
||||
<string name="night_theme_available">Šī opcija ir pieejama tikai, ja %s ir izvēlēts kā motīvs</string>
|
||||
<string name="detail_pinned_comment_view_description">Piespraustais komentārs</string>
|
||||
<string name="notifications_disabled">Paziņojumi ir atspējoti</string>
|
||||
@@ -760,7 +744,7 @@
|
||||
<string name="show_error_snackbar">Rādīt kļūdas paziņojumu</string>
|
||||
<string name="feed_fetch_channel_tabs">Piegādāt kanālu cilnes</string>
|
||||
<string name="feed_fetch_channel_tabs_summary">Cilnes, kuras piegādāt, atjaunojot jauninājumus. Šai opcijai nav nekādas iedarbības, ja kanāls tiek atjaunots ātrajā režīmā.</string>
|
||||
<string name="disable_media_tunneling_automatic_info">Multivides tuneļošana tika atspēkota pēc noklusējuma tādēļ, ka ir zināms, ka jūsu ierīces modelis to neatbalsta.</string>
|
||||
<string name="disable_media_tunneling_automatic_info">Multivides tunelēšana tika atspējota pēc noklusējuma tādēļ, ka ir zināms, ka jūsu ierīces modelis to neatbalsta.</string>
|
||||
<string name="select_quality_external_players">Izvēlēties kvalitāti ārējiem atskaņotājiem</string>
|
||||
<string name="settings_category_exoplayer_title">ExoPlayer iestatījumi</string>
|
||||
<string name="show_channel_tabs">Kanālu cilnes</string>
|
||||
@@ -771,8 +755,8 @@
|
||||
<string name="metadata_subchannel_avatars">Apakškanālu avatāri</string>
|
||||
<string name="metadata_uploader_avatars">Augšuplādētāju avatāri</string>
|
||||
<string name="duration">Ilgums</string>
|
||||
<string name="rewind">Attīt</string>
|
||||
<string name="forward">Patīt</string>
|
||||
<string name="rewind">Attīt - tīt atpakaļ</string>
|
||||
<string name="forward">Tīt uz priekšu</string>
|
||||
<string name="image_quality_summary">Izvēlēties attēlu kvalitāti un vai vispār ielādēt attēlus, lai samazinātu datu un atmiņas lietojumu. Izmaiņas iztīra iekšējās atmiņas un diska attēlu kešatmiņu — %s</string>
|
||||
<plurals name="replies">
|
||||
<item quantity="zero">%s atbildes</item>
|
||||
@@ -838,5 +822,15 @@
|
||||
<string name="permission_display_over_apps_permission_name">“Ļaut rādīt virs citām lietotnēm”</string>
|
||||
<string name="search_with_service_name">Meklēt %1$s</string>
|
||||
<string name="search_with_service_name_and_filter">Meklēt %1$s (%2$s)</string>
|
||||
<string name="migration_info_6_7_title">SoundCloud Top 50 lapa noņemta</string>
|
||||
<string name="migration_info_6_7_title">SoundCloud Top 50 lapa likvidēta</string>
|
||||
<string name="no_feed_group_created_yet">Vēl nav izveidota neviena abonementu grupa</string>
|
||||
<string name="account_terminated_service_provides_reason">Konts slēgts\n\n%1$s norāda, ka iemesls kādēļ: %2$s</string>
|
||||
<string name="player_http_403">Atskaņošanas laikā no servera saņemta HTTP 403 kļūda, ko, iespējams, izraisīja straumēšanas URL derīguma beigu termiņš vai IP aizliegums</string>
|
||||
<string name="player_http_invalid_status">Atskaņošanas laikā no servera saņemta HTTP %1$s kļūda</string>
|
||||
<string name="youtube_player_http_403">Atskaņošanas laikā no servera saņemta HTTP 403 kļūda, ko, iespējams, izraisīja IP aizliegums vai straumēšanas URL atšifrēšanas (deobfuskācijas) problēmas</string>
|
||||
<string name="kao_dialog_warning">2025. gada augustā Google paziņoja, ka, sākot ar 2026. gada septembri, lai uzstādītu lietotnes, būs nepieciešama izstrādātāja verifikācija visām Android lietotnēm sertificētajās ierīcēs, tostarp arī tām, kuras uzstādītas ārpus Play veikala. Tā kā NewPipe izstrādātāji nepiekrīt un negrib pieņemt šo prasību, pēc šī datuma NewPipe vairs nedarbosies sertificētajās Android ierīcēs.</string>
|
||||
<string name="kao_dialog_more_info">Detalizētāka informācija</string>
|
||||
<string name="kao_solution">Risinājums</string>
|
||||
<string name="migration_info_6_7_message">SoundCloud likvidēja oriģinālos Top 50 topus. Atbilstošā cilne noņemta no jūsu galvenās lapas.</string>
|
||||
<string name="permission_display_over_apps_message">Lai varētu izmantot uznirstošo atskaņotāju, lūdzu, atlasiet %1$s šajā Android iestatījumu izvēlnē un iespējojiet %2$s.</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -847,4 +847,9 @@
|
||||
<string name="youtube_player_http_403">HTTP-fout 403 ontvangen van de server tijdens het afspelen, waarschijnlijk veroorzaakt door een ip-blokkade of problemen met de deobfuscatie van de streaming-url</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s weigerde gegevens te verstrekken en vroeg om een login om te bevestigen dat de aanvrager geen bot is.\n\nUw ip-adres is mogelijk tijdelijk geblokkeerd door %1$s. U kunt even wachten of overschakelen naar een ander ip-adres (bijvoorbeeld door een vpn in of uit te schakelen, of door over te schakelen van wifi naar mobiele data).</string>
|
||||
<string name="unsupported_content_in_country">Deze inhoud is niet beschikbaar voor het momenteel geselecteerde inhoudsland.\n\nWijzig uw selectie via ‘Instellingen > Inhoud > Standaardland voor inhoud’.</string>
|
||||
<string name="kao_dialog_more_info">Details</string>
|
||||
<string name="kao_solution">Oplossing</string>
|
||||
<string name="import_subscriptions_title">Abonnementen importeren</string>
|
||||
<string name="export_subscriptions_title">Abonnementen exporteren</string>
|
||||
<string name="import_from_previous_export">Importeren vanuit vorige export</string>
|
||||
</resources>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<string name="subscription_change_failed">ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਨੂੰ ਬਦਲਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ</string>
|
||||
<string name="show_info">ਜਾਣਕਾਰੀ ਵਿਖਾਓ</string>
|
||||
<string name="subscription_update_failed">ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਅਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ</string>
|
||||
<string name="tab_subscriptions">ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ</string>
|
||||
<string name="tab_subscriptions">ਸਬਸਕ੍ਰਿਪਸ਼ਨਜ਼</string>
|
||||
<string name="tab_bookmarks">ਬੁੱਕਮਾਰਕ ਕੀਤੀਆਂ ਪਲੇਲਿਸਟਾਂ</string>
|
||||
<string name="fragment_feed_title">ਨਵਾਂ ਕੀ ਹੈ</string>
|
||||
<string name="controls_background_title">ਬੈਕਗ੍ਰਾਊਂਡ</string>
|
||||
@@ -104,10 +104,10 @@
|
||||
<string name="switch_to_background">ਬੈਕਗ੍ਰਾਊਂਡ ਮੋਡ ਵਿੱਚ ਚਲਾਓ</string>
|
||||
<string name="switch_to_popup">ਪੌਪ-ਅਪ ਮੋਡ ਵਿੱਚ ਚਲਾਓ</string>
|
||||
<string name="switch_to_main">ਮੇਨ ਤੇ ਚਲਾਓ</string>
|
||||
<string name="import_data_title">ਡਾਟਾਬੇਸ ਆਯਾਤ ਕਰੋ</string>
|
||||
<string name="export_data_title">ਡਾਟਾਬੇਸ ਨਿਰਯਾਤ ਕਰੋ</string>
|
||||
<string name="import_data_title">ਡਾਟਾਬੇਸ ਇੰਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="export_data_title">ਡਾਟਾਬੇਸ ਐਕਸਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="import_data_summary">ਤੁਹਾਡੇ ਮੌਜੂਦਾ ਇਤਿਹਾਸ, ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ, ਪਲੇਲਿਸਟਾਂ ਅਤੇ (ਚੋਣਵੇਂ ਤੌਰ \'ਤੇ) ਸੈਟਿੰਗਾਂ ਨੂੰ ਨਵੀਆਂ ਨਾਲ ਬਦਲ ਦਿੰਦਾ ਹੈ</string>
|
||||
<string name="export_data_summary">ਇਤਿਹਾਸ, ਸੁਬਸਕ੍ਰਿਪਸ਼ਨਾਂ, ਪਲੇਲਿਸਟਾਂ ਅਤੇ ਸੈਟਿੰਗਾਂ ਨਿਰਯਾਤ ਕਰੋ</string>
|
||||
<string name="export_data_summary">ਇਤਿਹਾਸ, ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ, ਪਲੇਲਿਸਟਾਂ ਅਤੇ ਸੈਟਿੰਗਾਂ ਐਕਸਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="clear_views_history_title">ਵੇਖੇ ਗਏ ਵੀਡੀਓਜ਼ ਦੀ ਸੂਚੀ ਮਿਟਾਓ</string>
|
||||
<string name="clear_views_history_summary">ਚਲਾਈਆਂ ਗਈਆਂ ਸਟ੍ਰੀਮਾਂ ਦੇ ਇਤਿਹਾਸ ਅਤੇ ਪਲੇ-ਸਥਿਤੀਆਂ ਨੂੰ ਮਿਟਾਉਂਦਾ ਹੈ</string>
|
||||
<string name="delete_view_history_alert">ਕੀ ਵੇਖੇ ਗਏ ਵੀਡੀਓਜ਼ ਦਾ ਇਤਿਹਾਸ ਮਿਟਾ ਦਿੱਤਾ ਜਾਵੇ\?</string>
|
||||
@@ -273,7 +273,7 @@
|
||||
<string name="export_to">ਤੇ ਐਕਸਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="import_ongoing">ਇੰਪੋਰਟ ਹੋ ਰਿਹਾ ਹੈ…</string>
|
||||
<string name="export_ongoing">ਐਕਸਪੋਰਟ ਹੋ ਰਿਹਾ ਹੈ…</string>
|
||||
<string name="import_file_title">ਇੰਪੋਰਟ ਫਾਈਲ</string>
|
||||
<string name="import_file_title">ਫ਼ਾਈਲ ਇੰਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="previous_export">ਪਿੱਛਲਾ ਐਕਸਪੋਰਟ</string>
|
||||
<string name="subscriptions_import_unsuccessful">ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਨਹੀਂ ਹੋ ਸਕੀਆਂ</string>
|
||||
<string name="subscriptions_export_unsuccessful">ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਐਕਸਪੋਰਟ ਨਹੀਂ ਹੋ ਸਕੀਆਂ</string>
|
||||
@@ -430,7 +430,7 @@
|
||||
<string name="description_select_disable">ਵੇਰਵੇ \'ਚੋਂ ਲਿਖਤ ਚੁਣਨਾ ਬੰਦ ਕਰੋ</string>
|
||||
<string name="description_select_enable">ਵੇਰਵੇ \'ਚੋਂ ਲਿਖਤ ਚੁਣਨਾ ਚਾਲੂ ਕਰੋ</string>
|
||||
<string name="description_select_note">ਤੁਸੀਂ ਹੁਣ ਵੇਰਵੇ \'ਚੋਂ ਲਿਖਤ ਨੂੰ ਚੁਣ ਸਕਦੇ ਹੋ। ਨੋਟ ਕਰੋ ਕਿ ਪੰਨਾ ਜਗ-ਬੁੱਝ ਸਕਦਾ ਹੈ ਅਤੇ ਚੋਣ ਮੋਡ ਵਿੱਚ ਹੋਣ ਵੇਲੇ ਲਿੰਕ ਕਲਿੱਕ ਕਰਨ ਯੋਗ ਨਹੀਂ ਹੋ ਸਕਦੇ ਹਨ।</string>
|
||||
<string name="download_has_started">ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਹੋ ਗਿਐ</string>
|
||||
<string name="download_has_started">ਡਾਊਨਲੋਡ ਸ਼ੁਰੂ ਹੋਇਆ</string>
|
||||
<string name="select_night_theme_toast">ਤੁਸੀਂ ਆਪਣੀ ਪਸੰਦੀਦਾ ਰਾਤ ਦੀ ਥੀਮ ਹੇਠਾਂ ਚੁਣ ਸਕਦੇ ਹੋ</string>
|
||||
<string name="night_theme_summary">ਆਪਣੀ ਪਸੰਦੀਦਾ ਰਾਤ ਦੀ ਥੀਮ ਚੁਣੋ — %s</string>
|
||||
<string name="auto_device_theme_title">ਆਟੋਮੈਟਿਕ (ਡਿਵਾਈਸ ਥੀਮ)</string>
|
||||
@@ -494,8 +494,8 @@
|
||||
<item quantity="other">%d ਸਕਿੰਟ</item>
|
||||
</plurals>
|
||||
<string name="remove_watched_popup_partially_watched_streams">ਹਾਂ, ਅਤੇ ਅੱਧ-ਪਚੱਧੀਆਂ ਵੇਖੀਆਂ ਹੋਈਆਂ ਵੀ</string>
|
||||
<string name="remove_watched_popup_warning">ਪਲੇਲਿਸਟ ਵਿੱਚ ਸ਼ਾਮਿਲ ਪਹਿਲਾਂ ਤੇ ਬਾਅਦ ਵਿੱਚ ਵੇਖੇ ਜਾ ਚੁੱਕੇ ਵੀਡੀਓ ਹਟਾ ਦਿੱਤੇ ਜਾਣਗੇ। \nਕੀ ਵਾਕਿਆ ਹੀ ਤੁਸੀਂ ਇਹਨਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਵਾਪਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਣਾ!</string>
|
||||
<string name="remove_watched_popup_title">ਵੇਖੇ ਹੋਏ ਵੀਡੀਓ ਹਟਾ ਦੇਈਏ?</string>
|
||||
<string name="remove_watched_popup_warning">ਪਲੇਲਿਸਟ ਵਿੱਚ ਸ਼ਾਮਿਲ ਪਹਿਲਾਂ ਤੇ ਬਾਅਦ ਵਿੱਚ ਵੇਖੀਆਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ।\nਕੀ ਤੁਸੀਂ ਯਕੀਨਨ ਇਹ ਚਾਹੁੰਦੇ ਹੋ?</string>
|
||||
<string name="remove_watched_popup_title">ਕੀ ਵੇਖੀਆਂ ਸਟ੍ਰੀਮਾਂ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?</string>
|
||||
<string name="remove_watched">ਵੇਖੇ ਹੋਏ ਨੂੰ ਹਟਾਓ</string>
|
||||
<string name="systems_language">ਸਿਸਟਮ ਡਿਫ਼ਾਲਟ</string>
|
||||
<string name="app_language_title">ਐਪ ਦੀ ਭਾਸ਼ਾ</string>
|
||||
@@ -651,8 +651,7 @@
|
||||
<item quantity="other">%1$s ਡਾਊਨਲੋਡ ਹਟਾਏ</item>
|
||||
</plurals>
|
||||
<string name="detail_sub_channel_thumbnail_view_description">ਚੈਨਲ ਦਾ ਅਵਤਾਰ ਥੰਮਨੇਲ</string>
|
||||
<string name="no_appropriate_file_manager_message_android_10">ਇਸ ਕਾਰਜ ਲਈ ਕੋਈ ਢੁਕਵਾਂ ਫਾਈਲ ਮੈਨੇਜਰ ਨਹੀਂ ਮਿਲਿਆ।
|
||||
\nਕ੍ਰਿਪਾ ਕਰਕੇ ਸਟੋਰੇਜ ਐਕਸਿਸ ਫਰੇਮਵਰਕ SAF ਅਨੁਕੂਲ ਫਾਈਲ ਮੈਨੇਜਰ ਇੰਨਸਟਾਲ ਕਰੋ</string>
|
||||
<string name="no_appropriate_file_manager_message_android_10">ਇਸ ਕਾਰਜ ਲਈ ਕੋਈ ਢੁਕਵਾਂ ਫਾਈਲ ਮੈਨੇਜਰ ਨਹੀਂ ਮਿਲਿਆ।\nਕ੍ਰਿਪਾ ਕਰਕੇ ਸਟੋਰੇਜ ਐਕਸਿਸ ਫਰੇਮਵਰਕ SAF ਅਨੁਕੂਲ ਫਾਈਲ ਮੈਨੇਜਰ ਸਥਾਪਤ ਕਰੋ</string>
|
||||
<string name="tablet_mode_title">ਟੈਬਲੇਟ ਮੋਡ</string>
|
||||
<string name="notifications_disabled">ਨੋਟੀਫਿਕੇਸ਼ਨ ਬੰਦ ਕੀਤੇ ਹੋਏ ਹਨ</string>
|
||||
<string name="toggle_all">ਸਭ ਨੂੰ ਟੌਗਲ ਕਰੋ</string>
|
||||
@@ -684,7 +683,7 @@
|
||||
\n
|
||||
\nਤੁਹਾਡੀ ਚੋਣ ਇਸ ਗੱਲ ਤੇ ਮੁਨੱਸਰ ਕਰਦੀ ਹੈ ਕਿ ਤੁਸੀਂ ਗਤੀ ਤੇ ਸਟੀਕਤਾ ਵਿੱਚੋਂ ਕਿਸ ਨੂੰ ਪ੍ਰਾਥਮਿਕਤਾ ਦਿੰਦੇ ਹੋ।</string>
|
||||
<string name="fast_mode">ਤੇਜ ਮੋਡ</string>
|
||||
<string name="import_subscriptions_hint">3-ਡੌਟ ਮੀਨੂ ਤੋਂ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਨੂੰ ਆਯਾਤ ਜਾਂ ਨਿਰਯਾਤ ਕਰੋ</string>
|
||||
<string name="import_subscriptions_hint">3-ਡੌਟ ਮੀਨੂ ਤੋਂ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਨੂੰ ਇੰਪੋਰਟ ਜਾਂ ਐਕਸਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="app_update_unavailable_toast">ਤੁਸੀਂ ਨਿਊਪਾਈਪ ਦਾ ਨਵੀਨਤਮ ਸੰਸਕਰਣ ਚਲਾ ਰਹੇ ਹੋ</string>
|
||||
<string name="app_update_available_notification_text">%s ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ</string>
|
||||
<string name="night_theme_available">ਇਹ ਵਿਕਲਪ ਤਾਂ ਹੀ ਉਪਲਬਧ ਹੁੰਦਾ ਹੈ ਜੇਕਰ %s ਨੂੰ ਥੀਮ ਲਈ ਚੁਣਿਆ ਜਾਂਦਾ ਹੈ</string>
|
||||
@@ -827,6 +826,26 @@
|
||||
<string name="player_http_403">ਪਲੇਅ ਕਰਦੇ ਸਮੇਂ ਸਰਵਰ ਤੋਂ HTTP error 403 ਪ੍ਰਾਪਤ ਹੋਇਆ, ਜੋ ਸ਼ਾਇਦ ਸਟ੍ਰੀਮਿੰਗ URL ਦੀ ਮਿਆਦ ਪੁੱਗਣ ਜਾਂ IP ਦੀ ਪਾਬੰਦੀ ਕਾਰਨ ਹੋਈ ਹੈ</string>
|
||||
<string name="player_http_invalid_status">ਚਲਾਉਣ ਦੌਰਾਨ ਸਰਵਰ ਤੋਂ HTTP error %1$s ਪ੍ਰਾਪਤ ਹੋਇਆ</string>
|
||||
<string name="youtube_player_http_403">ਪਲੇਅ ਕਰਦੇ ਸਮੇਂ ਸਰਵਰ ਤੋਂ HTTP error 403 ਪ੍ਰਾਪਤ ਹੋਇਆ, ਜੋ ਸ਼ਾਇਦ IP ਬੈਨ ਜਾਂ ਸਟ੍ਰੀਮਿੰਗ URL ਡੀਔਬਫਸਕੇਸ਼ਨ ਸਮੱਸਿਆਵਾਂ ਕਾਰਨ ਹੋਈ ਹੈ</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s ਨੇ ਡੇਟਾ ਪ੍ਰਦਾਨ ਕਰਨ ਤੋਂ ਇਨਕਾਰ ਕਰ ਦਿੱਤਾ, ਅਤੇ ਇਹ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਲੌਗਇਨ ਕਰਨ ਲਈ ਕਿਹਾ ਕਿ ਬੇਨਤੀਕਰਤਾ ਬੋਟ ਨਹੀਂ ਹੈ।\n\nਹੋ ਸਕਦਾ ਹੈ ਕਿ %1$s ਨੇ ਤੁਹਾਡੇ IP ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਪਾਬੰਦੀ ਲਗਾਈ ਹੋਵੇ, ਤੁਸੀਂ ਕੁਝ ਸਮਾਂ ਉਡੀਕ ਕਰ ਸਕਦੇ ਹੋ ਜਾਂ ਕਿਸੇ ਵੱਖਰੇ IP \'ਤੇ ਸਵਿੱਚ ਕਰ ਸਕਦੇ ਹੋ (ਉਦਾਹਰਣ ਵਜੋਂ VPN ਨੂੰ ਚਾਲੂ/ਬੰਦ ਕਰਕੇ, ਜਾਂ WiFi ਤੋਂ ਮੋਬਾਈਲ ਡੇਟਾ \'ਤੇ ਸਵਿੱਚ ਕਰਕੇ)।</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s ਨੇ ਡੇਟਾ ਪ੍ਰਦਾਨ ਕਰਨ ਤੋਂ ਇਨਕਾਰ ਕਰ ਦਿੱਤਾ, ਅਤੇ ਇਹ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਲੌਗਇਨ ਕਰਨ ਲਈ ਕਿਹਾ ਕਿ ਬੇਨਤੀਕਰਤਾ ਬੋਟ ਨਹੀਂ ਹੈ।\n\nਹੋ ਸਕਦਾ ਹੈ ਕਿ %1$s ਨੇ ਤੁਹਾਡੇ IP ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਪਾਬੰਦੀ ਲਗਾਈ ਹੋਵੇ, ਤੁਸੀਂ ਕੁਝ ਸਮਾਂ ਉਡੀਕ ਕਰ ਸਕਦੇ ਹੋ ਜਾਂ ਕਿਸੇ ਵੱਖਰੇ IP \'ਤੇ ਸਵਿੱਚ ਕਰ ਸਕਦੇ ਹੋ (ਉਦਾਹਰਣ ਵਜੋਂ VPN ਨੂੰ ਚਾਲੂ/ਬੰਦ ਕਰਕੇ, ਜਾਂ WiFi ਤੋਂ ਮੋਬਾਈਲ ਡੇਟਾ \'ਤੇ ਸਵਿੱਚ ਕਰਕੇ)।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਕਿਰਪਾ ਕਰਕੇ <a href="%2$s">ਇਹ FAQ ਐਂਟਰੀ</a> ਵੇਖੋ।</string>
|
||||
<string name="unsupported_content_in_country">ਇਹ ਸਮੱਗਰੀ ਵਰਤਮਾਨ ਵਿੱਚ ਚੁਣੇ ਗਏ ਦੇਸ਼ ਦੀ ਸਮੱਗਰੀ ਲਈ ਉਪਲੱਬਧ ਨਹੀਂ ਹੈ।\n\n\"ਸੈਟਿੰਗਾਂ > ਸਮੱਗਰੀ > ਡਿਫ਼ਾਲਟ ਸਮੱਗਰੀ ਦੇਸ਼\" ਤੋਂ ਆਪਣੀ ਚੋਣ ਬਦਲੋ।</string>
|
||||
<string name="kao_dialog_warning">ਅਗਸਤ 2025 ਵਿੱਚ, ਗੂਗਲ ਨੇ ਐਲਾਨ ਕੀਤਾ ਕਿ ਸਤੰਬਰ 2026 ਤੋਂ, ਐਪਸ ਨੂੰ ਸਥਾਪਿਤ ਕਰਨ ਲਈ ਪ੍ਰਮਾਣਿਤ ਡਿਵਾਈਸਾਂ \'ਤੇ ਸਾਰੇ ਐਂਡਰਾਇਡ ਐਪਸ ਲਈ ਡਿਵੈਲਪਰ ਤਸਦੀਕ ਦੀ ਲੋੜ ਹੋਵੇਗੀ, ਜਿਸ ਵਿੱਚ ਪਲੇ ਸਟੋਰ ਤੋਂ ਬਾਹਰ ਸਥਾਪਤ ਕੀਤੇ ਐਪਸ ਵੀ ਸ਼ਾਮਲ ਹਨ। ਕਿਉਂਕਿ ਨਿਊਪਾਈਪ ਦੇ ਡਿਵੈਲਪਰ ਇਸ ਲੋੜ ਨਾਲ ਸਹਿਮਤ ਨਹੀਂ ਹਨ, ਇਸ ਲਈ ਨਿਊਪਾਈਪ ਉਸ ਸਮੇਂ ਤੋਂ ਬਾਅਦ ਪ੍ਰਮਾਣਿਤ ਐਂਡਰਾਇਡ ਡਿਵਾਈਸਾਂ \'ਤੇ ਕੰਮ ਨਹੀਂ ਕਰੇਗੀ।</string>
|
||||
<string name="kao_dialog_more_info">ਵੇਰਵੇ</string>
|
||||
<string name="kao_solution">ਹੱਲ</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">%d ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਐਕਸਪੋਰਟ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…</item>
|
||||
<item quantity="other">%d ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਐਕਸਪੋਰਟ ਕੀਤੀਆਂ ਜਾ ਰਹੀਆਂ ਹਨ…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">%d ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਲੋਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…</item>
|
||||
<item quantity="other">%d ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਲੋਡ ਕੀਤੀਆਂ ਜਾ ਰਹੀਆਂ ਹਨ…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">%d ਸਬਸਕ੍ਰਿਪਸ਼ਨ ਇੰਪੋਰਟ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…</item>
|
||||
<item quantity="other">%d ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਕੀਤੀਆਂ ਜਾ ਰਹੀਆਂ ਹਨ…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਇੰਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="export_subscriptions_title">ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਐਕਸਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="import_subscriptions_summary">ਪਹਿਲਾਂ ਕੀਤੇ .json ਐਕਸਪੋਰਟ ਤੋਂ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਨੂੰ ਇੰਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="export_subscriptions_summary">ਆਪਣੀਆਂ ਸਬਸਕ੍ਰਿਪਸ਼ਨਾਂ ਨੂੰ .json ਫਾਈਲ ਵਿੱਚ ਐਕਸਪੋਰਟ ਕਰੋ</string>
|
||||
<string name="import_from_previous_export">ਪਹਿਲਾਂ ਕੀਤੇ ਐਕਸਪੋਰਟ ਤੋਂ ਇੰਪੋਰਟ ਕਰੋ</string>
|
||||
</resources>
|
||||
|
||||
@@ -868,6 +868,32 @@
|
||||
<string name="player_http_403">Podczas odtwarzania otrzymano od serwera błąd HTTP 403, prawdopodobnie spowodowany wygaśnięciem adresu URL strumienia lub blokadą adresu IP.</string>
|
||||
<string name="player_http_invalid_status">Podczas odtwarzania otrzymano od serwera błąd HTTP %1$s.</string>
|
||||
<string name="youtube_player_http_403">Podczas odtwarzania otrzymano od serwera błąd HTTP 403, prawdopodobnie spowodowany blokadą adresu IP lub problemami z odszyfrowaniem adresu URL strumienia.</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s odmówił dostarczenia danych, prosząc o zalogowanie się w celu potwierdzenia, że nie jest się botem.\n\nTwoje IP mogło zostać tymczasowo zablokowane przez %1$s. Możesz chwilę poczekać lub zmienić adres IP (na przykład włączając/wyłączając VPN lub przełączając się z sieci Wi-Fi na dane komórkowe).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s odmówił dostarczenia danych, prosząc o zalogowanie się w celu potwierdzenia, że nie jest się botem.\n\nTwoje IP mogło zostać tymczasowo zablokowane przez %1$s. Możesz chwilę poczekać lub zmienić adres IP (na przykład włączając/wyłączając VPN lub przełączając się z sieci Wi-Fi na dane komórkowe).\n\nZobacz <a href="%2$s">ten wpis w FAQ</a>, aby uzyskać więcej informacji.</string>
|
||||
<string name="unsupported_content_in_country">Ta treść nie jest dostępna dla aktualnie wybranego kraju treści.\n\nZmień swój wybór w „Ustawienia > Zawartość > Domyślny kraj treści”.</string>
|
||||
<string name="kao_dialog_warning">W sierpniu 2025 r. Google ogłosił, że od września 2026 r. instalowanie aplikacji będzie wymagać weryfikacji ich twórców w przypadku wszystkich aplikacji na Androida na certyfikowanych urządzeniach, w tym tych zainstalowanych poza sklepem Google Play. Ponieważ programiści NewPipe nie zgadzają się z tym wymogiem, NewPipie nie będzie już działać na certyfikowanych urządzeniach z Androidem po tym czasie.</string>
|
||||
<string name="kao_dialog_more_info">Szczegóły</string>
|
||||
<string name="kao_solution">Rozwiązanie</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Eksportowanie %d subskrypcji…</item>
|
||||
<item quantity="few">Eksportowanie %d subskrypcji…</item>
|
||||
<item quantity="many">Eksportowanie %d subskrypcji…</item>
|
||||
<item quantity="other">Eksportowanie %d subskrypcji…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Ładowanie %d subskrypcji…</item>
|
||||
<item quantity="few">Ładowanie %d subskrypcji…</item>
|
||||
<item quantity="many">Ładowanie %d subskrypcji…</item>
|
||||
<item quantity="other">Ładowanie %d subskrypcji…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importowanie %d subskrypcji…</item>
|
||||
<item quantity="few">Importowanie %d subskrypcji…</item>
|
||||
<item quantity="many">Importowanie %d subskrypcji…</item>
|
||||
<item quantity="other">Importowanie %d subskrypcji…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Importuj subskrypcje</string>
|
||||
<string name="export_subscriptions_title">Eksportuj subskrypcje</string>
|
||||
<string name="import_subscriptions_summary">Zaimportuj subskrypcje z poprzedniego eksportu do .json</string>
|
||||
<string name="export_subscriptions_summary">Wyeksportuj swoje subskrypcje do pliku .json</string>
|
||||
<string name="import_from_previous_export">Importuj z poprzedniego eksportu</string>
|
||||
</resources>
|
||||
|
||||
@@ -859,6 +859,29 @@
|
||||
<string name="player_http_403">Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por URL de streaming expirado ou IP banido</string>
|
||||
<string name="player_http_invalid_status">Erro HTTP %1$s recebido do servidor durante reprodução</string>
|
||||
<string name="youtube_player_http_403">Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por um banimento de IP ou problemas de desofuscação de URL de streaming</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s se recusou a fornecer dados, solicitando um login para confirmar que o solicitante não é um bot.\n\nSeu IP pode ter sido temporariamente banido por %1$s. Você pode esperar um pouco ou mudar para um IP diferente (por exemplo, ativando/desativando uma VPN ou alternando de Wi-Fi para dados móveis).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s se recusou a fornecer dados, solicitando um login para confirmar que o solicitante não é um bot.\n\nSeu IP pode ter sido temporariamente banido por %1$s. Você pode esperar um pouco ou mudar para um IP diferente (por exemplo, ativando/desativando uma VPN ou alternando de Wi-Fi para dados móveis).\n\nConfira <a href="%2$s">este artigo do FAQ</a> para mais informações.</string>
|
||||
<string name="unsupported_content_in_country">Este conteúdo não está disponível para o país selecionado atualmente.\n\nAltere sua seleção acessando “Configurações > Conteúdo > País padrão do conteúdo”.</string>
|
||||
<string name="kao_dialog_warning">Em agosto de 2025, o Google anunciou que, a partir de setembro de 2026, a instalação de aplicativos exigirá a verificação do desenvolvedor para todos os aplicativos Android em dispositivos certificados, incluindo aqueles instalados fora da Play Store. Como os desenvolvedores do NewPipe não concordam com esse requisito, o NewPipe não funcionará mais em dispositivos Android certificados após essa data.</string>
|
||||
<string name="kao_dialog_more_info">Detalhes</string>
|
||||
<string name="kao_solution">Solução</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Exportando %d inscrição…</item>
|
||||
<item quantity="many">Exportando %d inscrições…</item>
|
||||
<item quantity="other">Exportando %d inscrições…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Carregando %d inscrição…</item>
|
||||
<item quantity="many">Carregando %d inscrições…</item>
|
||||
<item quantity="other">Carregando %d inscrições…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importando %d inscrição…</item>
|
||||
<item quantity="many">Importando %d inscrições…</item>
|
||||
<item quantity="other">Importando %d inscrições…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Importar inscrições</string>
|
||||
<string name="export_subscriptions_title">Exportar inscrições</string>
|
||||
<string name="import_subscriptions_summary">Importar inscrições do arquivo .json exportado anterior</string>
|
||||
<string name="export_subscriptions_summary">Exportar inscrições para arquivo .json</string>
|
||||
<string name="import_from_previous_export">Importar da exportação anterior</string>
|
||||
</resources>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
<string name="delete_downloaded_files">Eliminar ficheiros descarregados</string>
|
||||
<string name="app_language_title">Idioma da aplicação</string>
|
||||
<string name="users">Utilizadores</string>
|
||||
<string name="remove_watched_popup_warning">Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. \nTem a certeza? Esta ação não pode ser revertida!</string>
|
||||
<string name="remove_watched_popup_warning">Os vídeos que tenham sido vistos antes e após serem adicionados à lista de reprodução serão removidos. \nTem a certeza?</string>
|
||||
<plurals name="watching">
|
||||
<item quantity="one">%s a ver</item>
|
||||
<item quantity="many">%s a ver</item>
|
||||
@@ -857,8 +857,11 @@
|
||||
<string name="entry_deleted">Entrada apagada</string>
|
||||
<string name="account_terminated_service_provides_reason">Conta terminada\n\n%1$s fornece esta razão: %2$s</string>
|
||||
<string name="player_http_invalid_status">Erro HTTP %1$s recebido do servidor ao reproduzir</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s recusou fornecer dados, pedindo por um login para confirmar que o solicitante não é um bot.\n\nO seu IP pode ter sido temporariamente banido por %1$s, pode esperar algum tempo ou mudar para um IP diferente (por exemplo, a ligar / desligar uma VPN, ou a alternar de Wi-Fi para dados móveis).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s recusou fornecer dados, pedindo por um login para confirmar que o solicitante não é um bot.\n\nO seu IP pode ter sido temporariamente banido por %1$s, você pode esperar algum tempo ou mudar para um IP diferente (por exemplo, a ligar/desligar uma VPN, ou a alternar de Wi-Fi para dados móveis).\n\nConfira <a href="%2$s">este artigo do FAQ</a> para mais informações.</string>
|
||||
<string name="unsupported_content_in_country">Este conteúdo não está disponível para o país de conteúdo atualmente selecionado.\n\nAltere a sua seleção de \"Configurações > Conteúdo > País predefinido de conteúdo\".</string>
|
||||
<string name="player_http_403">Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado pela URL de streaming expirado ou IP banido</string>
|
||||
<string name="youtube_player_http_403">Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por um bloqueio de IP ou problemas de desofuscação da URL de streaming</string>
|
||||
<string name="kao_dialog_warning">Em agosto de 2025, o Google anunciou que, a partir de setembro de 2026, a instalação de apps exigirá a verificação do programador para todas as apps Android em dispositivos certificados, incluindo aqueles instalados fora da Play Store. Como os programadores do NewPipe não concordam com este requisito, o NewPipe já não funcionará em dispositivos Android certificados após essa data.</string>
|
||||
<string name="kao_dialog_more_info">Pormenores</string>
|
||||
<string name="kao_solution">Solução</string>
|
||||
</resources>
|
||||
|
||||
@@ -517,7 +517,7 @@
|
||||
<string name="restricted_video">Este vídeo está restringido a adultos.
|
||||
\n
|
||||
\nPara o poder ver, tem que ativar \"%1$s\" nas definições.</string>
|
||||
<string name="remove_watched_popup_warning">Os vídeos que tenham sido vistos antes e depois de serem adicionados à lista de reprodução serão removidos. \nTem a certeza? Esta ação não pode ser revertida!</string>
|
||||
<string name="remove_watched_popup_warning">Os vídeos que tenham sido vistos antes e após serem adicionados à lista de reprodução serão removidos. \nTem a certeza?</string>
|
||||
<string name="remove_watched_popup_partially_watched_streams">Sim e também os vídeos parcialmente vistos</string>
|
||||
<string name="remove_watched_popup_title">Remover transmissões vistas?</string>
|
||||
<string name="remove_watched">Remover visualizados</string>
|
||||
@@ -857,11 +857,11 @@
|
||||
<string name="entry_deleted">Entrada apagada</string>
|
||||
<string name="account_terminated_service_provides_reason">Conta terminada\n\n%1$s fornece esta razão: %2$s</string>
|
||||
<string name="player_http_invalid_status">Erro HTTP %1$s recebido do servidor ao reproduzir</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s recusou fornecer dados, pedindo por um login para confirmar que o solicitante não é um bot.\n\nO seu IP pode ter sido temporariamente banido por %1$s, pode esperar algum tempo ou mudar para um IP diferente (por exemplo, a ligar / desligar uma VPN, ou a alternar de Wi-Fi para dados móveis).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s recusou fornecer dados, pedindo por um login para confirmar que o solicitante não é um bot.\n\nO seu IP pode ter sido temporariamente banido por %1$s, você pode esperar algum tempo ou mudar para um IP diferente (por exemplo, a ligar/desligar uma VPN, ou a alternar de Wi-Fi para dados móveis).\n\nConfira <a href="%2$s">este artigo do FAQ</a> para mais informações.</string>
|
||||
<string name="unsupported_content_in_country">Este conteúdo não está disponível para o país de conteúdo atualmente selecionado.\n\nAltere a sua seleção de \"Configurações > Conteúdo > País predefinido de conteúdo\".</string>
|
||||
<string name="player_http_403">Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado pela URL de streaming expirado ou IP banido</string>
|
||||
<string name="youtube_player_http_403">Erro HTTP 403 recebido do servidor durante a reprodução, provavelmente causado por um bloqueio de IP ou problemas de desofuscação da URL de streaming</string>
|
||||
<string name="kao_dialog_warning">O Google anunciou que, a partir de 2026/2027, todos os aplicativos em dispositivos Android certificados exigirão que os desenvolvedores forneçam seus dados pessoais de identidade diretamente ao Google. Como os desenvolvedores deste aplicativo não concordam com esse requisito, o aplicativo deixará de funcionar em dispositivos Android certificados após essa data.</string>
|
||||
<string name="kao_dialog_warning">Em agosto de 2025, o Google anunciou que, a partir de setembro de 2026, a instalação de apps exigirá a verificação do programador para todas as apps Android em dispositivos certificados, incluindo aqueles instalados fora da Play Store. Como os programadores do NewPipe não concordam com este requisito, o NewPipe já não funcionará em dispositivos Android certificados após essa data.</string>
|
||||
<string name="kao_dialog_more_info">Detalhes</string>
|
||||
<string name="kao_solution">Solução</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
@@ -633,7 +633,7 @@
|
||||
<string name="feed_load_error">Ошибка загрузки подписки</string>
|
||||
<string name="open_website_license">Открыть веб-сайт</string>
|
||||
<string name="account_terminated">Аккаунт отключён</string>
|
||||
<string name="downloads_storage_use_saf_summary_api_29">Начиная с Android 10 поддерживается только «Storage Access Framework»</string>
|
||||
<string name="downloads_storage_use_saf_summary_api_29">Начиная с Android 10, поддерживается только \"Storage Access Framework\"</string>
|
||||
<string name="downloads_storage_ask_summary_no_saf_notice">Спрашивать, куда сохранять каждую загрузку</string>
|
||||
<string name="no_dir_yet">Папка для загрузки ещё не выбрана, укажите папку для загрузки сейчас</string>
|
||||
<string name="off">Отключить</string>
|
||||
@@ -866,7 +866,7 @@
|
||||
<string name="youtube_player_http_403">Во время воспроизведения получена ошибка HTTP 403 от сервера, вероятно, вызванная блокировкой IP-адреса или проблемами деобфускации URL-адреса потоковой передачи</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s отказался предоставить данные, запросив логин для подтверждения, что запросчик не бот.\n\nВозможно, ваш IP-адрес временно заблокирован %1$s. Вы можете подождать некоторое время или переключиться на другой IP-адрес (например, включив/выключив VPN или переключившись с Wi-Fi на мобильный интернет).</string>
|
||||
<string name="unsupported_content_in_country">Этот контент недоступен для выбранной страны контента.\n\nИзмените свой выбор в разделе «Настройки > Контент > Страна контента по умолчанию».</string>
|
||||
<string name="kao_dialog_warning">Google объявила, что начиная с 2026/2027 года все приложения на сертифицированных устройствах Android будут требовать от разработчиков предоставления своих личных данных для идентификации напрямую Google. Так как разработчики этого приложения не согласны с этим требованием, приложение перестанет работать на сертифицированных устройствах Android после этого времени.</string>
|
||||
<string name="kao_dialog_warning">В августе 2025 года, Google анонсировала, что с сентября 2026 года, установка приложений потребует верификации разработчика для всех Android приложений на сертифицированных устройствах, включая те, которые были установлены не через Play Store. Поскольку разработчики NewPipe не согласны с этим требованием, NewPipe перестанет работать на сертифицированных Android устройствах после этой даты.</string>
|
||||
<string name="kao_dialog_more_info">Подробнее</string>
|
||||
<string name="kao_solution">Решение</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
@@ -860,9 +860,32 @@
|
||||
<string name="player_http_403">Počas prehrávania bola zo servera prijatá chyba HTTP 403, pravdepodobne spôsobená vypršaním platnosti streamingovej adresy URL alebo zákazom IP adresy</string>
|
||||
<string name="player_http_invalid_status">Chyba HTTP %1$s prijatá zo servera počas prehrávania</string>
|
||||
<string name="youtube_player_http_403">Chyba HTTP 403 prijatá zo servera počas prehrávania, pravdepodobne spôsobená zákazom IP adresy alebo problémami s deobfuskáciou streamingovej URL adresy</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s odmietol poskytnúť údaje, žiada o prihlásenie na potvrdenie, že žiadateľ nie je bot.\n\nVaša IP adresa mohla byť dočasne zakázaná %1$s, môžete nejaký čas počkať alebo prejsť na inú IP adresu (napríklad zapnutím/vypnutím VPN alebo prepnutím z WiFi na mobilné dáta).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s odmietol poskytnúť údaje, žiada o prihlásenie na potvrdenie, že žiadateľ nie je bot.\n\nVaša IP adresa mohla byť dočasne zakázaná %1$s, môžete nejaký čas počkať alebo prejsť na inú IP adresu (napríklad zapnutím/vypnutím VPN alebo prepnutím z WiFi na mobilné dáta).\n\nPozrite si <a href="%2$s">túto časť FAQ</a> pre viac informácií.</string>
|
||||
<string name="unsupported_content_in_country">Tento obsah nie je dostupný pre aktuálne zvolenú krajinu obsahu.\n\nZmeňte výber v ponuke \"Nastavenia > Obsah > Predvolená krajina obsahu\".</string>
|
||||
<string name="kao_dialog_warning">Google oznámil, že od roku 2026/2027 budú všetky aplikácie na certifikovaných zariadeniach s Androidom vyžadovať, aby vývojári odovzdali svoje osobné identifikačné údaje priamo Googlu. Keďže vývojári tejto aplikácie s touto požiadavkou nesúhlasia, aplikácia po tomto termíne na certifikovaných zariadeniach s Androidom prestane fungovať.</string>
|
||||
<string name="kao_dialog_warning">V auguste 2025 spoločnosť Google oznámila, že od septembra 2026 bude inštalácia aplikácií vyžadovať overenie vývojára pre všetky aplikácie Android na certifikovaných zariadeniach, vrátane tých, ktoré sú inštalované mimo obchodu Play Store. Keďže vývojári NewPipe s touto požiadavkou nesúhlasia, NewPipe po tomto termíne nebude na certifikovaných zariadeniach Android fungovať.</string>
|
||||
<string name="kao_dialog_more_info">Podrobnosti</string>
|
||||
<string name="kao_solution">Riešenie</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Exportovanie %d odberu…</item>
|
||||
<item quantity="few">Exportovanie %d odberov…</item>
|
||||
<item quantity="many">Exportovanie %d odberov…</item>
|
||||
<item quantity="other">Exportovanie %d odberov…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Načítanie %d odberu…</item>
|
||||
<item quantity="few">Načítanie %d odberov…</item>
|
||||
<item quantity="many">Načítanie %d odberov…</item>
|
||||
<item quantity="other">Načítanie %d odberov…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importovanie %d odberu…</item>
|
||||
<item quantity="few">Importovanie %d odberov…</item>
|
||||
<item quantity="many">Importovanie %d odberov…</item>
|
||||
<item quantity="other">Importovanie %d odberov…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Importovať odbery</string>
|
||||
<string name="export_subscriptions_title">Exportovať odbery</string>
|
||||
<string name="import_subscriptions_summary">Import odberov z predchádzajúceho exportu .json</string>
|
||||
<string name="export_subscriptions_summary">Export vašich odberov do súboru .json</string>
|
||||
<string name="import_from_previous_export">Importovať z predchádzajúceho exportu</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="use_inexact_seek_title">Dhaafinta dagdaga ah</string>
|
||||
<string name="use_inexact_seek_title">Isticmaal Dhaafinta dagdaga ah</string>
|
||||
<string name="popup_remember_size_pos_summary">Xusuusnow meeshii iyo cabirkii udambeeyay ee daaqada</string>
|
||||
<string name="popup_remember_size_pos_title">Xusuusnow fadhiga daaqada</string>
|
||||
<string name="dark_theme_title">Madow</string>
|
||||
<string name="dark_theme_title">Mugdi</string>
|
||||
<string name="theme_title">Nashqada</string>
|
||||
<string name="default_video_format_title">Nooca muuqaalka</string>
|
||||
<string name="default_audio_format_title">Nooca dhagaysiga</string>
|
||||
<string name="default_audio_format_title">Nooca Maqaalka</string>
|
||||
<string name="notification_colorize_summary">Androidka hakuu baddalo midabka ogaysiiska galka waxa daaran asagoo kusalaynaya midabka galka shayga daaran (aalladahoo dhan looma wada heli karo nidaamkan)</string>
|
||||
<string name="notification_colorize_title">Midabbee ogaysiiska</string>
|
||||
<string name="notification_action_buffering">Soo Kicinaya</string>
|
||||
@@ -14,25 +14,25 @@
|
||||
<string name="notification_action_repeat">Ku celi</string>
|
||||
<string name="notification_actions_at_most_three">Ugu badnaan waxad dooran kartaa sadex shay iney ka muuqdaan ogaysiiska yar!</string>
|
||||
<string name="notification_actions_summary">Wax ka baddal hawsha ogaysiiska adigoo dushooda ku dhufanaya. Dooro ilaa sadex kamida si ay uga muuqdaan ogaysiiska yar adigoo saxaya santuuqa dhanka midig kaga yaala</string>
|
||||
<string name="notification_action_4_title">Batoonka hawsha shanaad</string>
|
||||
<string name="notification_action_3_title">Batoonka hawsha afraad</string>
|
||||
<string name="notification_action_2_title">Batoonka hawsha sadexaad</string>
|
||||
<string name="notification_action_1_title">Batoonka hawsha labaad</string>
|
||||
<string name="notification_action_0_title">Batoonka hawsha koowaad</string>
|
||||
<string name="notification_action_4_title">Batoonka shanaad</string>
|
||||
<string name="notification_action_3_title">Batoonka afraad</string>
|
||||
<string name="notification_action_2_title">Batoonka saddexaad</string>
|
||||
<string name="notification_action_1_title">Batoonka labaad</string>
|
||||
<string name="notification_action_0_title">Batoonka koowaad</string>
|
||||
<string name="notification_scale_to_square_image_summary">La ekaysii galka muuqaalka xaga ogaysiisyada ka muuqda cabirka 1:1 ayadoo laga soo baddalayo 16:9</string>
|
||||
<string name="notification_scale_to_square_image_title">Galka la ekaysii cabirka 1:1</string>
|
||||
<string name="show_play_with_kodi_summary">Soo bandhig istikhyaar ah in muuqaalka lagu furo xarunta madadaalada Kodi</string>
|
||||
<string name="show_play_with_kodi_summary">Soo bandhig istikhyaar ah in muuqaalka lagu furo Kodi</string>
|
||||
<string name="show_play_with_kodi_title">Soodhig istikhyaarka \"Ku fur Kodi\"</string>
|
||||
<string name="kore_not_found">Kushub appka maqan ee Kore\?</string>
|
||||
<string name="kore_not_found">Soo deji appka maqan ee Kore?</string>
|
||||
<string name="play_with_kodi_title">Ku fur Kodi</string>
|
||||
<string name="show_higher_resolutions_summary">Aalladaha qaar kaliya ayaa furi kara muuqaalada 2K/4K ga ah</string>
|
||||
<string name="show_higher_resolutions_title">Tus tayooyinka kasii sareeeya</string>
|
||||
<string name="show_higher_resolutions_title">Tus tayooyinka sare</string>
|
||||
<string name="default_popup_resolution_title">Tayada muuqaalka daaqada</string>
|
||||
<string name="default_resolution_title">Tayada muuqaalka</string>
|
||||
<string name="download_path_audio_dialog_title">Dooro khaanada dhagaysiga lasoo dajiyo</string>
|
||||
<string name="download_path_dialog_title">Dooro khaanada muuqaalada lasoo dajiyo</string>
|
||||
<string name="download_path_audio_summary">Dhagaysiyada lasoo dajiyay halkan ayaa lagu kaydiyaa</string>
|
||||
<string name="download_path_summary">Muuqaalada lasoo dajiyo halkan ayaa lagu kaydiyaa</string>
|
||||
<string name="download_path_audio_dialog_title">Dooro Khaanada soo dejinta ee faylasha maqalka ah</string>
|
||||
<string name="download_path_dialog_title">Dooro khaanada Muuqaallada lagu soo dejinayo</string>
|
||||
<string name="download_path_audio_summary">Dhagaysiyada lasoo dajiyay halkan ayaa lagu kaydiyey</string>
|
||||
<string name="download_path_summary">Muuqaalada lasoo dajiyo halkan ayaa lagu kaydiyey</string>
|
||||
<string name="download_path_audio_title">Khaanada dajinta dhagaysiga</string>
|
||||
<string name="download_path_title">Khaanada dajinta muuqaalada</string>
|
||||
<string name="controls_add_to_playlist_title">Ku Dar</string>
|
||||
@@ -41,17 +41,17 @@
|
||||
<string name="tab_choose">Dooro Daaqada</string>
|
||||
<string name="tab_bookmarks">La calaamadsaday</string>
|
||||
<string name="tab_subscriptions">Rukunka</string>
|
||||
<string name="show_info">Faahfaahinta</string>
|
||||
<string name="show_info">Tus Faahfaahinta</string>
|
||||
<string name="subscription_update_failed">Lama cusbooneysiin karo rukunka</string>
|
||||
<string name="subscription_change_failed">Lama baddali karo rukunka</string>
|
||||
<string name="channel_unsubscribed">Kanaalka waad iskajoojisay</string>
|
||||
<string name="unsubscribe">Iskajooji Rukunka</string>
|
||||
<string name="subscribed_button_title">Rukuntay</string>
|
||||
<string name="subscribe_button_title">Rukumo</string>
|
||||
<string name="use_external_audio_player_title">Isticmaal dhagaysi daare dibada ah</string>
|
||||
<string name="use_external_audio_player_title">Isticmaal dhagaysi Daare dibada ah</string>
|
||||
<string name="use_external_video_player_summary">Codka ayuu ka saaraa tayada muuqaalada qaar</string>
|
||||
<string name="use_external_video_player_title">Isticmaal muuqaal daare dibada ah</string>
|
||||
<string name="share_dialog_title">La wadaag</string>
|
||||
<string name="share_dialog_title">Ku La wadaag</string>
|
||||
<string name="search_showing_result_for">Kutusaya natiijooyinka: %s</string>
|
||||
<string name="did_you_mean">Ma waxaad ka waday \"%1$s\"\?</string>
|
||||
<string name="settings">Fadhiga</string>
|
||||
@@ -64,7 +64,7 @@
|
||||
<string name="no_player_found_toast">Wax fura lama helin shaygan. (waxaad Ku shuban kartaa VLC si aad u furto).</string>
|
||||
<string name="no_player_found">Wax fura lama helin shaygan. Ku shubo VLC\?</string>
|
||||
<string name="upload_date_text">Lasoo galiyay: %1$s</string>
|
||||
<string name="main_bg_subtitle">Ku dhufo waynaysada 🔍 si aad wax uraadiso.</string>
|
||||
<string name="main_bg_subtitle">Ku dhufo raadinta si aad wax uraadiso.</string>
|
||||
<string name="overwrite_unrelated_warning">Shay magacan leh ayaa horay ujiray</string>
|
||||
<string name="overwrite">Ku badal</string>
|
||||
<string name="generate_unique_name">Usamee magac gaar ah</string>
|
||||
@@ -262,7 +262,7 @@
|
||||
<string name="error_report_open_github_notice">Fadlan hubi in arin cilladdan ka hadlaya horay loo wariyay. Marka wax horay u jiray la wariyo markale, wakhti ayaad naga qaadaysaa wakhtigaas oo aan cilada ku sixi la hayn.</string>
|
||||
<string name="error_report_open_issue_button_text">Ku wari xaga GitHub-ka</string>
|
||||
<string name="copy_for_github">Koobiyee warka oo diyaarsan</string>
|
||||
<string name="error_report_button_text">Khaladkan email ahaan ku warceli</string>
|
||||
<string name="error_report_button_text">Khaladkan email ahaan uga war bixi</string>
|
||||
<string name="sorry_string">Waan ka xunahay, sidaa inay dhacdo ma ahayn.</string>
|
||||
<string name="permission_display_over_apps">U ogolow appka inuu dul fuulo applicationada kale</string>
|
||||
<string name="restore_defaults_confirmation">Ma rabtaa inaad sidii hore kuceliso\?</string>
|
||||
@@ -400,11 +400,11 @@
|
||||
<string name="show_comments_title">Tus faallooyinka</string>
|
||||
<string name="clear_queue_confirmation_description">Hormada daareha hadda wax shidaya waa la baddali doonaa</string>
|
||||
<string name="clear_queue_confirmation_summary">Kala baddalka daareha waxay badali kartaa hormada sidaas darteed waydii in la xaqiijiyo intaan hormada la tirtirin</string>
|
||||
<string name="clear_queue_confirmation_title">Xaqiijinta tirtirka hormada</string>
|
||||
<string name="clear_queue_confirmation_title">Weydii xaqiijin ka hor intaadan tirtirin saf-ka</string>
|
||||
<string name="seek_duration_title">Wakhtiga horay udhaafinta/dibucelinta</string>
|
||||
<string name="black_theme_title">Mugdi</string>
|
||||
<string name="light_theme_title">Caddaan</string>
|
||||
<string name="play_audio">Dhagaysi</string>
|
||||
<string name="black_theme_title">Madow</string>
|
||||
<string name="light_theme_title">Iftiin</string>
|
||||
<string name="play_audio">Maqal</string>
|
||||
<string name="notification_action_nothing">Waxba</string>
|
||||
<string name="search">Raadi</string>
|
||||
<string name="download">Daji</string>
|
||||
@@ -491,7 +491,7 @@
|
||||
</plurals>
|
||||
<string name="new_seek_duration_toast">Ayadooy ugu wacantahay xayiraad xaga ExoPlayer-ka ah xadka dhaaf-dhaafinta waa %d ilbiriqsi</string>
|
||||
<string name="remove_watched_popup_partially_watched_streams">Haa, sidoo kale ku dar muuqaalada qayb laga daawaday</string>
|
||||
<string name="remove_watched_popup_warning">Muuqaalada la daawaday kahor iyo kadib markii xulka lagu daray waa la saari doonaa. \nMa hubtaa? Arrinkan dib looma soocelin karo!</string>
|
||||
<string name="remove_watched_popup_warning">Muuqaalada la daawaday kahor iyo kadib markii xulka lagu daray waa la saari doonaa. \nMa hubtaa?</string>
|
||||
<string name="remove_watched_popup_title">Saar muuqaalada la daawaday?</string>
|
||||
<string name="remove_watched">Saar kuwa la daawaday</string>
|
||||
<string name="systems_language">Aaladu saytahay</string>
|
||||
@@ -520,7 +520,7 @@
|
||||
<string name="error_postprocessing_failed">Habayntii way guuldareystay</string>
|
||||
<string name="error_http_not_found">Lama helin</string>
|
||||
<string name="error_http_unsupported_range">Martigaliyuhu ma aqbalo dajinta qaybaha badan leh, iskula day @string/msg_threads = 1</string>
|
||||
<string name="error_connect_host">Kuma xidhi karo martigaliyaha</string>
|
||||
<string name="error_connect_host">Kuma xidhmi karo server-ka</string>
|
||||
<string name="error_unknown_host">Lama heli karo martigaliyaha</string>
|
||||
<string name="error_ssl_exception">Lama samayn karo iskuxidh amni ah</string>
|
||||
<string name="error_path_creation">khaanadii la rabay lama samayn karo</string>
|
||||
@@ -630,7 +630,7 @@
|
||||
<string name="remote_search_suggestions">Soojeedinada raadinta banaanka</string>
|
||||
<string name="local_search_suggestions">Soojeedinada raadinta gudaha</string>
|
||||
<string name="progressive_load_interval_title">Cabirka soodaarida udhexeeya</string>
|
||||
<string name="crash_the_player">Jabi Daareha</string>
|
||||
<string name="crash_the_player">Jabi Daaraha</string>
|
||||
<string name="yes">Haa</string>
|
||||
<string name="no">Maya</string>
|
||||
<string name="search_with_service_name">Raadi %1$s</string>
|
||||
|
||||
@@ -845,9 +845,26 @@
|
||||
<string name="player_http_403">Oynatırken sunucudan HTTP 403 hatası alındı, akış URL’si bitmiş ya da IP engellenmiş olabilir</string>
|
||||
<string name="player_http_invalid_status">Oynatırken sunucudan HTTP %1$s hatası alındı</string>
|
||||
<string name="youtube_player_http_403">Oynatırken sunucudan HTTP 403 hatası alındı, IP engeli ya da akış URL’si çözme sorunları olabilir</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s veri sağlamayı geri çevirdi, istekçinin robot olmadığını doğrulaması için oturum açmasını istiyor.\n\n%1$s, IP adresinizi geçici olarak engellemiş olabilir, bir süre bekleyebilir ya da başka IP\'ye geçebilirsiniz (örneğin VPN\'i açıp/kapatarak ya da WiFi\'den mobil veriye geçerek).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s veri sağlamıyor, istekçinin robot olmadığını doğrulaması için oturum açmasını istiyor.\n\n%1$s, IP adresinizi geçici olarak engellemiş olabilir, bir süre bekleyebilir ya da başka IP\'ye geçebilirsiniz (örneğin VPN\'i açıp/kapatarak ya da WiFi\'den mobil veriye geçerek).\n\nDaha çok bilgi için <a href="%2$s">bu SSS girdisine</a> bakın.</string>
|
||||
<string name="unsupported_content_in_country">Bu içerik şu anda seçili içerik ülkesinde kullanılamıyor.\n\nSeçiminizi \"Ayarlar > İçerik > Öntanımlı içerik ülkesi\"nden değiştirin.</string>
|
||||
<string name="kao_dialog_warning">Google, 2026/2027 yılından itibaren sertifikalı Android cihazlardaki tüm uygulamaların, geliştiricilerin kişisel kimlik bilgilerini doğrudan Google’a göndermesini gerektireceğini duyurdu. Bu uygulamanın geliştiricileri bu gerekliliği kabul etmediğinden, uygulama bu tarihten sonra sertifikalı Android cihazlarda çalışmayacaktır.</string>
|
||||
<string name="kao_dialog_more_info">Detaylar</string>
|
||||
<string name="kao_dialog_warning">Google, Eylül 2026\'dan sonra sertifikalı Android aygıtlarda Play Store dışından kurulmuşlarla birlikte tüm uygulamaların, geliştiricilerin kişisel kimlik bilgilerini doğrudan Google’a göndermesini gerektireceğini duyurdu. NewPipe geliştiricileri bu zorunluluğu kabul etmediğinden, NewPipe bu tarihten sonra sertifikalı Android aygıtlarda çalışmayacaktır.</string>
|
||||
<string name="kao_dialog_more_info">Ayrıntılar</string>
|
||||
<string name="kao_solution">Çözüm</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">%d abonelik dışa aktarılıyor…</item>
|
||||
<item quantity="other">%d abonelik dışa aktarılıyor…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">%d abonelik yükleniyor…</item>
|
||||
<item quantity="other">%d abonelik yükleniyor…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">%d abonelik içeri aktarılıyor…</item>
|
||||
<item quantity="other">%d abonelik içeri aktarılıyor…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">Abonelikleri içeri aktar</string>
|
||||
<string name="export_subscriptions_title">Abonelikleri dışarı aktar</string>
|
||||
<string name="import_subscriptions_summary">Abonelikleri önceki dışarı aktarmadaki .json dosyası ile içeri aktar</string>
|
||||
<string name="export_subscriptions_summary">Aboneliklerini bir .json dosyasında dışarı aktar</string>
|
||||
<string name="import_from_previous_export">Önceki dışarı aktarmadan içe aktar</string>
|
||||
</resources>
|
||||
|
||||
@@ -491,7 +491,7 @@
|
||||
<string name="feed_use_dedicated_fetch_method_disable_button">Звичайний режим</string>
|
||||
<string name="feed_use_dedicated_fetch_method_enable_button">Швидкий режим</string>
|
||||
<string name="feed_use_dedicated_fetch_method_summary">Доступно для деяких служб, швидке, але може повертати не весь вміст каналу і часто неповну інформацію (тривалість, тип елемента, статус трансляції)</string>
|
||||
<string name="feed_use_dedicated_fetch_method_title">Оновлення з RSS, коли воно є</string>
|
||||
<string name="feed_use_dedicated_fetch_method_title">Отримувати з виділеної стрічки, коли доступно</string>
|
||||
<string name="feed_update_threshold_option_always_update">Оновлювати постійно</string>
|
||||
<string name="feed_update_threshold_summary">Період актуальності підписок після поновлення — %s</string>
|
||||
<string name="feed_update_threshold_title">Поріг оновлення підписок</string>
|
||||
@@ -510,8 +510,8 @@
|
||||
<string name="feed_oldest_subscription_update">Останнє оновлення: %s</string>
|
||||
<string name="new_seek_duration_toast">Через обмеження ExoPlayer точність перемотування становить %d секунд</string>
|
||||
<string name="remove_watched_popup_partially_watched_streams">Так, а також частково переглянуті відео</string>
|
||||
<string name="remove_watched_popup_warning">Відео, які Ви переглядали до та після додавання в добірку, вилучатимуться. \nВи впевнені? Це незворотна дія!</string>
|
||||
<string name="remove_watched_popup_title">Видалити переглянуті відео?</string>
|
||||
<string name="remove_watched_popup_warning">Потоки, які були переглянуті до та після додавання в добірку, будуть видалені. \nВи впевнені?</string>
|
||||
<string name="remove_watched_popup_title">Видалити переглянуті потоки?</string>
|
||||
<string name="remove_watched">Видалити переглянуті</string>
|
||||
<string name="playlist_no_uploader">Створено автоматично (автора не знайдено)</string>
|
||||
<string name="infinite_videos">∞ вiдео</string>
|
||||
@@ -604,7 +604,7 @@
|
||||
<string name="notification_scale_to_square_image_summary">Обрізати мініатюру відео показувану в сповіщенні з пропорцій 16: 9 до 1:1</string>
|
||||
<string name="disable_media_tunneling_summary">Вимкнення тунелювання медіаданих за наявності чорного екрана або гальмування під час відтворення відео.</string>
|
||||
<string name="disable_media_tunneling_title">Вимкнути тунелювання медіа</string>
|
||||
<string name="downloads_storage_use_saf_summary_api_29">«Фреймворк доступу до сховища» (SAF) підтримується лише починаючи з Android 10</string>
|
||||
<string name="downloads_storage_use_saf_summary_api_29">Починаючи з Android 10, підтримується тільки \"Storage Access Framework\"</string>
|
||||
<string name="downloads_storage_ask_summary_no_saf_notice">Вас питатиме, куди зберігати кожне завантаження</string>
|
||||
<string name="no_dir_yet">Не вказано теки завантаження, оберіть типову теку завантаження зараз</string>
|
||||
<string name="open_website_license">Відкрити вебсайт</string>
|
||||
@@ -866,4 +866,7 @@
|
||||
<string name="youtube_player_http_403">Під час відтворення від сервера отримано помилку HTTP 403, ймовірно, через заборону IP-адреси або проблеми з деобфускацією URL-адреси потокової передачі</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s відмовився надати дані, запитуючи логін для підтвердження того, що запитувач не є ботом.\n\nВаша IP-адреса могла бути тимчасово заблокована %1$s. Ви можете почекати деякий час або перейти на іншу IP-адресу (наприклад, увімкнувши/вимкнувши VPN або переключившись з Wi-Fi на мобільні дані).</string>
|
||||
<string name="unsupported_content_in_country">Цей контент недоступний для вибраної країни контенту.\n\nЗмініть свій вибір у розділі \"Налаштування > Контент > Країна контенту за замовчуванням\".</string>
|
||||
<string name="kao_dialog_warning">У серпні 2025 року, Google анонсувала, що з вересня 2026 року, для встановлення застосунків буде потрібна верифікація розробника для всіх Android застосунків на сертифікованих пристроях, включаючи ті, що були встановлені не через Play Store. Оскільки розробники NewPipe не згодні з цією вимогою, NewPipe перестане працювати на сертифікованих Android пристроях після цієї дати.</string>
|
||||
<string name="kao_dialog_more_info">Детальніше</string>
|
||||
<string name="kao_solution">Вирішення</string>
|
||||
</resources>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<string name="general_error">Lỗi</string>
|
||||
<string name="network_error">Lỗi kết nối mạng</string>
|
||||
<string name="could_not_load_thumbnails">Không thể tải tất cả hình thu nhỏ</string>
|
||||
<string name="parsing_error">Không thể phân tích cú pháp trang web vì trang này đã ngừng hoạt động vào 21/07/2025.</string>
|
||||
<string name="parsing_error">Không thể phân tích cú pháp web.</string>
|
||||
<string name="content_not_available">Nội dung không khả dụng</string>
|
||||
<string name="could_not_setup_download_menu">Không thể thiết lập menu tải về</string>
|
||||
<string name="app_ui_crash">Ứng dụng/Giao diện người dùng bị lỗi</string>
|
||||
@@ -821,8 +821,8 @@
|
||||
<string name="trending_movies">Phim và chương trình đang thịnh hành</string>
|
||||
<string name="trending_music">Âm nhạc đang thịnh hành</string>
|
||||
<string name="player_http_403">Đã xảy ra lỗi HTTP 403 trong khi phát, có thể do URL phát sóng đã hết hạn hoặc bị ban IP</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s đã từ chối cung cấp dữ liệu, cần phải đăng nhập để xác nhận yêu cầu viên ko phải là bot.\n\nIP này có vẻ đã bị ban tạm thời bởi %1$s, bạn có thể đợi một lúc hoặc chuyển sang IP khác (ví dụ như việc tắt / bật lại VPN, hoặc là chuyển mạng từ WIFI sang 4G/5G).</string>
|
||||
<string name="unsupported_content_in_country">Nội dung này không được hỗ trợ tại quốc gia mà bạn chọn.\n\nHãy đổi quốc gia trong phần \"Cài đặt > Nội dung > Nội dung quốc gia mặc định\".</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s đã từ chối cung cấp dữ liệu, cần phải đăng nhập để xác nhận requester của NewPipe ko phải là bot.\n\nIP này có vẻ đã bị ban tạm thời bởi %1$s, bạn có thể đợi một lúc hoặc chuyển sang IP khác (ví dụ như việc tắt / bật lại VPN, hoặc là chuyển mạng từ WIFI sang 4G/5G).\n\nXem qua <a href="%2$s">phần FAQ này</a> đẻ biết thêm chi tiết</string>
|
||||
<string name="unsupported_content_in_country">Nội dung này không được hỗ trợ tại quốc gia mà bạn chọn.\n\nHãy đổi quốc gia trong phần \"Cài đặt > Nội dung > Quốc gia nội dung mặc định\".</string>
|
||||
<string name="permission_display_over_apps_message">Để sử dụng tính năng phát video nổi, hãy chọn %1$s trong Cài đặt Android và bật tính năng %2$s.</string>
|
||||
<string name="youtube_player_http_403">Đã xảy ra lỗi HTTP 403 trong khi phát, có thể IP này đã bị ban hoặc vấn đề phát URL deobfuscation</string>
|
||||
<string name="permission_display_over_apps_permission_name">\"Cho phép hiển thị trên ứng dụng khác\"</string>
|
||||
@@ -831,4 +831,7 @@
|
||||
<string name="account_terminated_service_provides_reason">Tài khoản bị vô hiệu hóa. \n\n%1$s cung cấp lý do này: %2$s</string>
|
||||
<string name="entry_deleted">Entry đã xóa</string>
|
||||
<string name="player_http_invalid_status">Đã xảy ra lỗi HTTP %1$s trong khi phát</string>
|
||||
<string name="kao_dialog_warning">Từ tháng 8 năm 2025, Google đã thông báo rằng kể từ tháng 9 năm 2026, việc cài app sẽ yêu cầu các nhà phát triển phải xác minh trên những thiết bị đã chứng nhận, kể cả đối với các ứng dụng ngoài Play Store. Vì các nhà phát triển của NewPipe không đồng ý với điều kiện này, nên có lẽ NewPipe sẽ không còn hoạt động trên các máy Android được chứng nhận sau thời điểm ấy.</string>
|
||||
<string name="kao_dialog_more_info">Chi tiết</string>
|
||||
<string name="kao_solution">Giải pháp</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="open_in_browser">im brüscher öffn</string>
|
||||
<string name="yes">passd scho</string>
|
||||
<string name="ok">passd scho</string>
|
||||
<string name="cancel">stoarnieren</string>
|
||||
<string name="install">iser</string>
|
||||
<string name="no">net</string>
|
||||
<string name="share">tealn</string>
|
||||
</resources>
|
||||
@@ -831,6 +831,23 @@
|
||||
<string name="player_http_403">播放时从服务器收到 HTTP 403 错误,可能因串流 URL 过期或 IP 封锁导致</string>
|
||||
<string name="player_http_invalid_status">播放时从服务器收到 HTTP %1$s 错误</string>
|
||||
<string name="youtube_player_http_403">播放时从服务器收到 HTTP 403 错误,可能因 IP 封锁或串流 URL 解密问题导致</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s 拒绝提供数据, 要求登录确认请求方不是机器人。\n\n你的 IP 可能已经暂时被 %1$s 封禁,你可以等待一段时间或切换到不同 IP (比如开/关 VPN, 或者从 WiFi 连接切换到移动数据)。</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s 拒绝提供数据, 要求登录确认请求方不是机器人。\n\n你的 IP 可能已经暂时被 %1$s 封禁,你可以等待一段时间或切换到不同 IP (比如开/关 VPN, 或者从 WiFi 连接切换到移动数据)。\n\n请见 <a href="%2$s">此 FAQ条目</a> 获取更多信息。</string>
|
||||
<string name="unsupported_content_in_country">此内容对当前选中的内容地区不可用。\n\n要更改选择,请前往 “设置 > 内容 > 默认内容地区”。</string>
|
||||
<string name="kao_dialog_warning">2025 年 8 月,Google 宣布自 2026 年 9 月起,在已认证设备上安装所有安卓应用都需要开发者验证身份,包括在 Play 商店之外安装的应用。由于 NewPipe 开发者反对此要求,NewPipe 在此时间点后不会再在已认证设备上工作。</string>
|
||||
<string name="kao_dialog_more_info">详情</string>
|
||||
<string name="kao_solution">解决方案</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="other">正在导出 %d 个订阅…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="other">正在加载 %d 个订阅…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="other">正在导入 %d 个订阅…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">导入订阅</string>
|
||||
<string name="export_subscriptions_title">导出订阅</string>
|
||||
<string name="import_subscriptions_summary">从之前的 .json 导出文件导入订阅</string>
|
||||
<string name="export_subscriptions_summary">导出订阅到 .json 文件</string>
|
||||
<string name="import_from_previous_export">从之前的导出文件导入</string>
|
||||
</resources>
|
||||
|
||||
@@ -343,7 +343,7 @@
|
||||
<string name="generate_unique_name">生成獨特的名稱</string>
|
||||
<string name="overwrite">覆寫</string>
|
||||
<string name="overwrite_finished_warning">有已下載的同名檔案</string>
|
||||
<string name="download_already_running">已有進行中的下載與此同名</string>
|
||||
<string name="download_already_running">已有正在進行的下載與此同名</string>
|
||||
<string name="show_error">顯示錯誤</string>
|
||||
<string name="error_file_creation">無法建立檔案</string>
|
||||
<string name="error_path_creation">無法建立目的地資料夾</string>
|
||||
@@ -377,7 +377,7 @@
|
||||
<string name="missing_file">檔案已被移動或刪除</string>
|
||||
<string name="overwrite_unrelated_warning">同名的檔案已存在</string>
|
||||
<string name="overwrite_failed">無法覆寫檔案</string>
|
||||
<string name="download_already_pending">已有擱置中的下載與此同名</string>
|
||||
<string name="download_already_pending">已有正在擱置的下載與此同名</string>
|
||||
<string name="error_postprocessing_stopped">NewPipe 在處理檔案時被關閉</string>
|
||||
<string name="error_insufficient_storage_left">裝置上沒有剩餘的空間</string>
|
||||
<string name="error_progress_lost">進度遺失,因為檔案已被刪除</string>
|
||||
@@ -811,6 +811,23 @@
|
||||
<string name="player_http_403">播放時收到來自伺服器的 HTTP 錯誤 403,可能因串流網址過期或 IP 封鎖所致</string>
|
||||
<string name="player_http_invalid_status">播放時收到來自伺服器的 HTTP 錯誤 %1$s</string>
|
||||
<string name="youtube_player_http_403">播放時收到來自伺服器的 HTTP 錯誤 403,可能因 IP 封鎖或串流網址去混淆化問題所致</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s 拒絕提供資料,要求登入以確認請求者並非機器人。\n\n您的 IP 位址可能已被 %1$s 暫時封鎖,您可稍候片刻或切換至其他 IP 位址(例如開啟/關閉 VPN,或從 Wi-Fi 切換至行動數據)。</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s 拒絕提供資料,要求登入以確認請求者並非機器人。\n\n您的 IP 位址可能已被 %1$s 暫時封鎖,您可稍候片刻或切換至其他 IP 位址(例如開啟/關閉 VPN,或從 Wi-Fi 切換至行動數據)。\n\n更多資訊請參見<a href="%2$s">此 FAQ 條目</a>。</string>
|
||||
<string name="unsupported_content_in_country">此內容目前無法於您所選的國家/地區提供。\n\n請至「設定」→「內容」→「預設內容國家」變更您的選擇。</string>
|
||||
<string name="kao_dialog_warning">2025年8月,Google 宣佈自2026年9月起,所有經認證裝置上的 Android 應用程式(包含不是透過 Play 商店安裝的應用程式)皆須通過開發者驗證方可安裝。由於 NewPipe 開發團隊不接受此項要求,該應用程式屆時將無法在經認證的 Android 裝置上運作。</string>
|
||||
<string name="kao_dialog_more_info">詳細資訊</string>
|
||||
<string name="kao_solution">解決方案</string>
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="other">正在匯出 %d 個訂閱…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="other">正在載入 %d 個訂閱…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="other">正在匯入 %d 個訂閱…</item>
|
||||
</plurals>
|
||||
<string name="import_subscriptions_title">匯入訂閱</string>
|
||||
<string name="export_subscriptions_title">匯出訂閱</string>
|
||||
<string name="export_subscriptions_summary">匯出您的訂閱至 .json 檔案</string>
|
||||
<string name="import_subscriptions_summary">從先前匯出的 .json 匯入訂閱</string>
|
||||
<string name="import_from_previous_export">從先前的匯出檔案匯入</string>
|
||||
</resources>
|
||||
|
||||
@@ -413,6 +413,8 @@
|
||||
<string name="import_export_data_path">import_export_data_path</string>
|
||||
<string name="import_data">import_data</string>
|
||||
<string name="export_data">export_data</string>
|
||||
<string name="import_subscriptions_key">import_subscriptions_key</string>
|
||||
<string name="export_subscriptions_key">export_subscriptions_key</string>
|
||||
|
||||
<string name="clear_cookie_key">clear_cookie</string>
|
||||
|
||||
@@ -1213,7 +1215,6 @@
|
||||
<item>fi</item>
|
||||
<item>fil</item>
|
||||
<item>fr</item>
|
||||
<item>frc</item>
|
||||
<item>gl</item>
|
||||
<item>gu</item>
|
||||
<item>he</item>
|
||||
@@ -1314,7 +1315,6 @@
|
||||
<item>Suomen kieli</item>
|
||||
<item>Wikang Filipino</item>
|
||||
<item>Français</item>
|
||||
<item>Français (Louisiana)</item>
|
||||
<item>Galego</item>
|
||||
<item>ગુજરાતી</item>
|
||||
<item>עברית</item>
|
||||
|
||||
@@ -501,6 +501,18 @@
|
||||
<string name="show_error_snackbar">Show an error snackbar</string>
|
||||
<string name="create_error_notification">Create an error notification</string>
|
||||
<!-- Subscriptions import/export -->
|
||||
<plurals name="export_subscriptions">
|
||||
<item quantity="one">Exporting %d subscription…</item>
|
||||
<item quantity="other">Exporting %d subscriptions…</item>
|
||||
</plurals>
|
||||
<plurals name="load_subscriptions">
|
||||
<item quantity="one">Loading %d subscription…</item>
|
||||
<item quantity="other">Loading %d subscriptions…</item>
|
||||
</plurals>
|
||||
<plurals name="import_subscriptions">
|
||||
<item quantity="one">Importing %d subscription…</item>
|
||||
<item quantity="other">Importing %d subscriptions…</item>
|
||||
</plurals>
|
||||
<string name="import_title">Import</string>
|
||||
<string name="import_from">Import from</string>
|
||||
<string name="export_to">Export to</string>
|
||||
@@ -508,6 +520,11 @@
|
||||
<string name="export_ongoing">Exporting…</string>
|
||||
<string name="import_file_title">Import file</string>
|
||||
<string name="previous_export">Previous export</string>
|
||||
<string name="import_subscriptions_title">Import subscriptions"</string>
|
||||
<string name="export_subscriptions_title">Export subscriptions</string>
|
||||
<string name="import_subscriptions_summary">Import subscriptions from a previous .json export"</string>
|
||||
<string name="export_subscriptions_summary">Export your subscriptions to a .json file</string>
|
||||
<string name="import_from_previous_export">Import from previous export</string>
|
||||
<string name="subscriptions_import_unsuccessful">Could not import subscriptions</string>
|
||||
<string name="subscriptions_export_unsuccessful">Could not export subscriptions</string>
|
||||
<string name="import_youtube_instructions">Import YouTube subscriptions from Google takeout:
|
||||
@@ -878,7 +895,7 @@
|
||||
<string name="player_http_403">HTTP error 403 received from server while playing, likely caused by streaming URL expiration or an IP ban</string>
|
||||
<string name="player_http_invalid_status">HTTP error %1$s received from server while playing</string>
|
||||
<string name="youtube_player_http_403">HTTP error 403 received from server while playing, likely caused by an IP ban or streaming URL deobfuscation issues</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s refused to provide data, asking for a login to confirm the requester is not a bot.\n\nYour IP might have been temporarily banned by %1$s, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data).</string>
|
||||
<string name="sign_in_confirm_not_bot_error">%1$s refused to provide data, asking for a login to confirm the requester is not a bot.\n\nYour IP might have been temporarily banned by %1$s, you can wait some time or switch to a different IP (for example by turning on/off a VPN, or by switching from WiFi to mobile data).\n\nPlease see <a href="%2$s">this FAQ entry</a> for more information.</string>
|
||||
<string name="unsupported_content_in_country">This content is not available for the currently selected content country.\n\nChange your selection from \"Settings > Content > Default content country\".</string>
|
||||
<string name="kao_dialog_warning">In August 2025, Google announced that as of September 2026, installing apps will require developer verification for all Android apps on certified devices, including those installed outside of the Play Store. Since the developers of NewPipe do not agree to this requirement, NewPipe will no longer work on certified Android devices after that time.</string>
|
||||
<string name="kao_dialog_more_info">Details</string>
|
||||
|
||||
@@ -22,4 +22,18 @@
|
||||
android:summary="@string/reset_settings_summary"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/export_subscriptions_key"
|
||||
android:title="@string/export_subscriptions_title"
|
||||
android:summary="@string/export_subscriptions_summary"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/import_subscriptions_key"
|
||||
android:title="@string/import_subscriptions_title"
|
||||
android:summary="@string/import_subscriptions_summary"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceScreen>
|
||||
@@ -5,11 +5,11 @@ import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
||||
import org.schabi.newpipe.extractor.subscription.SubscriptionItem;
|
||||
import org.schabi.newpipe.local.subscription.workers.ImportExportJsonHelper;
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionItem;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -23,26 +23,22 @@ public class ImportExportJsonHelperTest {
|
||||
final String emptySource =
|
||||
"{\"app_version\":\"0.11.6\",\"app_version_int\": 47,\"subscriptions\":[]}";
|
||||
|
||||
final List<SubscriptionItem> items = ImportExportJsonHelper.readFrom(
|
||||
new ByteArrayInputStream(emptySource.getBytes(StandardCharsets.UTF_8)), null);
|
||||
final var items = ImportExportJsonHelper.readFrom(
|
||||
new ByteArrayInputStream(emptySource.getBytes(StandardCharsets.UTF_8)));
|
||||
assertTrue(items.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidSource() {
|
||||
final List<String> invalidList = Arrays.asList(
|
||||
"{}",
|
||||
"",
|
||||
null,
|
||||
"gibberish");
|
||||
final var invalidList = Arrays.asList("{}", "", null, "gibberish");
|
||||
|
||||
for (final String invalidContent : invalidList) {
|
||||
try {
|
||||
if (invalidContent != null) {
|
||||
final byte[] bytes = invalidContent.getBytes(StandardCharsets.UTF_8);
|
||||
ImportExportJsonHelper.readFrom((new ByteArrayInputStream(bytes)), null);
|
||||
ImportExportJsonHelper.readFrom(new ByteArrayInputStream(bytes));
|
||||
} else {
|
||||
ImportExportJsonHelper.readFrom(null, null);
|
||||
ImportExportJsonHelper.readFrom(null);
|
||||
}
|
||||
|
||||
fail("didn't throw exception");
|
||||
@@ -58,38 +54,24 @@ public class ImportExportJsonHelperTest {
|
||||
@Test
|
||||
public void ultimateTest() throws Exception {
|
||||
// Read from file
|
||||
final List<SubscriptionItem> itemsFromFile = readFromFile();
|
||||
final var itemsFromFile = readFromFile();
|
||||
|
||||
// Test writing to an output
|
||||
final String jsonOut = testWriteTo(itemsFromFile);
|
||||
|
||||
// Read again
|
||||
final List<SubscriptionItem> itemsSecondRead = readFromWriteTo(jsonOut);
|
||||
final var itemsSecondRead = readFromWriteTo(jsonOut);
|
||||
|
||||
// Check if both lists have the exact same items
|
||||
if (itemsFromFile.size() != itemsSecondRead.size()) {
|
||||
if (!itemsFromFile.equals(itemsSecondRead)) {
|
||||
fail("The list of items were different from each other");
|
||||
}
|
||||
|
||||
for (int i = 0; i < itemsFromFile.size(); i++) {
|
||||
final SubscriptionItem item1 = itemsFromFile.get(i);
|
||||
final SubscriptionItem item2 = itemsSecondRead.get(i);
|
||||
|
||||
final boolean equals = item1.getServiceId() == item2.getServiceId()
|
||||
&& item1.getUrl().equals(item2.getUrl())
|
||||
&& item1.getName().equals(item2.getName());
|
||||
|
||||
if (!equals) {
|
||||
fail("The list of items were different from each other");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<SubscriptionItem> readFromFile() throws Exception {
|
||||
final InputStream inputStream = getClass().getClassLoader().getResourceAsStream(
|
||||
"import_export_test.json");
|
||||
final List<SubscriptionItem> itemsFromFile = ImportExportJsonHelper.readFrom(
|
||||
inputStream, null);
|
||||
final var inputStream = getClass().getClassLoader()
|
||||
.getResourceAsStream("import_export_test.json");
|
||||
final var itemsFromFile = ImportExportJsonHelper.readFrom(inputStream);
|
||||
|
||||
if (itemsFromFile.isEmpty()) {
|
||||
fail("ImportExportJsonHelper.readFrom(input) returned a null or empty list");
|
||||
@@ -98,10 +80,10 @@ public class ImportExportJsonHelperTest {
|
||||
return itemsFromFile;
|
||||
}
|
||||
|
||||
private String testWriteTo(final List<SubscriptionItem> itemsFromFile) throws Exception {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ImportExportJsonHelper.writeTo(itemsFromFile, out, null);
|
||||
final String jsonOut = out.toString("UTF-8");
|
||||
private String testWriteTo(final List<SubscriptionItem> itemsFromFile) {
|
||||
final var out = new ByteArrayOutputStream();
|
||||
ImportExportJsonHelper.writeTo(itemsFromFile, out);
|
||||
final String jsonOut = out.toString(StandardCharsets.UTF_8);
|
||||
|
||||
if (jsonOut.isEmpty()) {
|
||||
fail("JSON returned by writeTo was empty");
|
||||
@@ -111,10 +93,8 @@ public class ImportExportJsonHelperTest {
|
||||
}
|
||||
|
||||
private List<SubscriptionItem> readFromWriteTo(final String jsonOut) throws Exception {
|
||||
final ByteArrayInputStream inputStream = new ByteArrayInputStream(
|
||||
jsonOut.getBytes(StandardCharsets.UTF_8));
|
||||
final List<SubscriptionItem> secondReadItems = ImportExportJsonHelper.readFrom(
|
||||
inputStream, null);
|
||||
final var inputStream = new ByteArrayInputStream(jsonOut.getBytes(StandardCharsets.UTF_8));
|
||||
final var secondReadItems = ImportExportJsonHelper.readFrom(inputStream);
|
||||
|
||||
if (secondReadItems.isEmpty()) {
|
||||
fail("second call to readFrom returned an empty list");
|
||||
|
||||
@@ -3,7 +3,9 @@ package org.schabi.newpipe.settings
|
||||
import android.content.SharedPreferences
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import kotlin.io.path.createTempFile
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.fileSize
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito
|
||||
@@ -47,10 +49,10 @@ class ImportAllCombinationsTest {
|
||||
BackupFileLocator::class.java,
|
||||
Mockito.withSettings().stubOnly()
|
||||
)
|
||||
val db = File.createTempFile("newpipe_", "")
|
||||
val dbJournal = File.createTempFile("newpipe_", "")
|
||||
val dbWal = File.createTempFile("newpipe_", "")
|
||||
val dbShm = File.createTempFile("newpipe_", "")
|
||||
val db = createTempFile("newpipe_", "")
|
||||
val dbJournal = createTempFile("newpipe_", "")
|
||||
val dbWal = createTempFile("newpipe_", "")
|
||||
val dbShm = createTempFile("newpipe_", "")
|
||||
Mockito.`when`(fileLocator.db).thenReturn(db)
|
||||
Mockito.`when`(fileLocator.dbJournal).thenReturn(dbJournal)
|
||||
Mockito.`when`(fileLocator.dbShm).thenReturn(dbShm)
|
||||
@@ -62,7 +64,7 @@ class ImportAllCombinationsTest {
|
||||
Assert.assertFalse(dbJournal.exists())
|
||||
Assert.assertFalse(dbWal.exists())
|
||||
Assert.assertFalse(dbShm.exists())
|
||||
Assert.assertTrue("database file size is zero", Files.size(db.toPath()) > 0)
|
||||
Assert.assertTrue("database file size is zero", db.fileSize() > 0)
|
||||
}
|
||||
} else {
|
||||
runTest {
|
||||
@@ -70,7 +72,7 @@ class ImportAllCombinationsTest {
|
||||
Assert.assertTrue(dbJournal.exists())
|
||||
Assert.assertTrue(dbWal.exists())
|
||||
Assert.assertTrue(dbShm.exists())
|
||||
Assert.assertEquals(0, Files.size(db.toPath()))
|
||||
Assert.assertEquals(0, db.fileSize())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,15 @@ import android.content.SharedPreferences
|
||||
import com.grack.nanojson.JsonParser
|
||||
import java.io.File
|
||||
import java.io.ObjectInputStream
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.zip.ZipFile
|
||||
import kotlin.io.path.createTempDirectory
|
||||
import kotlin.io.path.createTempFile
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import kotlin.io.path.div
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.fileSize
|
||||
import kotlin.io.path.inputStream
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertThrows
|
||||
@@ -46,7 +53,7 @@ class ImportExportManagerTest {
|
||||
|
||||
@Test
|
||||
fun `The settings must be exported successfully in the correct format`() {
|
||||
val db = File(classloader.getResource("settings/newpipe.db")!!.file)
|
||||
val db = Paths.get(classloader.getResource("settings/newpipe.db")!!.toURI())
|
||||
`when`(fileLocator.db).thenReturn(db)
|
||||
|
||||
val expectedPreferences = mapOf("such pref" to "much wow")
|
||||
@@ -81,29 +88,29 @@ class ImportExportManagerTest {
|
||||
|
||||
@Test
|
||||
fun `Ensuring db directory existence must work`() {
|
||||
val dir = Files.createTempDirectory("newpipe_").toFile()
|
||||
Assume.assumeTrue(dir.delete())
|
||||
`when`(fileLocator.dbDir).thenReturn(dir)
|
||||
val path = createTempDirectory("newpipe_") / BackupFileLocator.FILE_NAME_DB
|
||||
Assume.assumeTrue(path.parent.deleteIfExists())
|
||||
`when`(fileLocator.db).thenReturn(path)
|
||||
|
||||
ImportExportManager(fileLocator).ensureDbDirectoryExists()
|
||||
assertTrue(dir.exists())
|
||||
assertTrue(path.parent.exists())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Ensuring db directory existence must work when the directory already exists`() {
|
||||
val dir = Files.createTempDirectory("newpipe_").toFile()
|
||||
`when`(fileLocator.dbDir).thenReturn(dir)
|
||||
val path = createTempDirectory("newpipe_") / BackupFileLocator.FILE_NAME_DB
|
||||
`when`(fileLocator.db).thenReturn(path)
|
||||
|
||||
ImportExportManager(fileLocator).ensureDbDirectoryExists()
|
||||
assertTrue(dir.exists())
|
||||
assertTrue(path.parent.exists())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `The database must be extracted from the zip file`() {
|
||||
val db = File.createTempFile("newpipe_", "")
|
||||
val dbJournal = File.createTempFile("newpipe_", "")
|
||||
val dbWal = File.createTempFile("newpipe_", "")
|
||||
val dbShm = File.createTempFile("newpipe_", "")
|
||||
val db = createTempFile("newpipe_", "")
|
||||
val dbJournal = createTempFile("newpipe_", "")
|
||||
val dbWal = createTempFile("newpipe_", "")
|
||||
val dbShm = createTempFile("newpipe_", "")
|
||||
`when`(fileLocator.db).thenReturn(db)
|
||||
`when`(fileLocator.dbJournal).thenReturn(dbJournal)
|
||||
`when`(fileLocator.dbShm).thenReturn(dbShm)
|
||||
@@ -117,15 +124,15 @@ class ImportExportManagerTest {
|
||||
assertFalse(dbJournal.exists())
|
||||
assertFalse(dbWal.exists())
|
||||
assertFalse(dbShm.exists())
|
||||
assertTrue("database file size is zero", Files.size(db.toPath()) > 0)
|
||||
assertTrue("database file size is zero", db.fileSize() > 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Extracting the database from an empty zip must not work`() {
|
||||
val db = File.createTempFile("newpipe_", "")
|
||||
val dbJournal = File.createTempFile("newpipe_", "")
|
||||
val dbWal = File.createTempFile("newpipe_", "")
|
||||
val dbShm = File.createTempFile("newpipe_", "")
|
||||
val db = createTempFile("newpipe_", "")
|
||||
val dbJournal = createTempFile("newpipe_", "")
|
||||
val dbWal = createTempFile("newpipe_", "")
|
||||
val dbShm = createTempFile("newpipe_", "")
|
||||
`when`(fileLocator.db).thenReturn(db)
|
||||
|
||||
val emptyZip = File(classloader.getResource("settings/nodb_noser_nojson.zip")?.file!!)
|
||||
@@ -136,7 +143,7 @@ class ImportExportManagerTest {
|
||||
assertTrue(dbJournal.exists())
|
||||
assertTrue(dbWal.exists())
|
||||
assertTrue(dbShm.exists())
|
||||
assertEquals(0, Files.size(db.toPath()))
|
||||
assertEquals(0, db.fileSize())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -9,5 +9,6 @@ plugins {
|
||||
alias(libs.plugins.jetbrains.kotlin.kapt) apply false
|
||||
alias(libs.plugins.google.ksp) apply false
|
||||
alias(libs.plugins.jetbrains.kotlin.parcelize) apply false
|
||||
alias(libs.plugins.jetbrains.kotlinx.serialization) apply false
|
||||
alias(libs.plugins.sonarqube) apply false
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
اندرویددا یوتیوب اوچون بیر اؤزگور و یونگول قاپاخ.
|
||||
@@ -1 +1,11 @@
|
||||
Opraveno nepřehrávání jakéhokoli streamu ve službě YouTube
|
||||
Oprava chyby „Obsah není k dispozici“: videa z YouTube lze nyní opět přehrávat!
|
||||
|
||||
Další opravy chyb z verze 0.28.1:
|
||||
• Přetahování položek playlistu pouze na sousední pozice
|
||||
• Blikání názvu/komentářů mezi aktuálním a předchozím videem
|
||||
• Nefunkční možnost „Spustit hlavní přehrávač na celou obrazovku“
|
||||
|
||||
Další vylepšení:
|
||||
• [YouTube] Opětovné povolení přetáčení živých přenosů až o 4 hodiny zpět
|
||||
• Nepřetáčení živého videa při přehrávání na pozadí
|
||||
• Nové uživatelské rozhraní pro „Odebrat zhlédnuté“
|
||||
|
||||
14
fastlane/metadata/android/cs/changelogs/1009.txt
Normal file
14
fastlane/metadata/android/cs/changelogs/1009.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Důležité
|
||||
Přidány informace a výzva k akci v rámci kampaně Keep Android Open: https://www.keepandroidopen.org/
|
||||
|
||||
Vylepšeno
|
||||
[Feed] Změna pořadí aktualizace starších odběrů
|
||||
Zrušeno kupení stránek s komentáři
|
||||
Nepředávání události kliknutí podkladovým zobrazením při kliknutí na stránku s podrobnostmi o videu
|
||||
|
||||
Opraveno
|
||||
Rozložení záhlaví odpovědí na komentáře bez avataru
|
||||
Několik oprav rozhraní souvisejících s přehrávačem
|
||||
[SoundCloud] Oprava streamů s dlouhými ID
|
||||
|
||||
a další opravy a vylepšení!
|
||||
14
fastlane/metadata/android/de/changelogs/1009.txt
Normal file
14
fastlane/metadata/android/de/changelogs/1009.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Wichtig
|
||||
Informationen zur Kampagne „Keep Android Open“: https://keepandroidopen.org/de/
|
||||
|
||||
Verbessert
|
||||
[Feed] Die Reihenfolge, in der veraltete Abos aktualisiert werden
|
||||
Kommentarseiten nicht stapeln
|
||||
Beim Klicken auf die Videodetailseite keine Klickereignisse an darunterliegende Ansichten weiterleiten
|
||||
|
||||
Behoben
|
||||
Layout der Kommentarantworten ohne Profilbild
|
||||
Mehrere Player-bezogene Korrekturen der Bedienoberfläche
|
||||
[SoundCloud] Streams mit langen IDs
|
||||
|
||||
und weitere Korrekturen und Verbesserungen!
|
||||
@@ -7,6 +7,6 @@ Verbessert
|
||||
• [Bandcamp] Anzeige zusätzlicher Informationen im Radio-Kiosk
|
||||
|
||||
Behoben
|
||||
• [YouTube] Behebung gelegentlicher HTTP-403-Fehler am Anfang oder in der Mitte von Videos
|
||||
• [YouTube] Extrahieren von Avataren und Banner aus mehr Kanal-Header-Typen
|
||||
• [Bandcamp] Verschiedene Fehler behoben und HTTPS wird stets verwendet
|
||||
• [YouTube] Gelegentliche HTTP-403-Fehler am Anfang oder in der Mitte von Videos
|
||||
• [YouTube] Extrahieren von Profilbildern und Banner aus mehr Kanal-Header-Typen
|
||||
• [Bandcamp] Verschiedene Fehler behoben und HTTPS wird immer verwendet
|
||||
|
||||
14
fastlane/metadata/android/en-US/changelogs/1009.txt
Normal file
14
fastlane/metadata/android/en-US/changelogs/1009.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Important
|
||||
Information on and call for action for the Keep Android Open campaign added: https://www.keepandroidopen.org/
|
||||
|
||||
Improved
|
||||
[Feed] Shuffle the order outdated subscriptions are updated in
|
||||
Do not stack comment pages
|
||||
Do not pass click events to underlying views when clicking on video detail page
|
||||
|
||||
Fixed
|
||||
Comment replies header layout without avatar image
|
||||
Multiple player-related UI fixes
|
||||
[SoundCloud] Fix streams with long IDs
|
||||
|
||||
and more fixes and improvements!
|
||||
15
fastlane/metadata/android/fr/changelogs/1009.txt
Normal file
15
fastlane/metadata/android/fr/changelogs/1009.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
Important
|
||||
Informations et appel à l'action pour la campagne Keep Android Open ajoutés : https://www.keepandroidopen.org/
|
||||
|
||||
Améliorations
|
||||
[Flux] Ordre de mise à jour des abonnements obsolètes aléatoire
|
||||
Pages de commentaires non empilées
|
||||
Événements de clic désactivés sur la page de détails d'une vidéo
|
||||
|
||||
|
||||
Corrections
|
||||
Affichage de l'en-tête des réponses aux commentaires sans image d'avatar
|
||||
Corrections d'interface utilisateur pour plusieurs lecteurs
|
||||
[SoundCloud] Correction des flux avec des identifiants longs
|
||||
|
||||
Et bien d'autres corrections et améliorations !
|
||||
@@ -1 +1,10 @@
|
||||
फिक्स्ड YouTube कोई स्ट्रीम नहीं चला रहा है
|
||||
इस हॉटफ़िक्स रिलीज़ से "Content not available" एरर ठीक हो गया है: अब YouTube वीडियो फिर से चलाए जा सकते हैं!
|
||||
|
||||
इससे 0.28.1 में आई कुछ और गड़बड़ियाँ भी ठीक हो गई हैं:
|
||||
• प्लेलिस्ट आइटम को खींचकर सिर्फ़ आस-पास की जगहों पर ही ले जा पाना
|
||||
• मौजूदा और पिछले वीडियो के बीच टाइटल/कमेंट्स का बार-बार बदलना
|
||||
• "Start main player in fullscreen" ऑप्शन का काम न करना
|
||||
|
||||
दूसरे सुधार:
|
||||
• [YouTube] लाइवस्ट्रीम को 4 घंटे तक पीछे ले जाने की सुविधा फिर से चालू
|
||||
• बैकग्राउंड में चलते समय लाइवस्ट्रीम वीडियो लोड न करना
|
||||
|
||||
4
fastlane/metadata/android/hi/changelogs/1008.txt
Normal file
4
fastlane/metadata/android/hi/changelogs/1008.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
∙ स्ट्रीम को पिछली प्लेबैक स्थिति से फिर से शुरू करने की समस्या ठीक की गई
|
||||
∙ [YouTube] ज़्यादा चैनल URL फ़ॉर्मैट के लिए सपोर्ट जोड़ा गया
|
||||
∙ [YouTube] ज़्यादा वीडियो मेटा-इन्फ़ो फ़ॉर्मैट के लिए सपोर्ट जोड़ा गया
|
||||
∙ अनुवाद अपडेट किए गए
|
||||
14
fastlane/metadata/android/hi/changelogs/1009.txt
Normal file
14
fastlane/metadata/android/hi/changelogs/1009.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
ज़रूरी
|
||||
'Keep Android Open' कैंपेन के बारे में जानकारी और कार्रवाई के लिए अपील जोड़ी गई: https://www.keepandroidopen.org/
|
||||
|
||||
बेहतर
|
||||
[फ़ीड] पुरानी सब्सक्रिप्शन के अपडेट होने का क्रम बदला गया
|
||||
कमेंट पेज एक के ऊपर एक न दिखें
|
||||
वीडियो डिटेल पेज पर क्लिक करने पर, क्लिक इवेंट नीचे के व्यूज़ तक न पहुँचें
|
||||
|
||||
ठीक किया गया
|
||||
कमेंट रिप्लाई हेडर लेआउट में अवतार इमेज न दिखना
|
||||
प्लेयर से जुड़े कई UI सुधार
|
||||
[SoundCloud] लंबी ID वाले स्ट्रीम को ठीक किया गया
|
||||
|
||||
और भी कई सुधार और बेहतर बदलाव!
|
||||
16
fastlane/metadata/android/id/changelogs/1006.txt
Normal file
16
fastlane/metadata/android/id/changelogs/1006.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
# Peningkatan
|
||||
Pertahankan pemutar saat ini ketika mengklik stempel waktu
|
||||
Cobalah untuk memulihkan misi pengunduhan yang tertunda jika memungkinkan
|
||||
Tambahkan opsi untuk menghapus unduhan tanpa ikut menghapus berkas
|
||||
Izin Overlay: menampilkan dialog penjelasan untuk Android > R
|
||||
Mendukung tautan on.soundcloud saat membuka
|
||||
Banyak perbaikan dan optimasi kecil.
|
||||
|
||||
# Telah diperbaiki
|
||||
Memperbaiki format penghitungan pendek untuk versi Android di bawah 7
|
||||
Memperbaiki notifikasi berhantu
|
||||
Memperbaiki berkas SRT
|
||||
Memperbaiki banyak sekali kerusakan
|
||||
|
||||
# Pengembangan
|
||||
Modernisasi kode internal
|
||||
4
fastlane/metadata/android/id/changelogs/1008.txt
Normal file
4
fastlane/metadata/android/id/changelogs/1008.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
∙ Memperbaiki masalah melanjutkan pemutaran pengaliran dari posisi pemutaran terakhir
|
||||
∙ [YouTube] Menambahkan dukungan untuk lebih banyak format Tautan saluran
|
||||
∙ [YouTube] Menambahkan dukungan untuk lebih banyak format metainfo video
|
||||
∙ Pembaruan terjemahan
|
||||
14
fastlane/metadata/android/id/changelogs/1009.txt
Normal file
14
fastlane/metadata/android/id/changelogs/1009.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Penting
|
||||
Informasi dan ajakan untuk bertindak terkait kampanye Keep Android Open telah ditambahkan: https://www.keepandroidopen.org/
|
||||
|
||||
Improved
|
||||
[Feed] Acak urutan pembaruan langganan yang sudah kedaluwarsa di
|
||||
Jangan menumpuk halaman komentar
|
||||
Jangan meneruskan peristiwa klik ke tampilan yang mendasarinya saat mengklik halaman detail video.
|
||||
|
||||
Telah Diperbaiki
|
||||
Tata letak header balasan komentar tanpa gambar avatar
|
||||
Perbaikan antarmuka pengguna terkait pemain ganda
|
||||
[SoundCloud] Perbaiki aliran data dengan ID yang panjang
|
||||
|
||||
dan masih banyak perbaikan dan peningkatan lainnya!
|
||||
4
fastlane/metadata/android/it/changelogs/1008.txt
Normal file
4
fastlane/metadata/android/it/changelogs/1008.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
∙ Corretto il problema di ripresa degli streaming dall'ultima posizione di riproduzione
|
||||
∙ [YouTube] Aggiunto il supporto per più formati di URL dei canali
|
||||
∙ [YouTube] Aggiunto il supporto per più formati di metainformazioni video
|
||||
∙ Traduzioni aggiornate
|
||||
14
fastlane/metadata/android/it/changelogs/1009.txt
Normal file
14
fastlane/metadata/android/it/changelogs/1009.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Importante
|
||||
Informazioni e invito all'azione per la campagna Keep Android Open aggiunte: https://www.keepandroidopen.org/
|
||||
|
||||
Migliorato
|
||||
[Feed] Riordina l'ordine in cui vengono aggiornati gli abbonamenti obsoleti
|
||||
Non sovrapporre le pagine dei commenti
|
||||
Non passare gli eventi clic alle viste sottostanti quando si fa clic sulla pagina dei dettagli del video
|
||||
|
||||
Corretto
|
||||
Layout dell'intestazione delle risposte ai commenti senza immagine avatar
|
||||
Correzioni multiple all'interfaccia utente relative al player
|
||||
[SoundCloud] Correzione degli stream con ID lunghi
|
||||
|
||||
e altre correzioni e miglioramenti!
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user