Merge branch 'dev' into dev
This commit is contained in:
commit
69bf1c5d81
42 changed files with 428 additions and 590 deletions
|
@ -13,7 +13,7 @@
|
|||
</p>
|
||||
<hr>
|
||||
<p align="center"><a href="#screenshots">Screenshots</a> • <a href="#description">Description</a> • <a href="#features">Features</a> • <a href="#updates">Updates</a> • <a href="#contribution">Contribution</a> • <a href="#donate">Donate</a> • <a href="#license">License</a></p>
|
||||
<p align="center"><a href="https://newpipe.schabi.org">Website</a> • <a href="https://newpipe.schabi.org/blog/">Blog</a> • <a href="https://newpipe.schabi.org/press/">Press</a></p>
|
||||
<p align="center"><a href="https://newpipe.schabi.org">Website</a> • <a href="https://newpipe.schabi.org/blog/">Blog</a> • <a href="https://newpipe.schabi.org/FAQ/">FAQ</a> • <a href="https://newpipe.schabi.org/press/">Press</a></p>
|
||||
<hr>
|
||||
|
||||
<b>WARNING: THIS IS A BETA VERSION, THEREFORE YOU MAY ENCOUNTER BUGS. IF YOU DO, OPEN AN ISSUE VIA OUR GITHUB REPOSITORY.</b>
|
||||
|
|
|
@ -11,8 +11,8 @@ android {
|
|||
applicationId "org.schabi.newpipe"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 800
|
||||
versionName "0.18.0"
|
||||
versionCode 820
|
||||
versionName "0.18.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
@ -62,7 +62,7 @@ dependencies {
|
|||
exclude module: 'support-annotations'
|
||||
})
|
||||
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:bdbfa26'
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:ff61e284'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'org.mockito:mockito-core:2.23.0'
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
<!-- channel prefix -->
|
||||
<data android:pathPrefix="/channel/"/>
|
||||
<data android:pathPrefix="/user/"/>
|
||||
<data android:pathPrefix="/c/"/>
|
||||
<!-- playlist prefix -->
|
||||
<data android:pathPrefix="/playlist"/>
|
||||
</intent-filter>
|
||||
|
|
|
@ -449,6 +449,16 @@ public class MainActivity extends AppCompatActivity {
|
|||
sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply();
|
||||
NavigationHelper.openMainActivity(this);
|
||||
}
|
||||
|
||||
if (sharedPreferences.getBoolean(Constants.KEY_ENABLE_WATCH_HISTORY, true)) {
|
||||
if (DEBUG) Log.d(TAG, "do not show History-menu as its disabled in settings");
|
||||
drawerItems.getMenu().findItem(ITEM_ID_HISTORY).setVisible(true);
|
||||
}
|
||||
|
||||
if (!sharedPreferences.getBoolean(Constants.KEY_ENABLE_WATCH_HISTORY, true)) {
|
||||
if (DEBUG) Log.d(TAG, "show History-menu as its enabled in settings");
|
||||
drawerItems.getMenu().findItem(ITEM_ID_HISTORY).setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -551,8 +561,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
if (!(fragment instanceof SearchFragment)) {
|
||||
findViewById(R.id.toolbar).findViewById(R.id.toolbar_search_container).setVisibility(View.GONE);
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.main_menu, menu);
|
||||
}
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
|
@ -574,14 +582,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
case android.R.id.home:
|
||||
onHomeButtonPressed();
|
||||
return true;
|
||||
case R.id.action_show_downloads:
|
||||
return NavigationHelper.openDownloads(this);
|
||||
case R.id.action_history:
|
||||
NavigationHelper.openStatisticFragment(getSupportFragmentManager());
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
NavigationHelper.openSettings(this);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
|
|
@ -99,11 +99,6 @@ public class AboutActivity extends AppCompatActivity {
|
|||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
NavigationHelper.openSettings(this);
|
||||
return true;
|
||||
case R.id.action_show_downloads:
|
||||
return NavigationHelper.openDownloads(this);
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
|
|
|
@ -78,11 +78,7 @@ public class DownloadActivity extends AppCompatActivity {
|
|||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
case R.id.action_settings: {
|
||||
Intent intent = new Intent(this, SettingsActivity.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
|
|
@ -832,7 +832,6 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
|
|||
psArgs = new String[]{
|
||||
selectedStream.getFormat().getSuffix(),
|
||||
"false",// ignore empty frames
|
||||
"false",// detect youtube duplicate lines
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -79,6 +79,7 @@ import org.schabi.newpipe.util.Constants;
|
|||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.InfoCache;
|
||||
import org.schabi.newpipe.util.KoreUtil;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
|
@ -624,7 +625,7 @@ public class VideoDetailFragment
|
|||
url.replace("https", "http")));
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) Log.i(TAG, "Failed to start kore", e);
|
||||
showInstallKoreDialog(activity);
|
||||
KoreUtil.showInstallKoreDialog(activity);
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
|
@ -632,16 +633,6 @@ public class VideoDetailFragment
|
|||
}
|
||||
}
|
||||
|
||||
private static void showInstallKoreDialog(final Context context) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage(R.string.kore_not_found)
|
||||
.setPositiveButton(R.string.install, (DialogInterface dialog, int which) ->
|
||||
NavigationHelper.installKore(context))
|
||||
.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
private void setupActionBarOnError(final String url) {
|
||||
if (DEBUG) Log.d(TAG, "setupActionBarHandlerOnError() called with: url = [" + url + "]");
|
||||
Log.e("-----", "missing code");
|
||||
|
|
|
@ -55,10 +55,7 @@ public final class BackgroundPlayerActivity extends ServicePlayerActivity {
|
|||
return true;
|
||||
}
|
||||
|
||||
this.player.setRecovery();
|
||||
getApplicationContext().sendBroadcast(getPlayerShutdownIntent());
|
||||
getApplicationContext().startService(getSwitchIntent(PopupVideoPlayer.class));
|
||||
return true;
|
||||
return switchTo(PopupVideoPlayer.class);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -150,6 +150,8 @@ public abstract class BasePlayer implements
|
|||
@NonNull
|
||||
public static final String RESUME_PLAYBACK = "resume_playback";
|
||||
@NonNull
|
||||
public static final String START_PAUSED = "start_paused";
|
||||
@NonNull
|
||||
public static final String SELECT_ON_APPEND = "select_on_append";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -304,7 +306,7 @@ public abstract class BasePlayer implements
|
|||
}
|
||||
// Good to go...
|
||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence,
|
||||
/*playOnInit=*/true);
|
||||
/*playOnInit=*/!intent.getBooleanExtra(START_PAUSED, false));
|
||||
}
|
||||
|
||||
protected void initPlayback(@NonNull final PlayQueue queue,
|
||||
|
@ -944,10 +946,10 @@ public abstract class BasePlayer implements
|
|||
public void onPlayPause() {
|
||||
if (DEBUG) Log.d(TAG, "onPlayPause() called");
|
||||
|
||||
if (!isPlaying()) {
|
||||
onPlay();
|
||||
} else {
|
||||
if (isPlaying()) {
|
||||
onPause();
|
||||
} else {
|
||||
onPlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.database.ContentObserver;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
@ -75,6 +76,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
|
|||
import org.schabi.newpipe.player.resolver.MediaSourceTag;
|
||||
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
|
||||
import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.KoreUtil;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
@ -435,6 +437,7 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
private boolean queueVisible;
|
||||
|
||||
private ImageButton moreOptionsButton;
|
||||
private ImageButton kodiButton;
|
||||
private ImageButton shareButton;
|
||||
private ImageButton toggleOrientationButton;
|
||||
private ImageButton switchPopupButton;
|
||||
|
@ -471,6 +474,7 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
|
||||
this.moreOptionsButton = rootView.findViewById(R.id.moreOptionsButton);
|
||||
this.secondaryControls = rootView.findViewById(R.id.secondaryControls);
|
||||
this.kodiButton = rootView.findViewById(R.id.kodi);
|
||||
this.shareButton = rootView.findViewById(R.id.share);
|
||||
this.toggleOrientationButton = rootView.findViewById(R.id.toggleOrientation);
|
||||
this.switchBackgroundButton = rootView.findViewById(R.id.switchBackground);
|
||||
|
@ -482,6 +486,9 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
|
||||
titleTextView.setSelected(true);
|
||||
channelTextView.setSelected(true);
|
||||
boolean showKodiButton = PreferenceManager.getDefaultSharedPreferences(this.context).getBoolean(
|
||||
this.context.getString(R.string.show_play_with_kodi_key), false);
|
||||
kodiButton.setVisibility(showKodiButton ? View.VISIBLE : View.GONE);
|
||||
|
||||
getRootView().setKeepScreenOn(true);
|
||||
}
|
||||
|
@ -518,6 +525,7 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
closeButton.setOnClickListener(this);
|
||||
|
||||
moreOptionsButton.setOnClickListener(this);
|
||||
kodiButton.setOnClickListener(this);
|
||||
shareButton.setOnClickListener(this);
|
||||
toggleOrientationButton.setOnClickListener(this);
|
||||
switchBackgroundButton.setOnClickListener(this);
|
||||
|
@ -588,6 +596,17 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
finish();
|
||||
}
|
||||
|
||||
public void onKodiShare() {
|
||||
onPause();
|
||||
try {
|
||||
NavigationHelper.playWithKore(this.context, Uri.parse(
|
||||
playerImpl.getVideoUrl().replace("https", "http")));
|
||||
} catch (Exception e) {
|
||||
if (DEBUG) Log.i(TAG, "Failed to start kore", e);
|
||||
KoreUtil.showInstallKoreDialog(this.context);
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Player Overrides
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -614,7 +633,8 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
this.getPlaybackPitch(),
|
||||
this.getPlaybackSkipSilence(),
|
||||
this.getPlaybackQuality(),
|
||||
false
|
||||
false,
|
||||
!isPlaying()
|
||||
);
|
||||
context.startService(intent);
|
||||
|
||||
|
@ -637,7 +657,8 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
this.getPlaybackPitch(),
|
||||
this.getPlaybackSkipSilence(),
|
||||
this.getPlaybackQuality(),
|
||||
false
|
||||
false,
|
||||
!isPlaying()
|
||||
);
|
||||
context.startService(intent);
|
||||
|
||||
|
@ -686,6 +707,8 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
} else if (v.getId() == closeButton.getId()) {
|
||||
onPlaybackShutdown();
|
||||
return;
|
||||
} else if (v.getId() == kodiButton.getId()) {
|
||||
onKodiShare();
|
||||
}
|
||||
|
||||
if (getCurrentState() != STATE_COMPLETED) {
|
||||
|
|
|
@ -567,7 +567,8 @@ public final class PopupVideoPlayer extends Service {
|
|||
this.getPlaybackPitch(),
|
||||
this.getPlaybackSkipSilence(),
|
||||
this.getPlaybackQuality(),
|
||||
false
|
||||
false,
|
||||
!isPlaying()
|
||||
);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
|
@ -1123,4 +1124,4 @@ public final class PopupVideoPlayer extends Service {
|
|||
return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,10 +48,7 @@ public final class PopupVideoPlayerActivity extends ServicePlayerActivity {
|
|||
@Override
|
||||
public boolean onPlayerOptionSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_switch_background) {
|
||||
this.player.setRecovery();
|
||||
getApplicationContext().sendBroadcast(getPlayerShutdownIntent());
|
||||
getApplicationContext().startService(getSwitchIntent(BackgroundPlayer.class));
|
||||
return true;
|
||||
return switchTo(BackgroundPlayer.class);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -157,18 +157,11 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
case R.id.action_append_playlist:
|
||||
appendAllToPlaylist();
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
NavigationHelper.openSettings(this);
|
||||
redraw = true;
|
||||
return true;
|
||||
case R.id.action_system_audio:
|
||||
startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
|
||||
return true;
|
||||
case R.id.action_switch_main:
|
||||
this.player.setRecovery();
|
||||
getApplicationContext().sendBroadcast(getPlayerShutdownIntent());
|
||||
getApplicationContext().startActivity(getSwitchIntent(MainVideoPlayer.class));
|
||||
return true;
|
||||
return switchTo(MainVideoPlayer.class);
|
||||
}
|
||||
return onPlayerOptionSelected(item) || super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
@ -189,8 +182,17 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
this.player.getPlaybackPitch(),
|
||||
this.player.getPlaybackSkipSilence(),
|
||||
null,
|
||||
false,
|
||||
false
|
||||
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(BasePlayer.START_PAUSED, !this.player.isPlaying());
|
||||
}
|
||||
|
||||
protected boolean switchTo(final Class clazz) {
|
||||
this.player.setRecovery();
|
||||
getApplicationContext().sendBroadcast(getPlayerShutdownIntent());
|
||||
getApplicationContext().startActivity(getSwitchIntent(clazz));
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package org.schabi.newpipe.streams;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.Node;
|
||||
import org.jsoup.nodes.TextNode;
|
||||
import org.jsoup.parser.Parser;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.schabi.newpipe.streams.io.SharpStream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author kapodamy
|
||||
*/
|
||||
public class SrtFromTtmlWriter {
|
||||
private static final String NEW_LINE = "\r\n";
|
||||
|
||||
private SharpStream out;
|
||||
private boolean ignoreEmptyFrames;
|
||||
private final Charset charset = StandardCharsets.UTF_8;
|
||||
|
||||
private int frameIndex = 0;
|
||||
|
||||
public SrtFromTtmlWriter(SharpStream out, boolean ignoreEmptyFrames) {
|
||||
this.out = out;
|
||||
this.ignoreEmptyFrames = ignoreEmptyFrames;
|
||||
}
|
||||
|
||||
private static String getTimestamp(Element frame, String attr) {
|
||||
return frame
|
||||
.attr(attr)
|
||||
.replace('.', ',');// SRT subtitles uses comma as decimal separator
|
||||
}
|
||||
|
||||
private void writeFrame(String begin, String end, StringBuilder text) throws IOException {
|
||||
writeString(String.valueOf(frameIndex++));
|
||||
writeString(NEW_LINE);
|
||||
writeString(begin);
|
||||
writeString(" --> ");
|
||||
writeString(end);
|
||||
writeString(NEW_LINE);
|
||||
writeString(text.toString());
|
||||
writeString(NEW_LINE);
|
||||
writeString(NEW_LINE);
|
||||
}
|
||||
|
||||
private void writeString(String text) throws IOException {
|
||||
out.write(text.getBytes(charset));
|
||||
}
|
||||
|
||||
public void build(SharpStream ttml) throws IOException {
|
||||
/*
|
||||
* TTML parser with BASIC support
|
||||
* multiple CUE is not supported
|
||||
* styling is not supported
|
||||
* tag timestamps (in auto-generated subtitles) are not supported, maybe in the future
|
||||
* also TimestampTagOption enum is not applicable
|
||||
* Language parsing is not supported
|
||||
*/
|
||||
|
||||
// parse XML
|
||||
byte[] buffer = new byte[(int) ttml.available()];
|
||||
ttml.read(buffer);
|
||||
Document doc = Jsoup.parse(new ByteArrayInputStream(buffer), "UTF-8", "", Parser.xmlParser());
|
||||
|
||||
StringBuilder text = new StringBuilder(128);
|
||||
Elements paragraph_list = doc.select("body > div > p");
|
||||
|
||||
// check if has frames
|
||||
if (paragraph_list.size() < 1) return;
|
||||
|
||||
for (Element paragraph : paragraph_list) {
|
||||
text.setLength(0);
|
||||
|
||||
for (Node children : paragraph.childNodes()) {
|
||||
if (children instanceof TextNode)
|
||||
text.append(((TextNode) children).text());
|
||||
else if (children instanceof Element && ((Element) children).tagName().equalsIgnoreCase("br"))
|
||||
text.append(NEW_LINE);
|
||||
}
|
||||
|
||||
if (ignoreEmptyFrames && text.length() < 1) continue;
|
||||
|
||||
String begin = getTimestamp(paragraph, "begin");
|
||||
String end = getTimestamp(paragraph, "end");
|
||||
|
||||
writeFrame(begin, end, text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,369 +0,0 @@
|
|||
package org.schabi.newpipe.streams;
|
||||
|
||||
import org.schabi.newpipe.streams.io.SharpStream;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.ParseException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
/**
|
||||
* @author kapodamy
|
||||
*/
|
||||
public class SubtitleConverter {
|
||||
private static final String NEW_LINE = "\r\n";
|
||||
|
||||
public void dumpTTML(SharpStream in, final SharpStream out, final boolean ignoreEmptyFrames, final boolean detectYoutubeDuplicateLines
|
||||
) throws IOException, ParseException, SAXException, ParserConfigurationException, XPathExpressionException {
|
||||
|
||||
final FrameWriter callback = new FrameWriter() {
|
||||
int frameIndex = 0;
|
||||
final Charset charset = Charset.forName("utf-8");
|
||||
|
||||
@Override
|
||||
public void yield(SubtitleFrame frame) throws IOException {
|
||||
if (ignoreEmptyFrames && frame.isEmptyText()) {
|
||||
return;
|
||||
}
|
||||
out.write(String.valueOf(frameIndex++).getBytes(charset));
|
||||
out.write(NEW_LINE.getBytes(charset));
|
||||
out.write(getTime(frame.start, true).getBytes(charset));
|
||||
out.write(" --> ".getBytes(charset));
|
||||
out.write(getTime(frame.end, true).getBytes(charset));
|
||||
out.write(NEW_LINE.getBytes(charset));
|
||||
out.write(frame.text.getBytes(charset));
|
||||
out.write(NEW_LINE.getBytes(charset));
|
||||
out.write(NEW_LINE.getBytes(charset));
|
||||
}
|
||||
};
|
||||
|
||||
read_xml_based(in, callback, detectYoutubeDuplicateLines,
|
||||
"tt", "xmlns", "http://www.w3.org/ns/ttml",
|
||||
new String[]{"timedtext", "head", "wp"},
|
||||
new String[]{"body", "div", "p"},
|
||||
"begin", "end", true
|
||||
);
|
||||
}
|
||||
|
||||
private void read_xml_based(SharpStream source, FrameWriter callback, boolean detectYoutubeDuplicateLines,
|
||||
String root, String formatAttr, String formatVersion, String[] cuePath, String[] framePath,
|
||||
String timeAttr, String durationAttr, boolean hasTimestamp
|
||||
) throws IOException, ParseException, SAXException, ParserConfigurationException, XPathExpressionException {
|
||||
/*
|
||||
* XML based subtitles parser with BASIC support
|
||||
* multiple CUE is not supported
|
||||
* styling is not supported
|
||||
* tag timestamps (in auto-generated subtitles) are not supported, maybe in the future
|
||||
* also TimestampTagOption enum is not applicable
|
||||
* Language parsing is not supported
|
||||
*/
|
||||
|
||||
byte[] buffer = new byte[(int) source.available()];
|
||||
source.read(buffer);
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document xml = builder.parse(new ByteArrayInputStream(buffer));
|
||||
|
||||
String attr;
|
||||
|
||||
// get the format version or namespace
|
||||
Element node = xml.getDocumentElement();
|
||||
|
||||
if (node == null) {
|
||||
throw new ParseException("Can't get the format version. ¿wrong namespace?", -1);
|
||||
} else if (!node.getNodeName().equals(root)) {
|
||||
throw new ParseException("Invalid root", -1);
|
||||
}
|
||||
|
||||
if (formatAttr.equals("xmlns")) {
|
||||
if (!node.getNamespaceURI().equals(formatVersion)) {
|
||||
throw new UnsupportedOperationException("Expected xml namespace: " + formatVersion);
|
||||
}
|
||||
} else {
|
||||
attr = node.getAttributeNS(formatVersion, formatAttr);
|
||||
if (attr == null) {
|
||||
throw new ParseException("Can't get the format attribute", -1);
|
||||
}
|
||||
if (!attr.equals(formatVersion)) {
|
||||
throw new ParseException("Invalid format version : " + attr, -1);
|
||||
}
|
||||
}
|
||||
|
||||
NodeList node_list;
|
||||
|
||||
int line_break = 0;// Maximum characters per line if present (valid for TranScript v3)
|
||||
|
||||
if (!hasTimestamp) {
|
||||
node_list = selectNodes(xml, cuePath, formatVersion);
|
||||
|
||||
if (node_list != null) {
|
||||
// if the subtitle has multiple CUEs, use the highest value
|
||||
for (int i = 0; i < node_list.getLength(); i++) {
|
||||
try {
|
||||
int tmp = Integer.parseInt(((Element) node_list.item(i)).getAttributeNS(formatVersion, "ah"));
|
||||
if (tmp > line_break) {
|
||||
line_break = tmp;
|
||||
}
|
||||
} catch (Exception err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse every frame
|
||||
node_list = selectNodes(xml, framePath, formatVersion);
|
||||
|
||||
if (node_list == null) {
|
||||
return;// no frames detected
|
||||
}
|
||||
|
||||
int fs_ff = -1;// first timestamp of first frame
|
||||
boolean limit_lines = false;
|
||||
|
||||
for (int i = 0; i < node_list.getLength(); i++) {
|
||||
Element elem = (Element) node_list.item(i);
|
||||
SubtitleFrame obj = new SubtitleFrame();
|
||||
obj.text = elem.getTextContent();
|
||||
|
||||
attr = elem.getAttribute(timeAttr);// ¡this cant be null!
|
||||
obj.start = hasTimestamp ? parseTimestamp(attr) : Integer.parseInt(attr);
|
||||
|
||||
attr = elem.getAttribute(durationAttr);
|
||||
if (obj.text == null || attr == null) {
|
||||
continue;// normally is a blank line (on auto-generated subtitles) ignore
|
||||
}
|
||||
|
||||
if (hasTimestamp) {
|
||||
obj.end = parseTimestamp(attr);
|
||||
|
||||
if (detectYoutubeDuplicateLines) {
|
||||
if (limit_lines) {
|
||||
int swap = obj.end;
|
||||
obj.end = fs_ff;
|
||||
fs_ff = swap;
|
||||
} else {
|
||||
if (fs_ff < 0) {
|
||||
fs_ff = obj.end;
|
||||
} else {
|
||||
if (fs_ff < obj.start) {
|
||||
limit_lines = true;// the subtitles has duplicated lines
|
||||
} else {
|
||||
detectYoutubeDuplicateLines = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obj.end = obj.start + Integer.parseInt(attr);
|
||||
}
|
||||
|
||||
if (/*node.getAttribute("w").equals("1") &&*/line_break > 1 && obj.text.length() > line_break) {
|
||||
|
||||
// implement auto line breaking (once)
|
||||
StringBuilder text = new StringBuilder(obj.text);
|
||||
obj.text = null;
|
||||
|
||||
switch (text.charAt(line_break)) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
putBreakAt(line_break, text);
|
||||
break;
|
||||
default:// find the word start position
|
||||
for (int j = line_break - 1; j > 0; j--) {
|
||||
switch (text.charAt(j)) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
putBreakAt(j, text);
|
||||
j = -1;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
j = -1;// long word, just ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
obj.text = text.toString();// set the processed text
|
||||
}
|
||||
|
||||
callback.yield(obj);
|
||||
}
|
||||
}
|
||||
|
||||
private static NodeList selectNodes(Document xml, String[] path, String namespaceUri) {
|
||||
Element ref = xml.getDocumentElement();
|
||||
|
||||
for (int i = 0; i < path.length - 1; i++) {
|
||||
NodeList nodes = ref.getChildNodes();
|
||||
if (nodes.getLength() < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Element elem;
|
||||
for (int j = 0; j < nodes.getLength(); j++) {
|
||||
if (nodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
|
||||
elem = (Element) nodes.item(j);
|
||||
if (elem.getNodeName().equals(path[i]) && elem.getNamespaceURI().equals(namespaceUri)) {
|
||||
ref = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ref.getElementsByTagNameNS(namespaceUri, path[path.length - 1]);
|
||||
}
|
||||
|
||||
private static int parseTimestamp(String multiImpl) throws NumberFormatException, ParseException {
|
||||
if (multiImpl.length() < 1) {
|
||||
return 0;
|
||||
} else if (multiImpl.length() == 1) {
|
||||
return Integer.parseInt(multiImpl) * 1000;// ¡this must be a number in seconds!
|
||||
}
|
||||
|
||||
// detect wallclock-time
|
||||
if (multiImpl.startsWith("wallclock(")) {
|
||||
throw new UnsupportedOperationException("Parsing wallclock timestamp is not implemented");
|
||||
}
|
||||
|
||||
// detect offset-time
|
||||
if (multiImpl.indexOf(':') < 0) {
|
||||
int multiplier = 1000;
|
||||
char metric = multiImpl.charAt(multiImpl.length() - 1);
|
||||
switch (metric) {
|
||||
case 'h':
|
||||
multiplier *= 3600000;
|
||||
break;
|
||||
case 'm':
|
||||
multiplier *= 60000;
|
||||
break;
|
||||
case 's':
|
||||
if (multiImpl.charAt(multiImpl.length() - 2) == 'm') {
|
||||
multiplier = 1;// ms
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!Character.isDigit(metric)) {
|
||||
throw new NumberFormatException("Invalid metric suffix found on : " + multiImpl);
|
||||
}
|
||||
metric = '\0';
|
||||
break;
|
||||
}
|
||||
try {
|
||||
String offset_time = multiImpl;
|
||||
|
||||
if (multiplier == 1) {
|
||||
offset_time = offset_time.substring(0, offset_time.length() - 2);
|
||||
} else if (metric != '\0') {
|
||||
offset_time = offset_time.substring(0, offset_time.length() - 1);
|
||||
}
|
||||
|
||||
double time_metric_based = Double.parseDouble(offset_time);
|
||||
if (Math.abs(time_metric_based) <= Double.MAX_VALUE) {
|
||||
return (int) (time_metric_based * multiplier);
|
||||
}
|
||||
} catch (Exception err) {
|
||||
throw new UnsupportedOperationException("Invalid or not implemented timestamp on: " + multiImpl);
|
||||
}
|
||||
}
|
||||
|
||||
// detect clock-time
|
||||
int time = 0;
|
||||
String[] units = multiImpl.split(":");
|
||||
|
||||
if (units.length < 3) {
|
||||
throw new ParseException("Invalid clock-time timestamp", -1);
|
||||
}
|
||||
|
||||
time += Integer.parseInt(units[0]) * 3600000;// hours
|
||||
time += Integer.parseInt(units[1]) * 60000;//minutes
|
||||
time += Float.parseFloat(units[2]) * 1000f;// seconds and milliseconds (if present)
|
||||
|
||||
// frames and sub-frames are ignored (not implemented)
|
||||
// time += units[3] * fps;
|
||||
return time;
|
||||
}
|
||||
|
||||
private static void putBreakAt(int idx, StringBuilder str) {
|
||||
// this should be optimized at compile time
|
||||
|
||||
if (NEW_LINE.length() > 1) {
|
||||
str.delete(idx, idx + 1);// remove after replace
|
||||
str.insert(idx, NEW_LINE);
|
||||
} else {
|
||||
str.setCharAt(idx, NEW_LINE.charAt(0));
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTime(int time, boolean comma) {
|
||||
// cast every value to integer to avoid auto-round in ToString("00").
|
||||
StringBuilder str = new StringBuilder(12);
|
||||
str.append(numberToString(time / 1000 / 3600, 2));// hours
|
||||
str.append(':');
|
||||
str.append(numberToString(time / 1000 / 60 % 60, 2));// minutes
|
||||
str.append(':');
|
||||
str.append(numberToString(time / 1000 % 60, 2));// seconds
|
||||
str.append(comma ? ',' : '.');
|
||||
str.append(numberToString(time % 1000, 3));// miliseconds
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
private static String numberToString(int nro, int pad) {
|
||||
return String.format(Locale.ENGLISH, "%0".concat(String.valueOf(pad)).concat("d"), nro);
|
||||
}
|
||||
|
||||
|
||||
/******************
|
||||
* helper classes *
|
||||
******************/
|
||||
|
||||
private interface FrameWriter {
|
||||
|
||||
void yield(SubtitleFrame frame) throws IOException;
|
||||
}
|
||||
|
||||
private static class SubtitleFrame {
|
||||
//Java no support unsigned int
|
||||
|
||||
public int end;
|
||||
public int start;
|
||||
public String text = "";
|
||||
|
||||
private boolean isEmptyText() {
|
||||
if (text == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
switch (text.charAt(i)) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,5 +11,7 @@ public class Constants {
|
|||
public static final String KEY_THEME_CHANGE = "key_theme_change";
|
||||
public static final String KEY_MAIN_PAGE_CHANGE = "key_main_page_change";
|
||||
|
||||
public static final String KEY_ENABLE_WATCH_HISTORY = "enable_watch_history";
|
||||
|
||||
public static final int NO_SERVICE_ID = -1;
|
||||
}
|
||||
|
|
23
app/src/main/java/org/schabi/newpipe/util/KoreUtil.java
Normal file
23
app/src/main/java/org/schabi/newpipe/util/KoreUtil.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
|
||||
public class KoreUtil {
|
||||
private KoreUtil() { }
|
||||
|
||||
public static void showInstallKoreDialog(final Context context) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage(R.string.kore_not_found)
|
||||
.setPositiveButton(R.string.install,
|
||||
(DialogInterface dialog, int which) -> NavigationHelper.installKore(context))
|
||||
.setNegativeButton(R.string.cancel, (DialogInterface dialog, int which) -> {
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
|
@ -109,12 +109,14 @@ public class NavigationHelper {
|
|||
final float playbackPitch,
|
||||
final boolean playbackSkipSilence,
|
||||
@Nullable final String playbackQuality,
|
||||
final boolean resumePlayback) {
|
||||
final boolean resumePlayback,
|
||||
final boolean startPaused) {
|
||||
return getPlayerIntent(context, targetClazz, playQueue, playbackQuality, resumePlayback)
|
||||
.putExtra(BasePlayer.REPEAT_MODE, repeatMode)
|
||||
.putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed)
|
||||
.putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch)
|
||||
.putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence);
|
||||
.putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence)
|
||||
.putExtra(BasePlayer.START_PAUSED, startPaused);
|
||||
}
|
||||
|
||||
public static void playOnMainPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
|
||||
|
|
|
@ -80,7 +80,7 @@ public abstract class Postprocessing implements Serializable {
|
|||
|
||||
private transient DownloadMission mission;
|
||||
|
||||
private File tempFile;
|
||||
private transient File tempFile;
|
||||
|
||||
Postprocessing(boolean reserveSpace, boolean worksOnSameFile, String algorithmName) {
|
||||
this.reserveSpace = reserveSpace;
|
||||
|
@ -95,8 +95,12 @@ public abstract class Postprocessing implements Serializable {
|
|||
|
||||
public void cleanupTemporalDir() {
|
||||
if (tempFile != null && tempFile.exists()) {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
tempFile.delete();
|
||||
try {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
tempFile.delete();
|
||||
} catch (Exception e) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,15 +2,10 @@ package us.shandian.giga.postprocessing;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import org.schabi.newpipe.streams.SubtitleConverter;
|
||||
import org.schabi.newpipe.streams.SrtFromTtmlWriter;
|
||||
import org.schabi.newpipe.streams.io.SharpStream;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
|
||||
/**
|
||||
* @author kapodamy
|
||||
|
@ -27,33 +22,16 @@ class TtmlConverter extends Postprocessing {
|
|||
int process(SharpStream out, SharpStream... sources) throws IOException {
|
||||
// check if the subtitle is already in srt and copy, this should never happen
|
||||
String format = getArgumentAt(0, null);
|
||||
boolean ignoreEmptyFrames = getArgumentAt(1, "true").equals("true");
|
||||
|
||||
if (format == null || format.equals("ttml")) {
|
||||
SubtitleConverter ttmlDumper = new SubtitleConverter();
|
||||
SrtFromTtmlWriter writer = new SrtFromTtmlWriter(out, ignoreEmptyFrames);
|
||||
|
||||
try {
|
||||
ttmlDumper.dumpTTML(
|
||||
sources[0],
|
||||
out,
|
||||
getArgumentAt(1, "true").equals("true"),
|
||||
getArgumentAt(2, "true").equals("true")
|
||||
);
|
||||
writer.build(sources[0]);
|
||||
} catch (Exception err) {
|
||||
Log.e(TAG, "subtitle parse failed", err);
|
||||
|
||||
if (err instanceof IOException) {
|
||||
return 1;
|
||||
} else if (err instanceof ParseException) {
|
||||
return 2;
|
||||
} else if (err instanceof SAXException) {
|
||||
return 3;
|
||||
} else if (err instanceof ParserConfigurationException) {
|
||||
return 4;
|
||||
} else if (err instanceof XPathExpressionException) {
|
||||
return 7;
|
||||
}
|
||||
|
||||
return 8;
|
||||
return err instanceof IOException ? 1 : 8;
|
||||
}
|
||||
|
||||
return OK_RESULT;
|
||||
|
|
|
@ -139,6 +139,9 @@ public class DownloadManager {
|
|||
Log.d(TAG, "Loading pending downloads from directory: " + mPendingMissionsDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
File tempDir = pickAvailableTemporalDir(ctx);
|
||||
Log.i(TAG, "using '" + tempDir + "' as temporal directory");
|
||||
|
||||
for (File sub : subs) {
|
||||
if (!sub.isFile()) continue;
|
||||
if (sub.getName().equals(".tmp")) continue;
|
||||
|
@ -184,7 +187,7 @@ public class DownloadManager {
|
|||
|
||||
if (mis.psAlgorithm != null) {
|
||||
mis.psAlgorithm.cleanupTemporalDir();
|
||||
mis.psAlgorithm.setTemporalDir(pickAvailableTemporalDir(ctx));
|
||||
mis.psAlgorithm.setTemporalDir(tempDir);
|
||||
}
|
||||
|
||||
mis.metadata = sub;
|
||||
|
@ -513,13 +516,21 @@ public class DownloadManager {
|
|||
}
|
||||
|
||||
static File pickAvailableTemporalDir(@NonNull Context ctx) {
|
||||
if (isDirectoryAvailable(ctx.getExternalFilesDir(null)))
|
||||
return ctx.getExternalFilesDir(null);
|
||||
else if (isDirectoryAvailable(ctx.getFilesDir()))
|
||||
return ctx.getFilesDir();
|
||||
File dir = ctx.getExternalFilesDir(null);
|
||||
if (isDirectoryAvailable(dir)) return dir;
|
||||
|
||||
dir = ctx.getFilesDir();
|
||||
if (isDirectoryAvailable(dir)) return dir;
|
||||
|
||||
// this never should happen
|
||||
return ctx.getDir("tmp", Context.MODE_PRIVATE);
|
||||
dir = ctx.getDir("muxing_tmp", Context.MODE_PRIVATE);
|
||||
if (isDirectoryAvailable(dir)) return dir;
|
||||
|
||||
// fallback to cache dir
|
||||
dir = ctx.getCacheDir();
|
||||
if (isDirectoryAvailable(dir)) return dir;
|
||||
|
||||
throw new RuntimeException("Not temporal directories are available");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
@ -305,7 +305,7 @@
|
|||
tools:text="English" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/share"
|
||||
android:id="@+id/kodi"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
|
@ -316,6 +316,25 @@
|
|||
android:focusable="true"
|
||||
android:padding="5dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_cast_white_24dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/play_with_kodi_title"
|
||||
tools:ignore="RtlHardcoded"
|
||||
android:visibility="visible"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/share"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_toLeftOf="@id/kodi"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="5dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_share_white_24dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/share"
|
||||
|
|
|
@ -303,7 +303,7 @@
|
|||
tools:text="English" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/share"
|
||||
android:id="@+id/kodi"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
|
@ -314,6 +314,25 @@
|
|||
android:focusable="true"
|
||||
android:padding="5dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_cast_white_24dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/play_with_kodi_title"
|
||||
tools:ignore="RtlHardcoded"
|
||||
android:visibility="visible"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/share"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_toLeftOf="@id/kodi"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="5dp"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@drawable/ic_share_white_24dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/share"
|
||||
|
|
|
@ -27,8 +27,4 @@
|
|||
android:title="@string/clear_download_history"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item android:id="@+id/action_settings"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_show_downloads"
|
||||
android:orderInCategory="980"
|
||||
android:title="@string/downloads"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_history"
|
||||
android:orderInCategory="981"
|
||||
android:title="@string/action_history"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="990"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="never"/>
|
||||
</menu>
|
|
@ -3,14 +3,4 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.schabi.newpipe.about.AboutActivity">
|
||||
|
||||
<item android:id="@+id/action_show_downloads"
|
||||
android:orderInCategory="980"
|
||||
android:title="@string/downloads"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item android:id="@+id/action_settings"
|
||||
android:orderInCategory="990"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
</menu>
|
||||
|
|
|
@ -10,11 +10,6 @@
|
|||
android:visible="true"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item android:id="@+id/action_settings"
|
||||
android:orderInCategory="990"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item android:id="@+id/action_system_audio"
|
||||
android:orderInCategory="996"
|
||||
android:title="@string/play_queue_audio_settings"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<string name="open_in_browser">在浏览器中打开</string>
|
||||
<string name="open_in_popup_mode">在悬浮窗模式下打开</string>
|
||||
<string name="did_you_mean">您是不是要找:%1$s?</string>
|
||||
<string name="no_player_found_toast">找不到串流播放器 (您可以安裝并使用VLC播放)。</string>
|
||||
<string name="no_player_found_toast">找不到串流播放器 (您可以安装 VLC 进行播放)。</string>
|
||||
<string name="controls_download_desc">下载串流文件</string>
|
||||
<string name="install">安装</string>
|
||||
<string name="cancel">取消</string>
|
||||
|
@ -16,7 +16,7 @@
|
|||
<string name="settings">设置</string>
|
||||
<string name="share_dialog_title">分享给...</string>
|
||||
<string name="choose_browser">选择浏览器</string>
|
||||
<string name="download_path_title">视频下载文件夹</string>
|
||||
<string name="download_path_title">视频下载路径</string>
|
||||
<string name="download_path_summary">已下载的视频存储在这里</string>
|
||||
<string name="download_path_dialog_title">请选择下载视频的保存位置</string>
|
||||
<string name="download_path_audio_summary">已下载的音频存储在这里</string>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<string name="disabled">禁用</string>
|
||||
<string name="controls_background_title">背景</string>
|
||||
<string name="controls_background_title">后台播放</string>
|
||||
<string name="filter">过滤器</string>
|
||||
<string name="refresh">刷新</string>
|
||||
<string name="show_search_suggestions_title">搜索建议</string>
|
||||
|
@ -157,8 +157,8 @@
|
|||
<string name="drawer_header_description">切换服务,当前选择:</string>
|
||||
<string name="no_player_found">找不到串流播放器。您想安装 VLC 吗?</string>
|
||||
<string name="screen_rotation">旋转</string>
|
||||
<string name="use_external_video_player_title">使用第三方视频播放器</string>
|
||||
<string name="use_external_audio_player_title">使用第三方视频播放器</string>
|
||||
<string name="use_external_video_player_title">使用外部视频播放器</string>
|
||||
<string name="use_external_audio_player_title">使用外部音频播放器</string>
|
||||
<string name="download_path_audio_title">音频下载文件夹</string>
|
||||
<string name="autoplay_by_calling_app_summary">从其他应用调用 NewPipe 时播放视频</string>
|
||||
<string name="default_resolution_title">默认分辨率</string>
|
||||
|
@ -209,7 +209,7 @@
|
|||
\n需要此权限</string>
|
||||
<string name="reCaptcha_title">reCAPTCHA验证</string>
|
||||
<string name="recaptcha_request_toast">请求的新的CAPTCHA验证</string>
|
||||
<string name="popup_mode_share_menu_title">NewPipe悬浮窗模式</string>
|
||||
<string name="popup_mode_share_menu_title">NewPipe 悬浮窗模式</string>
|
||||
<string name="popup_playing_toast">在悬浮窗中播放</string>
|
||||
<string name="default_popup_resolution_title">默认悬浮窗分辨率</string>
|
||||
<string name="show_higher_resolutions_title">使用更高的分辨率</string>
|
||||
|
@ -219,7 +219,7 @@
|
|||
<string name="popup_remember_size_pos_summary">记住最后一次使用悬浮窗的大小和位置</string>
|
||||
<string name="settings_category_popup_title">悬浮窗</string>
|
||||
<string name="popup_resizing_indicator_title">调整大小</string>
|
||||
<string name="use_external_video_player_summary">删除“某些”分辨率的音频</string>
|
||||
<string name="use_external_video_player_summary">部分分辨率的视频将没有声音</string>
|
||||
<string name="player_gesture_controls_title">播放器手势控制</string>
|
||||
<string name="player_gesture_controls_summary">使用手势控制播放器的亮度和音量</string>
|
||||
<string name="show_search_suggestions_summary">显示搜索建议</string>
|
||||
|
@ -234,9 +234,9 @@
|
|||
<string name="channel_unsubscribed">取消订阅频道</string>
|
||||
<string name="subscription_change_failed">无法修改订阅</string>
|
||||
<string name="subscription_update_failed">无法更新订阅</string>
|
||||
<string name="tab_main">主页面</string>
|
||||
<string name="tab_main">主页</string>
|
||||
<string name="tab_subscriptions">订阅</string>
|
||||
<string name="fragment_whats_new">新增功能</string>
|
||||
<string name="fragment_whats_new">最新</string>
|
||||
<string name="resume_on_audio_focus_gain_title">恢复前台焦点</string>
|
||||
<string name="resume_on_audio_focus_gain_summary">中断后继续播放(例如突然来电后)</string>
|
||||
<string name="enable_search_history_title">搜索历史记录</string>
|
||||
|
@ -321,7 +321,7 @@
|
|||
<string name="could_not_import_all_files">警告:无法导入所有文件。</string>
|
||||
<string name="override_current_data">这将覆盖当前设置。</string>
|
||||
<string name="show_info">显示信息</string>
|
||||
<string name="tab_bookmarks">已收藏</string>
|
||||
<string name="tab_bookmarks">书签</string>
|
||||
<string name="delete_stream_history_prompt">确定要从观看历史记录中删除该项吗?</string>
|
||||
<string name="delete_all_history_prompt">是否确实要从历史记录中删除所有项目?</string>
|
||||
<string name="title_last_played">最后播放</string>
|
||||
|
@ -516,8 +516,8 @@
|
|||
</plurals>
|
||||
<string name="localization_changes_requires_app_restart">重新启动应用后,语言将更改。</string>
|
||||
<string name="peertube_instance_url_title">PeerTube 服务器</string>
|
||||
<string name="peertube_instance_url_summary">设置自己喜欢的peertube服务器</string>
|
||||
<string name="peertube_instance_url_help">查找最适合你的服务器https://joinpeertube.org/instances#instances-list</string>
|
||||
<string name="peertube_instance_url_summary">设置自己喜欢的PeerTube服务器</string>
|
||||
<string name="peertube_instance_url_help">查找最适合你的服务器%s</string>
|
||||
<string name="peertube_instance_add_title">添加服务器</string>
|
||||
<string name="peertube_instance_add_help">输入服务器网址</string>
|
||||
<string name="peertube_instance_add_fail">无法验证服务器</string>
|
||||
|
@ -533,4 +533,7 @@
|
|||
<string name="seek_duration_title">快进 / 快退的单位时间</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">在锁屏界面显示视频缩略图</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">在后台播放时,锁屏界面将会显示视频的缩略图</string>
|
||||
<string name="clear_download_history">清除下载历史记录</string>
|
||||
<string name="delete_downloaded_files">删除下载了的文件</string>
|
||||
<string name="deleted_downloads">已删除 %1$s 下载</string>
|
||||
</resources>
|
|
@ -79,7 +79,7 @@
|
|||
<string name="your_comment">Dein Kommentar (auf englisch):</string>
|
||||
<string name="could_not_get_stream">Konnte keinen Stream abrufen</string>
|
||||
<string name="autoplay_by_calling_app_title">Automatische Wiedergabe</string>
|
||||
<string name="autoplay_by_calling_app_summary">Wiedergabe eines Videos, wenn NewPipe von einer anderen App aufgerufen wurde</string>
|
||||
<string name="autoplay_by_calling_app_summary">Video abspielen, wenn NewPipe von einer anderen App aufgerufen wird</string>
|
||||
<string name="report_error">Einen Fehler melden</string>
|
||||
<string name="user_report">Anwenderbericht</string>
|
||||
<string name="duration_live">LIVE</string>
|
||||
|
@ -489,7 +489,7 @@
|
|||
<string name="error_postprocessing_stopped">NewPipe wurde während der Verarbeitung der Datei geschlossen</string>
|
||||
<string name="error_insufficient_storage">Kein Speicherplatz mehr auf dem Gerät</string>
|
||||
<string name="error_progress_lost">Vorgang abgebrochen, da die Datei gelöscht wurde</string>
|
||||
<string name="confirm_prompt">Bist Du sicher\?</string>
|
||||
<string name="confirm_prompt">Möchtest du deinen Downloadverlauf oder alle heruntergeladenen Dateien löschen\?</string>
|
||||
<string name="enable_queue_limit">Downloadwarteschlange begrenzen</string>
|
||||
<string name="enable_queue_limit_desc">Ein Download wird zur gleichen Zeit ausgeführt</string>
|
||||
<string name="start_downloads">Downloads starten</string>
|
||||
|
@ -536,4 +536,7 @@
|
|||
<string name="error_download_resource_gone">Dieser Download kann nicht wiederhergestellt werden</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Video-Vorschaubild für Sperrbildschirm aktivieren</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">Bei Verwendung des Hintergrundplayers wird ein Video-Miniaturbild auf dem Sperrbildschirm angezeigt</string>
|
||||
<string name="clear_download_history">Downloadverlauf löschen</string>
|
||||
<string name="delete_downloaded_files">Heruntergeladene Dateien löschen</string>
|
||||
<string name="deleted_downloads">%1$s Downloads gelöscht</string>
|
||||
</resources>
|
|
@ -15,9 +15,9 @@
|
|||
<string name="screen_rotation">turno</string>
|
||||
<string name="use_external_video_player_title">Uzi eksteran filmetoludilon</string>
|
||||
<string name="use_external_audio_player_title">Uzi eksteran sonludilon</string>
|
||||
<string name="default_resolution_title">Defaŭlta distingivo</string>
|
||||
<string name="play_with_kodi_title">Legi per Kodi</string>
|
||||
<string name="show_play_with_kodi_title">Montri \"Legi per Kodi\"-opcion</string>
|
||||
<string name="default_resolution_title">Defaŭlta rezolucio</string>
|
||||
<string name="play_with_kodi_title">Ludi per Kodi</string>
|
||||
<string name="show_play_with_kodi_title">Montri \"Ludi per Kodi\"-opcion</string>
|
||||
<string name="play_audio">Sono</string>
|
||||
<string name="default_audio_format_title">Defaŭlta sondosierformo</string>
|
||||
<string name="theme_title">Etoso</string>
|
||||
|
@ -30,8 +30,8 @@
|
|||
<string name="settings_category_video_audio_title">Filmeto kaj sono</string>
|
||||
<string name="settings_category_appearance_title">Apero</string>
|
||||
<string name="settings_category_other_title">Alia</string>
|
||||
<string name="background_player_playing_toast">Ludado fone</string>
|
||||
<string name="play_btn_text">Legi</string>
|
||||
<string name="background_player_playing_toast">Ludanta fone</string>
|
||||
<string name="play_btn_text">Ludi</string>
|
||||
<string name="general_error">Eraro</string>
|
||||
<string name="network_error">Reteraro</string>
|
||||
<string name="content_not_available">Enhavo malhavebla</string>
|
||||
|
@ -45,7 +45,7 @@
|
|||
<string name="youtube_signature_decryption_error">La subskribo de la ligilo de la filmeto ne malĉifreblas</string>
|
||||
<string name="parsing_error">La retejo ne analizeblas</string>
|
||||
<string name="list_thumbnail_view_description">Bildeto de la antaŭrigardo de la filmeto</string>
|
||||
<string name="detail_thumbnail_view_description">Legi filmeton, daŭro:</string>
|
||||
<string name="detail_thumbnail_view_description">Ludi filmeton, daŭro:</string>
|
||||
<string name="detail_uploader_thumbnail_view_description">Bildeto de la alŝutinto</string>
|
||||
<string name="err_dir_create">La elŝutujo \'%1$s\' ne kreeblas</string>
|
||||
<string name="info_dir_created">Elŝutujo \'%1$s\' kreita</string>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<string name="main_bg_subtitle">Premu serĉo por komenci</string>
|
||||
<string name="no_player_found_toast">Neniu elsendlflua ludilo trovita (instalu VLC por ludi ĝin).</string>
|
||||
<string name="open_in_popup_mode">Malfermi en ŝprucfenestron modon</string>
|
||||
<string name="use_external_video_player_summary">Forigas aŭdion ĉe KELKAJ distingivoj</string>
|
||||
<string name="use_external_video_player_summary">Forigas aŭdon ĉe KELKAJ rezolucioj</string>
|
||||
<string name="popup_mode_share_menu_title">NewPipe ŝprucfenestron modon</string>
|
||||
<string name="subscribe_button_title">Aboni</string>
|
||||
<string name="subscribed_button_title">Abonita</string>
|
||||
|
@ -86,10 +86,10 @@
|
|||
<string name="controls_popup_title">Ŝprucfenestro</string>
|
||||
<string name="controls_add_to_playlist_title">Aldonu al</string>
|
||||
<string name="autoplay_by_calling_app_title">Aŭtomata play</string>
|
||||
<string name="autoplay_by_calling_app_summary">Legas filmeton kiam NewPipe vokas de alia programo</string>
|
||||
<string name="default_popup_resolution_title">Defaŭlta distingivo de la ŝprucfenestro</string>
|
||||
<string name="show_higher_resolutions_title">Montri pli altajn distingivojn</string>
|
||||
<string name="show_higher_resolutions_summary">Nur kelkaj aparatoj subtenas legante 2K / 4K filmetojn</string>
|
||||
<string name="autoplay_by_calling_app_summary">Ludas filmeton kiam NewPipe vokas el alia programo</string>
|
||||
<string name="default_popup_resolution_title">Defaŭlta rezolucio de la ŝprucfenestro</string>
|
||||
<string name="show_higher_resolutions_title">Montri pli altajn rezoluciojn</string>
|
||||
<string name="show_higher_resolutions_summary">Nur kelkaj aparatoj subtenas ludi 2K / 4K filmetojn</string>
|
||||
<string name="default_video_format_title">Defaŭlta fomato de filmeto</string>
|
||||
<string name="black_theme_title">Nigra</string>
|
||||
<string name="popup_remember_size_pos_title">Memoru ŝprucfenestron kaj pozicion</string>
|
||||
|
@ -122,7 +122,7 @@
|
|||
<string name="later">Poste</string>
|
||||
<string name="msg_popup_permission">Tiu permeso estas necesa por
|
||||
\nmalfermi en ŝprucfenestro modo</string>
|
||||
<string name="popup_playing_toast">Leganta en ŝprucfenestro modo</string>
|
||||
<string name="popup_playing_toast">Ludanta en ŝprucfenestro modo</string>
|
||||
<string name="disabled">Malaktiva</string>
|
||||
<string name="filter">Filtri</string>
|
||||
<string name="refresh">Aktualigi</string>
|
||||
|
@ -133,13 +133,13 @@
|
|||
<string name="player_gesture_controls_summary">Uzu gestojn por kontroli la brilon kaj volumenon de la ludilo</string>
|
||||
<string name="show_search_suggestions_title">Serĉi sugestojn</string>
|
||||
<string name="show_search_suggestions_summary">Montri sugestojn kiam serĉanto</string>
|
||||
<string name="best_resolution">Plej bona distingivo</string>
|
||||
<string name="best_resolution">Plej bona rezolucio</string>
|
||||
<string name="app_description">Libera malpeza torentado ĉe Android.</string>
|
||||
<string name="settings_category_downloads_title">Elŝuti</string>
|
||||
<string name="charset_letters_and_digits">Leteroj kaj ciferoj</string>
|
||||
<string name="charset_most_special_characters">Plej specialaj karakteroj</string>
|
||||
<string name="resume_on_audio_focus_gain_title">Rekomencu en fokusa gajno</string>
|
||||
<string name="resume_on_audio_focus_gain_summary">Daŭrigi la legon post la interrompaĵoj (ekzemple telefonadoj)</string>
|
||||
<string name="resume_on_audio_focus_gain_summary">Daŭrigi la ludon post la interrompaĵoj (ekzemple telefonadoj)</string>
|
||||
<string name="enable_search_history_title">Serĉa historio</string>
|
||||
<string name="enable_search_history_summary">Konservi la historio de serĉo lokale</string>
|
||||
<string name="enable_watch_history_title">Rigardu historion</string>
|
||||
|
@ -205,7 +205,7 @@
|
|||
<string name="playlist_delete_failure">Ne povis forigi ludlisto.</string>
|
||||
<string name="settings_category_debug_title">Malcimigi</string>
|
||||
<string name="auto_queue_title">Auto-vico sekva fluo</string>
|
||||
<string name="auto_queue_summary">Aŭto-aldoni rilatan enhavon kiam leganta la lasta enhavo en malrepetita atendovico</string>
|
||||
<string name="auto_queue_summary">Aŭto-aldoni rilatan enhavon kiam ludanta la lasta enhavo en malrepetita atendovico</string>
|
||||
<string name="file">Dosiero</string>
|
||||
<string name="invalid_directory">Tia dosierujo ne ekzistas</string>
|
||||
<string name="invalid_source">Tia dosiero/enhavo ne ekzistas</string>
|
||||
|
@ -236,7 +236,7 @@
|
|||
<string name="clear_search_history_summary">Forviŝi la serĉajn ŝlosilvortojn</string>
|
||||
<string name="delete_search_history_alert">Ĉu vi volas forviŝi la totalon de la historio de serĉo \?</string>
|
||||
<string name="search_history_deleted">Historio de serĉo forviŝita.</string>
|
||||
<string name="limit_mobile_data_usage_title">Limigi distingivo kiam uzanta moveblan datumon</string>
|
||||
<string name="limit_mobile_data_usage_title">Limigi rezolucio kiam uzanta moveblan datumon</string>
|
||||
<string name="minimize_on_exit_popup_description">Minimumigi al ŝprucfenestro ludilo</string>
|
||||
<string name="channels">Kanaloj</string>
|
||||
<string name="playlists">Ludlistoj</string>
|
||||
|
@ -265,7 +265,7 @@
|
|||
<string name="conferences">Konferencoj</string>
|
||||
<string name="show_comments_title">Montri komentojn</string>
|
||||
<string name="show_comments_summary">Malebligu por malvidigi komentojn</string>
|
||||
<string name="autoplay_title">Aŭtolego</string>
|
||||
<string name="autoplay_title">Aŭtoludo</string>
|
||||
<plurals name="comments">
|
||||
<item quantity="one">Komentoj</item>
|
||||
<item quantity="other"/>
|
||||
|
@ -342,7 +342,7 @@
|
|||
<string name="view_on_github">Rigardu ĉe GitHub</string>
|
||||
<string name="app_license_title">Permesilo de NewPipe</string>
|
||||
<string name="contribution_encouragement">Ĉu vi havas ideojn pri; traduko, desegnaĵoj ŝanĝoj, purigado de kodo, aŭ realaj masivaj ŝanĝoj—helpo estas ĉiam bonvena. Ju pli oni faras, des pli bonas!</string>
|
||||
<string name="read_full_license">Legu permesilon</string>
|
||||
<string name="read_full_license">Legi permesilon</string>
|
||||
<string name="contribution_title">Kontribui</string>
|
||||
<string name="settings_file_charset_title">Permesitaj karakteroj en dosiernomoj</string>
|
||||
<string name="settings_file_replacement_character_summary">Nevalidaj karakteroj estas anstataŭigita kun ĉi tiu valoro</string>
|
||||
|
@ -375,7 +375,7 @@
|
|||
<string name="no_channel_subscribed_yet">Neniuj kanalaj abonoj ankoraŭ</string>
|
||||
<string name="select_a_kiosk">Elekti kioskon</string>
|
||||
<string name="start_here_on_main">Komenci ludi ĉi tie</string>
|
||||
<string name="start_here_on_background">Komenci ludi en la fono</string>
|
||||
<string name="start_here_on_background">Komenci ludi fone</string>
|
||||
<string name="donation_title">Donaci</string>
|
||||
<string name="donation_encouragement">NewPipe estas programada par volontuoj, elspezante tempo por alporti vin la plej bona sperto. Redonu por helpi programistojn plibonigi NewPipe dum ĝuante tason da kafo.</string>
|
||||
<string name="give_back">Redoni</string>
|
||||
|
@ -413,7 +413,7 @@
|
|||
<string name="enable_leak_canary_summary">La monitorado de la memorlikadoj povas frostigi la apon dum la hejta dumpingo</string>
|
||||
<string name="enable_disposed_exceptions_title">Signali ekster-vivciklajn erarojn</string>
|
||||
<string name="enable_disposed_exceptions_summary">Perforti signalante neenretigaj Rx esceptoj eksere la fragmento aŭ aktiveco vivciklo post dispono</string>
|
||||
<string name="invalid_file">La dosiero ne ekzistas aŭ la legopermeso mankas</string>
|
||||
<string name="invalid_file">La dosiero ne ekzistas aŭ la ludopermeso mankas</string>
|
||||
<string name="import_export_title">Importi/eksporti</string>
|
||||
<string name="import_title">Importi</string>
|
||||
<string name="import_from">Importi el</string>
|
||||
|
@ -440,10 +440,10 @@
|
|||
<string name="app_license">NewPipe estas programaro sub rajtoceda permesilo: Vi povas uzi, studi, komuniki kaj plibonigi ĝin kiel vi volas. Precize, vi povas redistribui kaj/aŭ modifi ĝin sub la kondiĉoj de la Ĝenerala Publika Permesilo de GNU, kiel publikigita per la Free Software Foundation, ĉu en la versio 3, ĉu (se vi volas) ajna posta versio.</string>
|
||||
<string name="import_settings">Ĉu vi volas ankaŭ importi agordojn\?</string>
|
||||
<string name="privacy_policy_title">Privateca politiko de NewPipe</string>
|
||||
<string name="privacy_policy_encouragement">La NewPipe projekto respektas vian privatecon serioze. Konsekvence, la apo ne kolektas ajnan datumo sen via konsento.
|
||||
<string name="privacy_policy_encouragement">La NewPipe projekto serioze respektas vian privatecon. Konsekvence, la apo ne kolektas ajnan datumo sen via konsento.
|
||||
\nLa privateco politiko de Newpipe detale eksplikas kion datumon estas sendita kaj stokita kiam vi sendas falegosignalon.</string>
|
||||
<string name="read_privacy_policy">Legi la privatecan politikon</string>
|
||||
<string name="start_accept_privacy_policy">Por konformiĝi al la Ĝenerala Datum-Protekta Regularon (GDPR), ni allogas vian atento al la privateca politiko de NewPipe. Bonvolu legi ĝin atentive.
|
||||
<string name="start_accept_privacy_policy">Por konformiĝi al la Ĝenerala Datum-Protekta Regularon (GDPR), ni allogas vian atenton al la privateca politiko de NewPipe. Bonvolu atentive legi ĝin.
|
||||
\nVi devas akcepti ĝin por sendi nin la cimsignalo.</string>
|
||||
<string name="accept">Akcepti</string>
|
||||
<string name="decline">Rifuzi</string>
|
||||
|
@ -455,7 +455,7 @@
|
|||
<string name="skip_silence_checkbox">Plirapidigi dum silentoj</string>
|
||||
<string name="playback_step">Paŝo</string>
|
||||
<string name="playback_reset">Restarigi</string>
|
||||
<string name="saved_tabs_invalid_json">Uzante defaŭltajn ongletojn, eraro dum leganta savajn ongletojn</string>
|
||||
<string name="saved_tabs_invalid_json">Uzante defaŭltajn ongletojn, eraro ludante savajn ongletojn</string>
|
||||
<string name="restore_defaults">Restaŭri la defaŭltojn</string>
|
||||
<string name="restore_defaults_confirmation">Ĉu vi volas restaŭri la defaŭltojn \?</string>
|
||||
<string name="subscribers_count_not_available">Kalkulo de abonantoj malhavebla</string>
|
||||
|
|
|
@ -520,16 +520,18 @@
|
|||
<string name="localization_changes_requires_app_restart">El idioma cambiará luego de que la app sea reiniciada.</string>
|
||||
<string name="seek_duration_title">Duración de búsqueda al avanzar y/o retroceder</string>
|
||||
<string name="peertube_instance_url_title">Instancias de PeerTube</string>
|
||||
<string name="peertube_instance_url_summary">Elige tus instancias favoritas de PeerTube</string>
|
||||
<string name="peertube_instance_url_help">Encuentra las mejores instancias para ti en https://joinpeertube.org/instances#instances-list</string>
|
||||
<string name="peertube_instance_url_summary">Selecciona tus instancias favoritas de PeerTube</string>
|
||||
<string name="peertube_instance_url_help">Encuentra las mejores instancias para ti en %s</string>
|
||||
<string name="peertube_instance_add_title">Agregar instancia</string>
|
||||
<string name="peertube_instance_add_help">Dirección URL de la instancia</string>
|
||||
<string name="peertube_instance_add_fail">Error al validar la instancia</string>
|
||||
<string name="peertube_instance_add_https_only">Sólo URLs con HTTPS</string>
|
||||
<string name="peertube_instance_add_help">Ingresar URL de la instancia</string>
|
||||
<string name="peertube_instance_add_fail">No se pudo validar la instancia</string>
|
||||
<string name="peertube_instance_add_https_only">Sólo URLs con HTTPS son soportados</string>
|
||||
<string name="peertube_instance_add_exists">La instancia ya existe</string>
|
||||
<string name="local">Local</string>
|
||||
<string name="recently_added">Agregados recientemente</string>
|
||||
<string name="most_liked">Más gustados</string>
|
||||
<string name="playlist_no_uploader">Generado automáticamente (no se encontró creador)</string>
|
||||
<string name="choose_instance_prompt">Elige una instancia</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Habilitar miniatura de video de la pantalla de bloqueo</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">Al usar el reproductor de fondo, se mostrará una miniatura de video en la pantalla de bloqueo</string>
|
||||
</resources>
|
|
@ -122,7 +122,7 @@
|
|||
<string name="short_million">M</string>
|
||||
<string name="msg_popup_permission">Cette autorisation est nécessaire pour
|
||||
\nutiliser le mode flottant</string>
|
||||
<string name="controls_background_title">Arrière-plan</string>
|
||||
<string name="controls_background_title">Lire l\'audio</string>
|
||||
<string name="controls_popup_title">Flottant</string>
|
||||
<string name="default_popup_resolution_title">Définition de la fenêtre flottante par défaut</string>
|
||||
<string name="show_higher_resolutions_title">Afficher des définitions plus élevées</string>
|
||||
|
@ -185,7 +185,7 @@
|
|||
<string name="notification_channel_name">Notification NewPipe</string>
|
||||
<string name="undo">Annuler</string>
|
||||
<string name="enable_watch_history_summary">Garde un suivi des vidéos vues</string>
|
||||
<string name="resume_on_audio_focus_gain_title">Reprendre à l’obtention de la cible de saisie</string>
|
||||
<string name="resume_on_audio_focus_gain_title">Reprendre lors du retour dans l\'application</string>
|
||||
<string name="settings_category_player_title">Lecteur</string>
|
||||
<string name="settings_category_player_behavior_title">Comportement</string>
|
||||
<string name="settings_category_history_title">Historique et cache</string>
|
||||
|
@ -310,7 +310,7 @@
|
|||
<string name="use_inexact_seek_title">Utiliser la recherche rapide approximative</string>
|
||||
<string name="use_inexact_seek_summary">Permet au lecteur d’accéder plus rapidement à une position au détriment de la précision</string>
|
||||
<string name="download_thumbnail_title">Charger les miniatures</string>
|
||||
<string name="download_thumbnail_summary">Désactiver pour empêcher le chargement des miniatures afin d\'économiser vos données. Modifier cette option vide le cache en mémoire vive et sur le disque.</string>
|
||||
<string name="download_thumbnail_summary">Désactivez pour empêcher le chargement des miniatures afin de réduire l’utilisation de la bande passante et de la mémoire. La modification de cette option, vide le cache en mémoire vive et sur le disque.</string>
|
||||
<string name="thumbnail_cache_wipe_complete_notice">Images en cache effacées</string>
|
||||
<string name="metadata_cache_wipe_title">Effacer les métadonnées en cache</string>
|
||||
<string name="metadata_cache_wipe_summary">Efface toutes les données de pages Web en cache</string>
|
||||
|
@ -534,5 +534,5 @@
|
|||
<string name="choose_instance_prompt">Choisissez une instance</string>
|
||||
<string name="playlist_no_uploader">Généré automatiquement (pas de téléverseur trouvé)</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Activer la vidéo miniaturisée sur l\'écran de verrouillage</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">En utilisant le lecteur en arrière-plan, une vidéo miniaturisé sera affichée sur l\'écran de verrouillage</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">En utilisant le lecteur audio, la miniature de la vidéo sera affichée sur l\'écran de verrouillage</string>
|
||||
</resources>
|
|
@ -496,7 +496,7 @@
|
|||
<string name="error_insufficient_storage">לא נשאר מקום במכשיר</string>
|
||||
<string name="error_progress_lost">התהליך אבד כיוון שהקובץ נמחק</string>
|
||||
<string name="error_timeout">החיבור המתין זמן רב מדי</string>
|
||||
<string name="confirm_prompt">בוודאות\?</string>
|
||||
<string name="confirm_prompt">למחוק את היסטוריית ההורדות שלך או למחוק את כל הקבצים שהורדת\?</string>
|
||||
<string name="enable_queue_limit">הגבלת תור ההורדה</string>
|
||||
<string name="enable_queue_limit_desc">רק הורדה אחת תרוץ בו־זמנית</string>
|
||||
<string name="start_downloads">התחלת הורדות</string>
|
||||
|
@ -547,4 +547,7 @@
|
|||
<string name="choose_instance_prompt">נא לבחור מופע</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">הפעלת תמונה מוקטנת של הסרטון במסך הנעילה</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">בעת השימוש בנגן הרקע תופיע תמונה מוקטנת של הסרטון על מסך הנעילה</string>
|
||||
<string name="clear_download_history">מחיקת היסטוריית ההורדות</string>
|
||||
<string name="delete_downloaded_files">למחוק את הקבצים שהורדתי</string>
|
||||
<string name="deleted_downloads">נמחקו %1$s הורדות</string>
|
||||
</resources>
|
|
@ -521,4 +521,9 @@
|
|||
<string name="recently_added">Nylig lagt til</string>
|
||||
<string name="most_liked">Mest likt</string>
|
||||
<string name="choose_instance_prompt">Velg en instans</string>
|
||||
<string name="clear_download_history">Tøm nedlastingshistorikk</string>
|
||||
<string name="delete_downloaded_files">Slett nedlastede filer</string>
|
||||
<string name="deleted_downloads">Slettet %1$s nedlastninger</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Aktiver videominiatyrbilde med låseskjerm</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">Når du bruker bakgrunnsspilleren, vises en videominiaturbilde på låseskjermen</string>
|
||||
</resources>
|
|
@ -2,8 +2,8 @@
|
|||
<resources>
|
||||
<string name="view_count_text">%1$s vistas</string>
|
||||
<string name="upload_date_text">Publicat lo %1$s</string>
|
||||
<string name="no_player_found">Cap de lector de flus trobat. Volètz installar VLC\?</string>
|
||||
<string name="no_player_found_toast">Cap de lector de flus trobat (podètz installar VLC per lo legir).</string>
|
||||
<string name="no_player_found">Cap de legidor de flus trobat. Volètz installar VLC\?</string>
|
||||
<string name="no_player_found_toast">Cap de legidor de flus trobat (podètz installar VLC per lo legir).</string>
|
||||
<string name="install">Installar</string>
|
||||
<string name="cancel">Anullar</string>
|
||||
<string name="open_in_browser">Dobrir dins lo navegador</string>
|
||||
|
@ -17,7 +17,7 @@
|
|||
<string name="share_dialog_title">Partejar amb</string>
|
||||
<string name="choose_browser">Causir un navegador</string>
|
||||
<string name="screen_rotation">rotacion</string>
|
||||
<string name="use_external_video_player_title">Utilizar un lector de vidèo extèrne</string>
|
||||
<string name="use_external_video_player_title">Utilizar un legidor de vidèo extèrne</string>
|
||||
<string name="popup_mode_share_menu_title">Mòde fenestron de NewPipe</string>
|
||||
<string name="subscribe_button_title">S\'abonar</string>
|
||||
<string name="subscribed_button_title">Abonat</string>
|
||||
|
@ -27,4 +27,50 @@
|
|||
<string name="show_info">Afichar las informacions</string>
|
||||
<string name="tab_main">Principal</string>
|
||||
<string name="tab_subscriptions">Abonaments</string>
|
||||
<string name="main_bg_subtitle">Clicatz sul boton de recèrca per començar</string>
|
||||
<string name="use_external_video_player_summary">Lèva l\'àudio per CÈRTAS resolucions</string>
|
||||
<string name="use_external_audio_player_title">Utilizar lo legidor àudio extèrne</string>
|
||||
<string name="channel_unsubscribed">Abonament a la cadena anullat</string>
|
||||
<string name="tab_bookmarks">Listas de lectura enregistradas</string>
|
||||
<string name="tab_new">Onglet novèl</string>
|
||||
<string name="tab_choose">Causir un onglet</string>
|
||||
<string name="fragment_whats_new">Çò novèl</string>
|
||||
<string name="controls_background_title">Rèireplan</string>
|
||||
<string name="controls_popup_title">Fenestron</string>
|
||||
<string name="controls_add_to_playlist_title">Apondre a</string>
|
||||
<string name="download_path_title">Dorsièr de telecargament de vidèos</string>
|
||||
<string name="download_path_summary">Los fichièrs vidèo telecargats son aquí</string>
|
||||
<string name="download_path_dialog_title">Causissètz lo dorsièr de telecargament de las vidèos</string>
|
||||
<string name="download_path_audio_title">Dorsièr de telecargament dels àudios</string>
|
||||
<string name="download_path_audio_summary">Los fichièrs àudio telecargats son estremats aicí</string>
|
||||
<string name="download_path_audio_dialog_title">Causissètz lo dorsièr de telecargament pels àudios</string>
|
||||
<string name="download_choose_new_path">Cambiatz los dorsièrs de telecargament per venga efectiu</string>
|
||||
<string name="autoplay_by_calling_app_title">Lectura automatica</string>
|
||||
<string name="autoplay_by_calling_app_summary">Legís una vidèo quand NewPIpe es apelat dempuèi una autra aplicacion</string>
|
||||
<string name="default_resolution_title">Resolucion per defaut</string>
|
||||
<string name="default_popup_resolution_title">Resolucion per defaut dels fenestrons</string>
|
||||
<string name="show_higher_resolutions_title">Afichar de resolucions mai nautas</string>
|
||||
<string name="show_higher_resolutions_summary">Totes los dispositius pòdon pas legir de vidèos 2K/4K</string>
|
||||
<string name="play_with_kodi_title">Jogar amb Kodi</string>
|
||||
<string name="kore_not_found">Trobam pas l\'aplicacion Kore. La volètz installar\?</string>
|
||||
<string name="show_play_with_kodi_title">Afichar l\'opcion \"Legir amb Kodi\"</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Activar la vidèo miniatura sus l\'ecran de blocatge</string>
|
||||
<string name="show_play_with_kodi_summary">Afichar una opcion per legir una vidèo dempuèi Kodi</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">En utilizant lo legidor de rèireplan, una vidèo miniatura s\'aficharà sus l\'ecran de blocatge</string>
|
||||
<string name="play_audio">Àudio</string>
|
||||
<string name="default_audio_format_title">Format àudio per defaut</string>
|
||||
<string name="default_video_format_title">Format vidèo per defaut</string>
|
||||
<string name="theme_title">Tèma</string>
|
||||
<string name="light_theme_title">Clar</string>
|
||||
<string name="dark_theme_title">Escur</string>
|
||||
<string name="black_theme_title">Negre</string>
|
||||
<string name="popup_remember_size_pos_title">Se remembrar la talha e la posicion del fenestron</string>
|
||||
<string name="popup_remember_size_pos_summary">Se remembrar las darrièras talha e posicion del fenestron</string>
|
||||
<string name="use_inexact_seek_title">Utilzar la recèrca rapida inexacta</string>
|
||||
<string name="use_inexact_seek_summary">La recèrca inexacta permet a l\'utilizaire de recercar mai rapidament una posicion amb mens de precision</string>
|
||||
<string name="seek_duration_title">Durada d\'avançada/reculada rapida</string>
|
||||
<string name="download_thumbnail_title">Cargar las miniaturas</string>
|
||||
<string name="show_comments_title">Afichar los comentaris</string>
|
||||
<string name="show_comments_summary">Desactivar per afichar pas mai los comentaris</string>
|
||||
<string name="auto_queue_title">Apondre la vidèo seguenta dins la coa de lectura</string>
|
||||
</resources>
|
|
@ -491,7 +491,7 @@
|
|||
<string name="error_postprocessing_stopped">NewPipe został zamknięty podczas pracy nad plikiem</string>
|
||||
<string name="error_insufficient_storage">Brak miejsca na urządzeniu</string>
|
||||
<string name="error_progress_lost">Postęp został utracony ze wzgledu na usunięcie pliku</string>
|
||||
<string name="confirm_prompt">Czy jesteś pewien\?</string>
|
||||
<string name="confirm_prompt">Czy chcesz wyczyścić historię pobierania lub usunąć wszystkie pobrane pliki\?</string>
|
||||
<string name="enable_queue_limit">Ogranicz kolejkę pobierania</string>
|
||||
<string name="enable_queue_limit_desc">Tylko jedno pobieranie będzie realizowane jednocześnie</string>
|
||||
<string name="start_downloads">Rozpocznij pobieranie</string>
|
||||
|
@ -541,4 +541,7 @@
|
|||
<string name="choose_instance_prompt">Wybierz instancję</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Włącz miniaturę wideo na ekranie blokady</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">Podczas korzystania z odtwarzacza w tle na ekranie blokady zostanie wyświetlona miniatura filmu</string>
|
||||
<string name="clear_download_history">Wyczyść historię pobierania</string>
|
||||
<string name="delete_downloaded_files">Usuń pobrane pliki</string>
|
||||
<string name="deleted_downloads">Usunięte% 1$s pobrania</string>
|
||||
</resources>
|
|
@ -492,7 +492,7 @@
|
|||
<string name="error_postprocessing_stopped">NewPipe была закрыта во время работы над файлом</string>
|
||||
<string name="error_insufficient_storage">Закончилось свободное место на устройстве</string>
|
||||
<string name="error_progress_lost">Прогресс потерян, так как файл был удалён</string>
|
||||
<string name="confirm_prompt">Вы уверены\?</string>
|
||||
<string name="confirm_prompt">Действительно удалить историю загрузок и загруженные файлы\?</string>
|
||||
<string name="enable_queue_limit">Ограничить очередь загрузки</string>
|
||||
<string name="enable_queue_limit_desc">Только одна одновременная загрузка</string>
|
||||
<string name="start_downloads">Начать загрузку</string>
|
||||
|
@ -522,10 +522,10 @@
|
|||
<item quantity="many">%s слушателей</item>
|
||||
</plurals>
|
||||
<string name="localization_changes_requires_app_restart">Язык будет изменён после перезапуска</string>
|
||||
<string name="seek_duration_title">Перемотка двойным нажатием</string>
|
||||
<string name="seek_duration_title">Шаг перемотки</string>
|
||||
<string name="peertube_instance_url_title">Серверы PeerTube</string>
|
||||
<string name="peertube_instance_url_summary">Выберите предпочтительные серверы PeerTube</string>
|
||||
<string name="peertube_instance_url_help">Выберите подходящие серверы на %s</string>
|
||||
<string name="peertube_instance_url_summary">Выберите предпочтительные серверы</string>
|
||||
<string name="peertube_instance_url_help">Каталог серверов: %s</string>
|
||||
<string name="peertube_instance_add_title">Новый сервер</string>
|
||||
<string name="peertube_instance_add_help">URL сервера</string>
|
||||
<string name="peertube_instance_add_fail">Не удалось проверить сервер</string>
|
||||
|
@ -540,4 +540,7 @@
|
|||
<string name="choose_instance_prompt">Выберите сервер</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Миниатюра на экране блокировки</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">Показать миниатюру видео на экране блокировки при воспроизведении в фоне</string>
|
||||
<string name="clear_download_history">Очистить историю загрузок</string>
|
||||
<string name="delete_downloaded_files">Удаление загруженных файлов</string>
|
||||
<string name="deleted_downloads">Удалено загрузок: %1$s</string>
|
||||
</resources>
|
|
@ -5,7 +5,7 @@
|
|||
<string name="upload_date_text">Yayınlanma: %1$s</string>
|
||||
<string name="no_player_found">Akış oynatıcısı bulunamadı. VLC\'yi yüklemek ister misiniz\?</string>
|
||||
<string name="install">Yükle</string>
|
||||
<string name="cancel">İptal et</string>
|
||||
<string name="cancel">Vazgeç</string>
|
||||
<string name="open_in_browser">Tarayıcıda aç</string>
|
||||
<string name="share">Paylaş</string>
|
||||
<string name="download">İndir</string>
|
||||
|
@ -484,7 +484,7 @@
|
|||
<string name="error_insufficient_storage">Aygıt üzerinde yer yok</string>
|
||||
<string name="error_progress_lost">İlerleme kaybedildi, çünkü dosya silinmiş</string>
|
||||
<string name="error_timeout">Bağlantı zaman aşımı</string>
|
||||
<string name="confirm_prompt">Emin misiniz\?</string>
|
||||
<string name="confirm_prompt">İndirme geçmişinizi temizlemek veya indirilen tüm dosyaları silmek istiyor musunuz\?</string>
|
||||
<string name="enable_queue_limit">İndirme kuyruğunu sınırla</string>
|
||||
<string name="enable_queue_limit_desc">Aynı anda yalnızca bir indirme yürütülecek</string>
|
||||
<string name="start_downloads">İndirmeleri başlat</string>
|
||||
|
@ -535,4 +535,7 @@
|
|||
<string name="choose_instance_prompt">Bir örnek seçin</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_title">Kilit ekranı video küçük resmini etkinleştir</string>
|
||||
<string name="enable_lock_screen_video_thumbnail_summary">Arka plan oynatıcıyı kullanırken kilit ekranında bir video küçük resmi görüntülenecektir</string>
|
||||
<string name="clear_download_history">İndirme geçmişini temizle</string>
|
||||
<string name="delete_downloaded_files">İndirilen dosyaları sil</string>
|
||||
<string name="deleted_downloads">%1$s indirme silindi</string>
|
||||
</resources>
|
|
@ -8,7 +8,7 @@
|
|||
<string name="share">بانٹیں</string>
|
||||
<string name="download">ڈاؤن لوڈکریں</string>
|
||||
<string name="search">تلاش کریں</string>
|
||||
<string name="did_you_mean">کیا آپ کا مطلب تھا: %1$s \?</string>
|
||||
<string name="did_you_mean">کیا آپ کا مطلب تھا: s$1%\?</string>
|
||||
<string name="open_in_browser">انٹرنیٹ میں کھولیں</string>
|
||||
<string name="settings">ترتیبات</string>
|
||||
<string name="no_player_found">کوئیstream پلیئر نہیں ملا.کیا آپ VLC انسٹال کرنا چاہتے ہیں؟</string>
|
||||
|
@ -159,7 +159,7 @@
|
|||
<string name="invalid_source">ایسی کوئی فائل / مواد کا ذریعہ نہیں</string>
|
||||
<string name="invalid_file">فائل موجود نہیں ہے اور نہ ہی اسے پڑھنے یا لکھنے کی اجازت ہے</string>
|
||||
<string name="file_name_empty_error">فائل کا نام ضروری ہے</string>
|
||||
<string name="error_occurred_detail">ایک خامی پیش آگئی:٪ 1 $ s</string>
|
||||
<string name="error_occurred_detail">ایک خامی پیش آگئی: s$1%</string>
|
||||
<string name="no_streams_available_download">کوئی اسٹریمز ڈاؤن لوڈ کرنے کے لئے دستیاب نہیں</string>
|
||||
<string name="sorry_string">معذرت ، ایسا نہیں ہونا چاہئے تھا۔</string>
|
||||
<string name="error_report_button_text">ای میل کے ذریعے غلطی کی اطلاع دیں</string>
|
||||
|
@ -182,8 +182,8 @@
|
|||
<string name="search_no_results">کوئی نتیجہ نہیں</string>
|
||||
<string name="empty_subscription_feed_subtitle">یہاں کچھ نہیں مگر اداسی کے</string>
|
||||
<string name="detail_drag_description">دوبارہ ترتیب دینے کیلئے کھینچں</string>
|
||||
<string name="err_dir_create">ڈاؤن لوڈ ڈائریکٹری \'٪ 1 $ s\' تشکیل نہیں دے سکتے</string>
|
||||
<string name="info_dir_created">ڈاؤن لوڈ ڈائریکٹری \'٪ 1 $ s\' بن گئی</string>
|
||||
<string name="err_dir_create">ڈاؤن لوڈ ڈائریکٹری \'s$1%\' تشکیل نہیں دے سکتے</string>
|
||||
<string name="info_dir_created">ڈاؤن لوڈ ڈائریکٹری \'s$1%\' بن گئی</string>
|
||||
<string name="video">ویڈیو</string>
|
||||
<string name="audio">آڈیو</string>
|
||||
<string name="retry">دوبارہ کوشش کریں</string>
|
||||
|
@ -193,18 +193,18 @@
|
|||
<string name="short_billion">بی</string>
|
||||
<string name="no_subscribers">کوئی صارفین نہیں</string>
|
||||
<plurals name="subscribers">
|
||||
<item quantity="one">% s صارف</item>
|
||||
<item quantity="other">% s صارفین</item>
|
||||
<item quantity="one">s% صارف</item>
|
||||
<item quantity="other">s% صارفین</item>
|
||||
</plurals>
|
||||
<string name="no_views">کوئی مناظر نہیں</string>
|
||||
<plurals name="views">
|
||||
<item quantity="one">% s منظر</item>
|
||||
<item quantity="other">% s مناظر</item>
|
||||
<item quantity="one">s% منظر</item>
|
||||
<item quantity="other">s% مناظر</item>
|
||||
</plurals>
|
||||
<string name="no_videos">ویڈیوز دستیاب نہیں</string>
|
||||
<plurals name="videos">
|
||||
<item quantity="one">ویڈیوز</item>
|
||||
<item quantity="other"></item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<string name="start">شروع کریں</string>
|
||||
<string name="pause">توقف</string>
|
||||
|
@ -306,7 +306,7 @@
|
|||
<string name="drawer_close">دراز بند کریں</string>
|
||||
<string name="drawer_header_action_paceholder_text">یہاں جلد ہی کچھ نظر آئے گا D D</string>
|
||||
<string name="preferred_open_action_settings_title">ترجیح \' کھلی \' عمل</string>
|
||||
<string name="preferred_open_action_settings_summary">مواد کھولنے پر ڈیفالٹ کارروائی -٪ s</string>
|
||||
<string name="preferred_open_action_settings_summary">مواد کھولنے پر ڈیفالٹ کارروائی — s%</string>
|
||||
<string name="video_player">ویڈیو پلیئر</string>
|
||||
<string name="background_player">پس منظر پلیئر</string>
|
||||
<string name="popup_player">پوپ اپ پلیئر</string>
|
||||
|
@ -345,16 +345,16 @@
|
|||
<string name="previous_export">پچھلی برآمد</string>
|
||||
<string name="subscriptions_import_unsuccessful">سبسکرپشنز کو درآمد نہیں کیا جاسکا</string>
|
||||
<string name="subscriptions_export_unsuccessful">رکنیت برآمد نہیں کر سکا</string>
|
||||
<string name="import_youtube_instructions">برآمد فائل کو ڈاؤن لوڈ کرکے YouTube کی رکنیت کو درآمد کریں:
|
||||
\n
|
||||
\n1. اس یو آر ایل پر جائیں:٪ 1 $ s
|
||||
\n2. جب پوچھا جائے تو لاگ ان کریں
|
||||
<string name="import_youtube_instructions">برآمد فائل کو ڈاؤن لوڈ کرکے YouTube کی رکنیت کو درآمد کریں:
|
||||
\n
|
||||
\n1. اس یو آر ایل پر جائیں:s$1%
|
||||
\n2. جب پوچھا جائے تو لاگ ان کریں
|
||||
\nA. ڈاؤن لوڈ شروع ہونا چاہئے (یہ برآمد فائل ہے)</string>
|
||||
<string name="import_soundcloud_instructions">URL یا آپ کی ID ٹائپ کرکے ایک SoundCloud پروفائل درآمد کریں:
|
||||
\n
|
||||
\n1. ویب براؤزر میں \"ڈیسک ٹاپ موڈ\" کو فعال کریں (سائٹ موبائل آلات کے لئے دستیاب نہیں ہے)
|
||||
\n2. اس URL پر جائیں: %1 $ s
|
||||
\n3. پوچھا گیا میں لاگ ان کریں
|
||||
<string name="import_soundcloud_instructions">URL یا آپ کی ID ٹائپ کرکے ایک SoundCloud پروفائل درآمد کریں:
|
||||
\n
|
||||
\n1. ویب براؤزر میں \"ڈیسک ٹاپ موڈ\" کو فعال کریں (سائٹ موبائل آلات کے لئے دستیاب نہیں ہے)
|
||||
\n2. اس URL پر جائیں: s$1%
|
||||
\n3. پوچھا گیا میں لاگ ان کریں
|
||||
\n4. پروفائل یو آر ایل کاپی کریں جو آپ کو ہدایت کی گئی تھی.</string>
|
||||
<string name="import_soundcloud_instructions_hint">yourID، soundcloud.com/yourid</string>
|
||||
<string name="import_network_expensive_warning">یاد رکھیں کہ یہ آپریشن نیٹ ورک مہنگا ہوسکتا ہے۔
|
||||
|
@ -388,7 +388,7 @@
|
|||
<string name="limit_data_usage_none_description">کوئی حد نہیں</string>
|
||||
<string name="limit_mobile_data_usage_title">موبائل ڈیٹا کا استعمال کرتے وقت ریذولوشن کو محدود کریں</string>
|
||||
<string name="minimize_on_exit_title">ایپ سوئچ کو کم سے کم کریں</string>
|
||||
<string name="minimize_on_exit_summary">اہم ویڈیو پلیئر سے دوسرے ایپ میں سوئچنگ کرتے وقت کارروائی-% s</string>
|
||||
<string name="minimize_on_exit_summary">اہم ویڈیو پلیئر سے دوسرے ایپ میں سوئچنگ کرتے وقت کارروائی — %s</string>
|
||||
<string name="minimize_on_exit_none_description">کوئی نہیں</string>
|
||||
<string name="minimize_on_exit_background_description">پس منظری پلیر میں کم کریں</string>
|
||||
<string name="minimize_on_exit_popup_description">پاپ اپ پلیر میں کم کریں</string>
|
||||
|
@ -437,7 +437,7 @@
|
|||
<string name="permission_denied">سسٹم نےکارروائی سے انکار کیا گیا</string>
|
||||
<string name="download_failed">ڈاؤن لوڈ ناکام</string>
|
||||
<string name="download_finished">ڈاؤن لوڈ تکمیل</string>
|
||||
<string name="download_finished_more">٪ s ڈاؤن لوڈ مکمل ہوگئے</string>
|
||||
<string name="download_finished_more">s% ڈاؤن لوڈ مکمل ہوگئے</string>
|
||||
<string name="generate_unique_name">منفرد نام بنائیں</string>
|
||||
<string name="overwrite">برتحریر</string>
|
||||
<string name="download_already_running">اس نام کے ساتھ ایک ڈاؤن لوڈ جاری ہے</string>
|
||||
|
@ -466,7 +466,7 @@
|
|||
<string name="autoplay_title">آٹوپلے</string>
|
||||
<plurals name="comments">
|
||||
<item quantity="one">تبصرے</item>
|
||||
<item quantity="other"></item>
|
||||
<item quantity="other"/>
|
||||
</plurals>
|
||||
<string name="no_comments">کوئی تبصرہ نہیں</string>
|
||||
<string name="error_unable_to_load_comments">تبصرے لوڈ نہیں ہوسکے</string>
|
||||
|
|
19
fastlane/metadata/android/en-US/changelogs/810.txt
Normal file
19
fastlane/metadata/android/en-US/changelogs/810.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
New
|
||||
• Show video thumbnail on the lock screen when playing in the background
|
||||
|
||||
Improved
|
||||
• Add local playlist to queue when long pressing on background / popup button
|
||||
• Make main page tabs scrollable and hide when there is only a single tab
|
||||
• Limit amount of notification thumbnail updates in background player
|
||||
• Add dummy thumbnail for empty local playlists
|
||||
• Use *.opus file extension instead of *.webm and show "opus" in format label instead of "WebM Opus" in the download dropdown
|
||||
• Add button to delete downloaded files or download history in "Downloads"
|
||||
• [YouTube] Add support to /c/shortened_url channel links
|
||||
|
||||
Fixed
|
||||
• Fixed multiple issues when sharing a video to NewPipe and downloading its streams directly
|
||||
• Fixed player access out of its creation thread
|
||||
• Fixed search result paging
|
||||
• [YouTube] Fixed switching on null causing NPE
|
||||
• [YouTube] Fixed viewing comments when opening an invidio.us url
|
||||
• [SoundCloud] Updated client_id
|
1
fastlane/metadata/android/en-US/changelogs/820.txt
Normal file
1
fastlane/metadata/android/en-US/changelogs/820.txt
Normal file
|
@ -0,0 +1 @@
|
|||
Fixed decrypt function name regex making YouTube unusable.
|
Loading…
Reference in a new issue