summaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java155
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java73
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java58
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ssl/CompositeX509TrustManager.java60
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ssl/NoV1SslSocketFactory.java100
-rw-r--r--core/src/main/res/values-cs/strings.xml95
-rw-r--r--core/src/main/res/values-eu/strings.xml5
-rw-r--r--core/src/main/res/values-fa/strings.xml4
-rw-r--r--core/src/main/res/values-pl/strings.xml6
-rw-r--r--core/src/main/res/values-pt-rBR/strings.xml31
-rw-r--r--core/src/main/res/values-zh-rTW/strings.xml28
12 files changed, 469 insertions, 148 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
index 889018c45..a01b3cb52 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java
@@ -1,39 +1,16 @@
package de.danoeh.antennapod.core.service.download;
import android.os.Build;
-import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
-
-import de.danoeh.antennapod.core.service.BasicAuthorizationInterceptor;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.CookieManager;
-import java.net.CookiePolicy;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.security.GeneralSecurityException;
-import java.security.KeyStore;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
+import androidx.annotation.NonNull;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.BasicAuthorizationInterceptor;
import de.danoeh.antennapod.core.service.UserAgentInterceptor;
+import de.danoeh.antennapod.core.ssl.BackportTrustManager;
+import de.danoeh.antennapod.core.ssl.NoV1SslSocketFactory;
import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.Flavors;
import okhttp3.Cache;
import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
@@ -45,6 +22,19 @@ import okhttp3.Request;
import okhttp3.Response;
import okhttp3.internal.http.StatusLine;
+import javax.net.ssl.X509TrustManager;
+import java.io.File;
+import java.net.CookieManager;
+import java.net.CookiePolicy;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
/**
* Provides access to a HttpClient singleton.
*/
@@ -149,13 +139,20 @@ public class AntennapodHttpClient {
});
}
}
- if (Build.VERSION.SDK_INT < 21) {
- builder.sslSocketFactory(new CustomSslSocketFactory(), trustManager());
+
+ if (Flavors.FLAVOR == Flavors.FREE) {
+ // The Free flavor bundles a modern conscrypt (security provider), so CustomSslSocketFactory
+ // is only used to make sure that modern protocols (TLSv1.3 and TLSv1.2) are enabled and
+ // that old, deprecated, protocols (like SSLv3, TLSv1.0 and TLSv1.1) are disabled.
+ X509TrustManager trustManager = BackportTrustManager.create();
+ builder.sslSocketFactory(new NoV1SslSocketFactory(trustManager), trustManager);
+ } else if (Build.VERSION.SDK_INT < 21) {
+ X509TrustManager trustManager = BackportTrustManager.create();
+ builder.sslSocketFactory(new NoV1SslSocketFactory(trustManager), trustManager);
// workaround for Android 4.x for certain web sites.
// see: https://github.com/square/okhttp/issues/4053#issuecomment-402579554
- List<CipherSuite> cipherSuites = new ArrayList<>(
- ConnectionSpec.MODERN_TLS.cipherSuites());
+ List<CipherSuite> cipherSuites = new ArrayList<>(ConnectionSpec.MODERN_TLS.cipherSuites());
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
cipherSuites.add(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
@@ -168,101 +165,7 @@ public class AntennapodHttpClient {
return builder;
}
- /**
- * Closes expired connections. This method should be called by the using class once has finished its work with
- * the HTTP client.
- */
- public static synchronized void cleanup() {
- if (httpClient != null) {
- // does nothing at the moment
- }
- }
-
- private static X509TrustManager trustManager() {
- try {
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init((KeyStore) null);
- TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
- if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
- throw new IllegalStateException("Unexpected default trust managers:"
- + Arrays.toString(trustManagers));
- }
- return (X509TrustManager) trustManagers[0];
- } catch (Exception e) {
- Log.e(TAG, Log.getStackTraceString(e));
- return null;
- }
- }
-
public static void setCacheDirectory(File cacheDirectory) {
AntennapodHttpClient.cacheDirectory = cacheDirectory;
}
-
- private static class CustomSslSocketFactory extends SSLSocketFactory {
-
- private SSLSocketFactory factory;
-
- public CustomSslSocketFactory() {
- try {
- SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
- sslContext.init(null, null, null);
- factory= sslContext.getSocketFactory();
- } catch(GeneralSecurityException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public String[] getDefaultCipherSuites() {
- return factory.getDefaultCipherSuites();
- }
-
- @Override
- public String[] getSupportedCipherSuites() {
- return factory.getSupportedCipherSuites();
- }
-
- public Socket createSocket() throws IOException {
- SSLSocket result = (SSLSocket) factory.createSocket();
- configureSocket(result);
- return result;
- }
-
- public Socket createSocket(String var1, int var2) throws IOException {
- SSLSocket result = (SSLSocket) factory.createSocket(var1, var2);
- configureSocket(result);
- return result;
- }
-
- public Socket createSocket(Socket var1, String var2, int var3, boolean var4) throws IOException {
- SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4);
- configureSocket(result);
- return result;
- }
-
- public Socket createSocket(InetAddress var1, int var2) throws IOException {
- SSLSocket result = (SSLSocket) factory.createSocket(var1, var2);
- configureSocket(result);
- return result;
- }
-
- public Socket createSocket(String var1, int var2, InetAddress var3, int var4) throws IOException {
- SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4);
- configureSocket(result);
- return result;
- }
-
- public Socket createSocket(InetAddress var1, int var2, InetAddress var3, int var4) throws IOException {
- SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4);
- configureSocket(result);
- return result;
- }
-
- private void configureSocket(SSLSocket s) {
- s.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" } );
- }
-
- }
-
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
index 61608992b..65b7ed7d1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
@@ -71,6 +71,7 @@ public class HttpDownloader extends Downloader {
// set header explicitly so that okhttp doesn't do transparent gzip
Log.d(TAG, "addHeader(\"Accept-Encoding\", \"identity\")");
httpReq.addHeader("Accept-Encoding", "identity");
+ httpReq.cacheControl(new CacheControl.Builder().noCache().build()); // noStore breaks CDNs
}
if (!TextUtils.isEmpty(request.getLastModified())) {
@@ -259,7 +260,6 @@ public class HttpDownloader extends Downloader {
onFail(DownloadError.ERROR_CONNECTION_ERROR, request.getSource());
} finally {
IOUtils.closeQuietly(out);
- AntennapodHttpClient.cleanup();
IOUtils.closeQuietly(responseBody);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java
new file mode 100644
index 000000000..720d6a9d9
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportCaCerts.java
@@ -0,0 +1,73 @@
+package de.danoeh.antennapod.core.ssl;
+
+public class BackportCaCerts {
+ public static final String SECTIGO_USER_TRUST = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB\n"
+ + "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n"
+ + "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n"
+ + "BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw\n"
+ + "MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV\n"
+ + "BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU\n"
+ + "aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy\n"
+ + "dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n"
+ + "AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B\n"
+ + "3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY\n"
+ + "tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/\n"
+ + "Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2\n"
+ + "VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT\n"
+ + "79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6\n"
+ + "c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT\n"
+ + "Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l\n"
+ + "c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee\n"
+ + "UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE\n"
+ + "Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd\n"
+ + "BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G\n"
+ + "A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF\n"
+ + "Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO\n"
+ + "VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3\n"
+ + "ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs\n"
+ + "8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR\n"
+ + "iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze\n"
+ + "Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ\n"
+ + "XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/\n"
+ + "qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB\n"
+ + "VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB\n"
+ + "L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG\n"
+ + "jjxDah2nGN59PRbxYvnKkKj9\n"
+ + "-----END CERTIFICATE-----\n";
+
+ public static final String COMODO = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB\n"
+ + "hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n"
+ + "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV\n"
+ + "BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5\n"
+ + "MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT\n"
+ + "EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR\n"
+ + "Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh\n"
+ + "dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR\n"
+ + "6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X\n"
+ + "pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC\n"
+ + "9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV\n"
+ + "/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf\n"
+ + "Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z\n"
+ + "+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w\n"
+ + "qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah\n"
+ + "SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC\n"
+ + "u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf\n"
+ + "Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq\n"
+ + "crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E\n"
+ + "FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB\n"
+ + "/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl\n"
+ + "wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM\n"
+ + "4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV\n"
+ + "2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna\n"
+ + "FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ\n"
+ + "CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK\n"
+ + "boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke\n"
+ + "jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL\n"
+ + "S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb\n"
+ + "QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl\n"
+ + "0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB\n"
+ + "NVOFBkpdn627G190\n"
+ + "-----END CERTIFICATE-----";
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java
new file mode 100644
index 000000000..b8fe950b2
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/ssl/BackportTrustManager.java
@@ -0,0 +1,58 @@
+package de.danoeh.antennapod.core.ssl;
+
+import android.util.Log;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import java.io.ByteArrayInputStream;
+import java.nio.charset.Charset;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SSL trust manager that allows old Android systems to use modern certificates.
+ */
+public class BackportTrustManager {
+ private static final String TAG = "BackportTrustManager";
+
+ private static X509TrustManager getSystemTrustManager(KeyStore keystore) {
+ TrustManagerFactory factory;
+ try {
+ factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ factory.init(keystore);
+ for (TrustManager manager : factory.getTrustManagers()) {
+ if (manager instanceof X509TrustManager) {
+ return (X509TrustManager) manager;
+ }
+ }
+ } catch (NoSuchAlgorithmException | KeyStoreException e) {
+ e.printStackTrace();
+ }
+ throw new IllegalStateException("Unexpected default trust managers");
+ }
+
+ public static X509TrustManager create() {
+ try {
+ KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keystore.load(null); // Clear
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ keystore.setCertificateEntry("BACKPORT_COMODO_ROOT_CA", cf.generateCertificate(
+ new ByteArrayInputStream(BackportCaCerts.COMODO.getBytes(Charset.forName("UTF-8")))));
+ keystore.setCertificateEntry("SECTIGO_USER_TRUST_CA", cf.generateCertificate(
+ new ByteArrayInputStream(BackportCaCerts.SECTIGO_USER_TRUST.getBytes(Charset.forName("UTF-8")))));
+
+ List<X509TrustManager> managers = new ArrayList<>();
+ managers.add(getSystemTrustManager(keystore));
+ managers.add(getSystemTrustManager(null));
+ return new CompositeX509TrustManager(managers);
+ } catch (Exception e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ return null;
+ }
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/CompositeX509TrustManager.java b/core/src/main/java/de/danoeh/antennapod/core/ssl/CompositeX509TrustManager.java
new file mode 100644
index 000000000..7af96a492
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/ssl/CompositeX509TrustManager.java
@@ -0,0 +1,60 @@
+package de.danoeh.antennapod.core.ssl;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Represents an ordered list of {@link X509TrustManager}s with additive trust. If any one of the composed managers
+ * trusts a certificate chain, then it is trusted by the composite manager.
+ * Based on https://stackoverflow.com/a/16229909
+ */
+public class CompositeX509TrustManager implements X509TrustManager {
+ private final List<X509TrustManager> trustManagers;
+
+ public CompositeX509TrustManager(List<X509TrustManager> trustManagers) {
+ this.trustManagers = trustManagers;
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ CertificateException reason = null;
+ for (X509TrustManager trustManager : trustManagers) {
+ try {
+ trustManager.checkClientTrusted(chain, authType);
+ return; // someone trusts them. success!
+ } catch (CertificateException e) {
+ // maybe someone else will trust them
+ reason = e;
+ }
+ }
+ throw reason;
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ CertificateException reason = null;
+ for (X509TrustManager trustManager : trustManagers) {
+ try {
+ trustManager.checkServerTrusted(chain, authType);
+ return; // someone trusts them. success!
+ } catch (CertificateException e) {
+ // maybe someone else will trust them
+ reason = e;
+ }
+ }
+ throw reason;
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ List<X509Certificate> certificates = new ArrayList<>();
+ for (X509TrustManager trustManager : trustManagers) {
+ certificates.addAll(Arrays.asList(trustManager.getAcceptedIssuers()));
+ }
+ return certificates.toArray(new X509Certificate[0]);
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ssl/NoV1SslSocketFactory.java b/core/src/main/java/de/danoeh/antennapod/core/ssl/NoV1SslSocketFactory.java
new file mode 100644
index 000000000..96a42f22d
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/ssl/NoV1SslSocketFactory.java
@@ -0,0 +1,100 @@
+package de.danoeh.antennapod.core.ssl;
+
+import de.danoeh.antennapod.core.util.Flavors;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+
+/**
+ * SSLSocketFactory that does not use TLS 1.0
+ * This fixes issues with old Android versions that abort if the server does not know TLS 1.0
+ */
+public class NoV1SslSocketFactory extends SSLSocketFactory {
+ private SSLSocketFactory factory;
+
+ public NoV1SslSocketFactory(TrustManager trustManager) {
+ try {
+ SSLContext sslContext;
+
+ if (Flavors.FLAVOR == Flavors.FREE) {
+ // Free flavor (bundles modern conscrypt): support for TLSv1.3 is guaranteed.
+ sslContext = SSLContext.getInstance("TLSv1.3");
+ } else {
+ // Play flavor (security provider can vary): only TLSv1.2 is guaranteed.
+ sslContext = SSLContext.getInstance("TLSv1.2");
+ }
+
+ sslContext.init(null, new TrustManager[] {trustManager}, null);
+ factory = sslContext.getSocketFactory();
+ } catch (GeneralSecurityException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return factory.getDefaultCipherSuites();
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return factory.getSupportedCipherSuites();
+ }
+
+ public Socket createSocket() throws IOException {
+ SSLSocket result = (SSLSocket) factory.createSocket();
+ configureSocket(result);
+ return result;
+ }
+
+ public Socket createSocket(String var1, int var2) throws IOException {
+ SSLSocket result = (SSLSocket) factory.createSocket(var1, var2);
+ configureSocket(result);
+ return result;
+ }
+
+ public Socket createSocket(Socket var1, String var2, int var3, boolean var4) throws IOException {
+ SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4);
+ configureSocket(result);
+ return result;
+ }
+
+ public Socket createSocket(InetAddress var1, int var2) throws IOException {
+ SSLSocket result = (SSLSocket) factory.createSocket(var1, var2);
+ configureSocket(result);
+ return result;
+ }
+
+ public Socket createSocket(String var1, int var2, InetAddress var3, int var4) throws IOException {
+ SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4);
+ configureSocket(result);
+ return result;
+ }
+
+ public Socket createSocket(InetAddress var1, int var2, InetAddress var3, int var4) throws IOException {
+ SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4);
+ configureSocket(result);
+ return result;
+ }
+
+ private void configureSocket(SSLSocket s) {
+ if (Flavors.FLAVOR == Flavors.FREE) {
+ // Free flavor (bundles modern conscrypt): TLSv1.3 and modern cipher suites are
+ // guaranteed. Protocols older than TLSv1.2 are now deprecated and can be disabled.
+ s.setEnabledProtocols(new String[] { "TLSv1.3", "TLSv1.2" });
+ } else {
+ // Play flavor (security provider can vary): only TLSv1.2 is guaranteed, supported
+ // cipher suites may vary. Old protocols might be necessary to keep things working.
+
+ // TLS 1.0 is enabled by default on some old systems, which causes connection errors.
+ // This disables that.
+ s.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" });
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/main/res/values-cs/strings.xml b/core/src/main/res/values-cs/strings.xml
index 2aa11889d..ec6f20941 100644
--- a/core/src/main/res/values-cs/strings.xml
+++ b/core/src/main/res/values-cs/strings.xml
@@ -40,7 +40,7 @@
<string name="drawer_open">Otevřít menu</string>
<string name="drawer_close">Zavřít menu</string>
<string name="drawer_preferences">Nastavení panelu</string>
- <string name="drawer_feed_order_unplayed_episodes">Řadit dle počtu</string>
+ <string name="drawer_feed_order_unplayed_episodes">Řadit dle čítače</string>
<string name="drawer_feed_order_alphabetical">Řadit abecedně</string>
<string name="drawer_feed_order_last_update">Řadit dle data zveřejnění</string>
<string name="drawer_feed_order_most_played">Řadit podle počtu poslechnutých epizod</string>
@@ -110,12 +110,21 @@
<item quantity="many">%d dnů po dokončení</item>
<item quantity="other">%d dnů po dokončení</item>
</plurals>
+ <plurals name="num_selected_label">
+ <item quantity="one">%d vybrána</item>
+ <item quantity="few">%d vybrány</item>
+ <item quantity="many">%d vybráno</item>
+ <item quantity="other">%d vybráno</item>
+ </plurals>
<string name="loading_more">Načítají se další…</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Označit vše jako poslechnuté</string>
<string name="mark_all_read_msg">Všechny epizody označeny jako poslechnuté</string>
<string name="mark_all_read_confirmation_msg">Potvrďte prosím, že chcete označit všechny vybrané epizody jako poslechnuté.</string>
<string name="mark_all_read_feed_confirmation_msg">Potvrďte prosím, že chcete označit všechny epizody tohoto podcastu jako poslechnuté.</string>
+ <string name="remove_all_new_flags_label">Odstranit příznak „nová“ ze všech epizod</string>
+ <string name="removed_all_new_flags_msg">Příznak „nová“ odstraněn ze všech epizod</string>
+ <string name="remove_all_new_flags_confirmation_msg">Potvrďte prosím, že chcete odstranit příznak „nová“ ze všech epizod.</string>
<string name="show_info_label">Informace o zdroji</string>
<string name="show_feed_settings_label">Zobrazit nastavení podcastu</string>
<string name="feed_info_label">Informace o podcastu</string>
@@ -132,6 +141,7 @@
<string name="share_item_url_with_position_label">Sdílet URL souboru s časovou značkou</string>
<string name="feed_delete_confirmation_msg">Potvrďte prosím, že chcete smazat podcast „%1$s“ a VŠECHNY jeho epizody (včetně stažených epizod).</string>
<string name="feed_remover_msg">Odstraňování podcastu</string>
+ <string name="load_complete_feed">Aktualizovat celý podcast</string>
<string name="multi_select">Výběr více položek</string>
<string name="select_all_above">Vybrat všechny výše</string>
<string name="select_all_below">Vybrat všechny níže</string>
@@ -168,10 +178,13 @@
<item quantity="many">%d epizod staženo.</item>
<item quantity="other">%d epizod staženo.</item>
</plurals>
+ <string name="remove_new_flag_label">Odstranit příznak „nová“</string>
+ <string name="removed_new_flag_label">Příznak „nová“ odstraněn</string>
<string name="mark_read_label">Označit jako poslechnuté</string>
<string name="marked_as_read_label">Označeno jako poslechnuté</string>
<string name="mark_read_no_media_label">Označit jako poslechnuté</string>
<string name="marked_as_read_no_media_label">Označeno jako poslechnuté</string>
+ <string name="play_this_to_seek_position">Pro přeskočení na pozice musíte epizodu přehrát</string>
<plurals name="marked_read_batch_label">
<item quantity="one">%d epizoda označena jako přehraná</item>
<item quantity="few">%d epizody označeny jako přehrané</item>
@@ -180,9 +193,27 @@
</plurals>
<string name="mark_unread_label">Označit jako neposlechnuté</string>
<string name="mark_unread_label_no_media">Označit jako nepřečtené</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d epizoda označena jako neposlechnutá</item>
+ <item quantity="few">%d epizody označeny jako neposlechnuté</item>
+ <item quantity="many">%d epizod označeno jako neposlechnuté</item>
+ <item quantity="other">%d epizod označeno jako neposlechnuté</item>
+ </plurals>
<string name="add_to_queue_label">Přidat do fronty</string>
<string name="added_to_queue_label">Přidáno do fronty</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">%d epizoda přidána do fronty</item>
+ <item quantity="few">%d epizody přidány do fronty</item>
+ <item quantity="many">%d epizod přidáno do fronty</item>
+ <item quantity="other">%d epizod přidáno do fronty</item>
+ </plurals>
<string name="remove_from_queue_label">Odebrat z fronty</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">%d epizoda odebrána z fronty</item>
+ <item quantity="few">%d epizody odebrány z fronty</item>
+ <item quantity="many">%d epizod odebráno z fronty</item>
+ <item quantity="other">%d epizod odebráno z fronty</item>
+ </plurals>
<string name="add_to_favorite_label">Přidat k oblíbeným</string>
<string name="added_to_favorites">Přidáno k oblíbeným</string>
<string name="remove_from_favorite_label">Odebrat z obíbených</string>
@@ -233,6 +264,7 @@
<string name="download_type_feed">Kanál</string>
<string name="download_type_media">Soubor</string>
<string name="download_request_error_dialog_message_prefix">Nastala chyba při pokusu o stažení souboru:\u0020</string>
+ <string name="null_value_podcast_error">Nebyl poskytnut žádný podcast, co by mohl být zobrazen.</string>
<string name="authentication_notification_title">Vyžadováno ověření</string>
<string name="authentication_notification_msg">Zdroj který jste vybrali vyžaduje zadání uživatelského jména a hesla</string>
<string name="confirm_mobile_download_dialog_title">Potvrdit mobilní stahování</string>
@@ -285,13 +317,17 @@
<!--Variable Speed-->
<string name="download_plugin_label">Stáhnout modul</string>
<string name="no_playback_plugin_title">Modul není nainstalován</string>
+ <string name="no_playback_plugin_or_sonic_msg">Pro správnou funkci proměnlivé rychlosti přehrávání je doporučeno povolit vestavěný přehrávač Sonic.</string>
<string name="set_playback_speed_label">Rychlosti přehrávání</string>
<string name="enable_sonic">Povolit Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">Žádné epizody ve frontě</string>
+ <string name="no_items_label">Přidejte epizodu stažením nebo dlouhým dotykem a volbou „Přidat do fronty“.</string>
<string name="no_shownotes_label">Tato epizoda neobsahuje žádné poznámky.</string>
<string name="no_run_downloads_head_label">Neběží žádná stahování</string>
+ <string name="no_run_downloads_label">Můžete stáhnout epizody tohoto podcastu z obrazovky s jeho detaily.</string>
<string name="no_comp_downloads_head_label">Žádné stažené epizody</string>
+ <string name="no_comp_downloads_label">Můžete stáhnout epizody tohoto podcastu z obrazovky s jeho detaily.</string>
<string name="no_log_downloads_head_label">Žádné záznamy o stahování</string>
<string name="no_log_downloads_label">Až proběhnou nějaká stahování, tak se záznamy o nich objeví zde.</string>
<string name="no_history_head_label">Žádná historie</string>
@@ -304,6 +340,7 @@
<string name="no_fav_episodes_label">Epizody si můžete přidat mezi oblíbené dlouhým dotykem.</string>
<string name="no_chapters_head_label">Žádné kapitoly</string>
<string name="no_chapters_label">Tato epizoda nemá žádné kapitoly.</string>
+ <string name="no_subscriptions_head_label">Žádené sbírky</string>
<string name="no_subscriptions_label">Pro přidání podcastu do sbírky se dotkněte ikonky plus níže.</string>
<!--Preferences-->
<string name="storage_pref">Úložiště</string>
@@ -317,6 +354,7 @@
<string name="import_export_pref">Importovat/Exportovat</string>
<string name="import_export_search_keywords">zálohovat, obnovit</string>
<string name="appearance">Vzhled</string>
+ <string name="external_elements">Externí elementy</string>
<string name="interruptions">Přerušení</string>
<string name="playback_control">Ovládání přehrávání</string>
<string name="preference_search_hint">Vyhledávání…</string>
@@ -328,6 +366,8 @@
<string name="pref_pauseOnDisconnect_sum">Při odpojení sluchátek nebo bluetooth připojení pozastavit přehrávání.</string>
<string name="pref_unpauseOnHeadsetReconnect_sum">Pokračovat v přehrávání po připojení sluchátek</string>
<string name="pref_unpauseOnBluetoothReconnect_sum">Pokračovat v přehrávání po připojení bluetooth</string>
+ <string name="pref_hardwareForwardButtonSkips_title">Tlačítko rychle vpřed přeskakuje</string>
+ <string name="pref_hardwareForwardButtonSkips_sum">Stisk tlačítka rychle vpřed (FF) na připojeném zařízení Bluetooth přeskočí na další epizodu místo rychlého přetočení vpřed.</string>
<string name="pref_hardwarePreviousButtonRestarts_title">Tlačítko zpět restartuje</string>
<string name="pref_hardwarePreviousButtonRestarts_sum">Po stlačení hardwarového tlačítka pro posun zpět místo přetočení vpřed restartovat přehrávání aktuální epizody</string>
<string name="pref_followQueue_sum">Po přehrání položky z fronty přejít automaticky na další</string>
@@ -337,10 +377,14 @@
<string name="pref_smart_mark_as_played_title">Chytré označování jako poslechnuté</string>
<string name="pref_skip_keeps_episodes_sum">Neodstraňovat epizody při jejich přeskočení</string>
<string name="pref_skip_keeps_episodes_title">Nemazat přeskočené epizody</string>
+ <string name="pref_favorite_keeps_episodes_sum">Nemazat epizody, které jsou mezi oblíbenými.</string>
<string name="pref_favorite_keeps_episodes_title">Nemazat oblíbené epizody</string>
<string name="playback_pref">Přehrávání</string>
+ <string name="playback_pref_sum">Ovládání tlačítky sluchátek, přeskakování, fronta</string>
<string name="network_pref">Síť</string>
+ <string name="network_pref_sum">Četnost aktualizací, ovládání stahování, mobilní data</string>
<string name="pref_autoUpdateIntervallOrTime_title">Aktualizovat interval nebo čas v průběhu dne</string>
+ <string name="pref_autoUpdateIntervallOrTime_sum">Zvolte čas mezi aktualizacemi nebo čas v rámci dne, kdy proběhne automatická aktualizace podcastů</string>
<string name="pref_autoUpdateIntervallOrTime_message">Můžete nastavit <i>interval</i> jako třeba \"každé 2 hodiny\", nastavit specifický <i>čas v průběhu dne</i> jako \"7:00\" nebo úplně <i>vypnout</i> automatické aktualizace.\n\n<small>Mějte na paměti: Časy aktualizací nejsou přesné. Možná zaznamenáte krátká zpoždění.</small></string>
<string name="pref_autoUpdateIntervallOrTime_Disable">Vypnout</string>
<string name="pref_autoUpdateIntervallOrTime_Interval">Nastavit interval</string>
@@ -351,17 +395,24 @@
<string name="pref_pauseOnHeadsetDisconnect_title">Sluchátka odpojena</string>
<string name="pref_unpauseOnHeadsetReconnect_title">Sluchátka připojena</string>
<string name="pref_unpauseOnBluetoothReconnect_title">Bluetooth připojeno</string>
+ <string name="pref_stream_over_download_title">Upřednostnit streamování</string>
+ <string name="pref_stream_over_download_sum">Zobrazit tlačítko streamovat místo tlačítka stáhnout v seznamech.</string>
<string name="pref_mobileUpdate_title">Mobilní aktualizace</string>
+ <string name="pref_mobileUpdate_sum">Vyberte, co by mělo být povoleno přes mobilní data</string>
<string name="pref_mobileUpdate_refresh">Obnovit podcast</string>
+ <string name="pref_mobileUpdate_images">Obrázky podcastů/epizod</string>
<string name="pref_mobileUpdate_auto_download">Automatické stahování</string>
+ <string name="pref_mobileUpdate_episode_download">Stahování epizod</string>
<string name="pref_mobileUpdate_streaming">Streamování</string>
<string name="user_interface_label">Uživatelské rozhraní</string>
+ <string name="user_interface_sum">Vzhled, poradí ve sbírce, uzamčená obrazovka</string>
<string name="pref_set_theme_title">Vybrat motiv</string>
<string name="pref_nav_drawer_items_title">Změnit navigační panel</string>
<string name="pref_nav_drawer_items_sum">Upravit zobrazení položek v navigačním panelu.</string>
<string name="pref_nav_drawer_feed_order_title">Nastavit pořadí sbírek</string>
<string name="pref_nav_drawer_feed_order_sum">Upravit pořadí vašich sbírek</string>
- <string name="pref_nav_drawer_feed_counter_title">Nastavit počítadlo sbírek</string>
+ <string name="pref_nav_drawer_feed_counter_title">Nastavit čítač sbírek</string>
+ <string name="pref_nav_drawer_feed_counter_sum">Změnit informaci zobrazenou čítačem sbírek. Též ovlivňuje řazení, je-li nastaveno na „podle čítače“.</string>
<string name="pref_set_theme_sum">Změnit vzhled AntennaPod.</string>
<string name="pref_automatic_download_title">Automatické stahování</string>
<string name="pref_automatic_download_sum">Nastavení automatického stahování epizod.</string>
@@ -371,6 +422,9 @@
<string name="pref_automatic_download_on_battery_sum">Povolit automatické stahování i pokud není baterie nabíjena</string>
<string name="pref_parallel_downloads_title">Paralelní stahování</string>
<string name="pref_episode_cache_title">Historie epizod</string>
+ <string name="pref_episode_cache_summary">Celkový počet epizod stažených na zařízení. Automatické stahování se zastaví při dosažení této hodnoty.</string>
+ <string name="pref_episode_cover_title">Použít obrázek epizody</string>
+ <string name="pref_episode_cover_summary">Použít obrázek přímo z epizody, pokud je k dispozici. Není-li tato možnost zaškrtnuta, tak se vžy použije obrázek podcastu.</string>
<string name="pref_theme_title_use_system">Použít systémové téma</string>
<string name="pref_theme_title_light">Světlý</string>
<string name="pref_theme_title_dark">Tmavý</string>
@@ -387,9 +441,10 @@
<string name="pref_gpodnet_setlogin_information_sum">Změní přihlašovací údaje k vašemu gpodder.net účtu.</string>
<string name="pref_gpodnet_sync_changes_title">Synchronizovat ihned</string>
<string name="pref_gpodnet_sync_changes_sum">Synchronizovat odběr a změny stavu epizody s gpodder.net.</string>
+ <string name="pref_gpodnet_full_sync_title">Synchronizovat vše ihned</string>
<string name="pref_gpodnet_full_sync_sum">Synchronizovat všechny odběry a stav epizod s gpodder.net.</string>
<string name="pref_gpodnet_login_status"><![CDATA[Přihlášen jako <i>%1$s</i> z přístroje <i>%2$s</i>]]></string>
- <string name="pref_gpodnet_notifications_title">Zobrazovat upozornění na chyby synchronizace</string>
+ <string name="pref_gpodnet_notifications_title">Zobrazovat oznámení o chybách synchronizace</string>
<string name="pref_gpodnet_notifications_sum">Toto nastavení se netýká chyb přihlášení.</string>
<string name="pref_playback_speed_title">Rychlosti přehrávání</string>
<string name="pref_playback_speed_sum">Přizpůsobení rychlosti je dostupné pro přehrávání zvuku různými rychlostmi</string>
@@ -398,16 +453,20 @@
<string name="pref_feed_skip_sum">Přeskočit úvod a závěr.</string>
<string name="pref_feed_skip_ending">Přeskočit posledních</string>
<string name="pref_feed_skip_intro">Přeskočit prvních</string>
+ <string name="pref_feed_skip_ending_toast">Přeskočeno posledních %d sekund</string>
+ <string name="pref_feed_skip_intro_toast">Přeskočeno prvních %d sekund</string>
<string name="pref_playback_time_respects_speed_title">Upravit informace o médiu vzhledem k rychlosti přehrávání.</string>
<string name="pref_playback_time_respects_speed_sum">Zobrazené délka a pozice jsou upravené vzhledem k rychlosti přehrávání</string>
<string name="pref_fast_forward">Délka času posunu vpřed</string>
+ <string name="pref_fast_forward_sum">Upravit o kolik sekund se přeskočí dopředu při stisku tlačítka rychle vpřed (FF).</string>
<string name="pref_rewind">Délka času posunu zpět</string>
+ <string name="pref_rewind_sum">Upravit o kolik sekund se přeskočí zpět při stisku tlačítka přetočit zpět (RW).</string>
<string name="pref_gpodnet_sethostname_title">Nastavit hostname</string>
<string name="pref_gpodnet_sethostname_use_default_host">Použít přednastaveného hosta</string>
- <string name="pref_expandNotify_title">Vysoká priorita pro upozornění</string>
+ <string name="pref_expandNotify_title">Vysoká priorita pro oznámení</string>
<string name="pref_expandNotify_sum">Toto obvykle přidá tlačítka ovládání přehrávání do zpráv upozornění</string>
<string name="pref_persistNotify_title">Pevné ovládání přehrávání</string>
- <string name="pref_persistNotify_sum">Zachovat upozornění a ovládání na obrazovce uzamčení i při pozastaveném přehrávání.</string>
+ <string name="pref_persistNotify_sum">Zachovat oznámení a ovládání na obrazovce uzamčení i při pozastaveném přehrávání.</string>
<string name="pref_compact_notification_buttons_title">Nastavení tlačítek uzamčené obrazovky</string>
<string name="pref_compact_notification_buttons_sum">Změnit tlačítka ovládání na obrazovce uzamčení. Tlačítka přehrát/pozastavit jsou vždy zobrazena.</string>
<string name="pref_compact_notification_buttons_dialog_title">Vybrat maximálně %1$d položek</string>
@@ -416,7 +475,9 @@
<string name="pref_lockscreen_background_sum">Nastavit pozadí uzamčené obrazovky na obrázek aktuální epizody. Jako vedlejší efekt zobrazí toto nastavení obrázek i v aplikacích třetích stran. </string>
<string name="pref_showDownloadReport_title">Zobrazit report stahování</string>
<string name="pref_showDownloadReport_sum">Pokud selže stahování, vygenerovat report zobrazující detaily o chybě.</string>
- <string name="pref_expand_notify_unsupport_toast">Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění.</string>
+ <string name="pref_showAutoDownloadReport_title">Zobrazovat hlášení automatického stahování</string>
+ <string name="pref_showAutoDownloadReport_sum">Zobrazovat oznámení o automaticky stažených epizodách.</string>
+ <string name="pref_expand_notify_unsupport_toast">Verze Androidu nižší než 4.1 nepodporují rozšířená oznámení.</string>
<string name="pref_enqueue_location_title">Pozice přidávání do fronty</string>
<string name="pref_enqueue_location_sum">Přidávat epizody na: %1$s</string>
<string name="enqueue_location_back">konec</string>
@@ -425,7 +486,9 @@
<string name="pref_smart_mark_as_played_disabled">Vypnuto</string>
<string name="pref_image_cache_size_title">Velikost odkládací paměti obrázků</string>
<string name="pref_image_cache_size_sum">Velikost diskové paměti pro obrázky.</string>
+ <string name="visit_user_forum">Uživatelské fórum</string>
<string name="bug_report_title">Nahlásit chybu</string>
+ <string name="open_bug_tracker">Otevřít systém pro sledování a hlášení chyb (bug tracker)</string>
<string name="export_logs">Exportovat záznamy</string>
<string name="copy_to_clipboard">Zkopírovat do schránky</string>
<string name="copied_to_clipboard">Zkopírováno do schránky</string>
@@ -490,6 +553,7 @@
<string name="database">Databáze</string>
<string name="opml">OPML</string>
<string name="html">HTML</string>
+ <string name="html_export_summary">Ukažte své sbírky přátelům</string>
<string name="opml_export_summary">Přenést sbírky do jiné podcastové aplikace</string>
<string name="opml_import_summary">Importovat vaše sbírky z jiné podcastové aplikace</string>
<string name="database_export_summary">Přenést sbírky, poslechnuté epizody a frontu do aplikace AntennaPod na jiném zařízení</string>
@@ -582,6 +646,7 @@
<string name="choose_data_directory">Vybrat umístění dat</string>
<string name="choose_data_directory_message">Vyberte prosím váš výchozí datový adresář. AntennaPod vytvoří všechny potřebné podadresáře.</string>
<string name="choose_data_directory_permission_rationale">Ke změně datového adresáře je vyžadován přístup k externímu úložišti</string>
+ <string name="choose_data_directory_available_space">%1$s z %2$s zdarma</string>
<string name="create_folder_msg">Vytvořit adresář \"%1$s\"?</string>
<string name="create_folder_success">Nový adresář vytvořen</string>
<string name="create_folder_error_no_write_access">Nelze zapisovat do adresáře</string>
@@ -600,6 +665,9 @@
<string name="pref_restart_required">Pro aktivování změn nastavení bylo třeba restartovat aplikaci AntennaPod.</string>
<!--Online feed view-->
<string name="subscribe_label">Odebírat</string>
+ <string name="subscribing_label">Přidává se do sbírky…</string>
+ <string name="preview_episode">Spustit ukázku</string>
+ <string name="stop_preview">Zastavit ukázku</string>
<!--Content descriptions for image buttons-->
<string name="rewind_label">Posunout zpět</string>
<string name="fast_forward_label">Posunout vpřed</string>
@@ -613,6 +681,9 @@
<string name="is_favorite_label">Epizoda je označená jako oblíbená</string>
<string name="drag_handle_content_description">Tahem změnit pozici této položky</string>
<string name="load_next_page_label">Načíst další stranu</string>
+ <string name="switch_pages">Přehodit stránku</string>
+ <string name="position">Pozice: %1$s</string>
+ <string name="apply_action">Vykonat</string>
<!--Feed information screen-->
<string name="authentication_label">Ověření</string>
<string name="authentication_descr">Změnit uživatelské jméno a heslo pro tento podcast a jeho epizody.</string>
@@ -638,6 +709,7 @@
<string name="browse_gpoddernet_label">Prohledávat gpodder.net</string>
<string name="discover">Objevit</string>
<string name="discover_more">více »</string>
+ <string name="search_powered_by">Vyhledávání poskytuje %1$s</string>
<string name="filter">Filtr</string>
<!--Episodes apply actions-->
<string name="all_label">Vše</string>
@@ -716,11 +788,22 @@
<string name="cast_failed_receiver_player_error">Přijímač zaznamenal závažnou chybu</string>
<string name="cast_failed_media_error_skipping">Chyba přehrávání médií. Přeskakuji...</string>
<!--Notification channels-->
+ <string name="notification_channel_user_action">Je vyžadována činnost z vaší strany</string>
+ <string name="notification_channel_user_action_description">Zobrazuje se, pokud je požadována činnost z vaší strany. Například je-li potřeba zadat heslo.</string>
<string name="notification_channel_downloading">Stahuji</string>
+ <string name="notification_channel_downloading_description">Zobrazuje se v průběhu stahování.</string>
+ <string name="notification_channel_playing">Přehrává se</string>
+ <string name="notification_channel_playing_description">Umožňuje ovládat přehrávání. Toto je to hlavní oznámení, které uvidité při přehrávání podcastu.</string>
+ <string name="notification_channel_error">Chyby</string>
<string name="notification_channel_error_description">Zobrazuje se, když se něco nepovedlo. Například pokud selhalo stahování anebo synchronizace gpodder.</string>
+ <string name="notification_channel_auto_download">Automatické stahování</string>
+ <string name="notification_channel_episode_auto_download">Zobrazuje se po automatickém stažení epizod.</string>
<!--Widget settings-->
+ <string name="widget_settings">Nastavení widgetu</string>
+ <string name="widget_create_button">Vytvořit widget</string>
<string name="widget_opacity">Průhlednost</string>
<!--On-Demand configuration-->
+ <string name="on_demand_config_setting_changed">Nastavení úspěšně aktualizováno</string>
<string name="on_demand_config_stream_text"> Vypadá to, že častěji streamujete než stahujete. Chcete zobrazovat tlačítko streamovat v seznamu epizod? </string>
<string name="on_demand_config_download_text">Vypadá to, že častěji stahujete než streamujete. Chcete zobrazovat tlačítko stáhnout v seznamu epizod?</string>
</resources>
diff --git a/core/src/main/res/values-eu/strings.xml b/core/src/main/res/values-eu/strings.xml
index 6c0973739..e4b4fe4b6 100644
--- a/core/src/main/res/values-eu/strings.xml
+++ b/core/src/main/res/values-eu/strings.xml
@@ -509,8 +509,11 @@
<!--About screen-->
<string name="about_pref">Honi buruz</string>
<string name="antennapod_version">AntennaPod bertsioa</string>
+ <string name="contributors">Laguntzaileak</string>
+ <string name="contributors_summary">Denek lagun dezakete gure foroan kodea, itzulpenak edo erabiltzaileei laguntza emanez.</string>
<string name="developers">Garatzaileak</string>
<string name="translators">Itzultzaileak</string>
+ <string name="special_thanks">Esker bereziak</string>
<string name="privacy_policy">Pribatutasun politika</string>
<string name="licenses">Baimenak</string>
<string name="licenses_summary">AntennaPod-ek beste software ezin hobeak erabiltzen ditu</string>
@@ -554,6 +557,8 @@
<string name="import_select_file">Aukeratu inportatzeko fitxategia</string>
<string name="import_ok">Inportazio arrakastatsua.\n\nSakatu OK, AntennaPod berrabiarazteko</string>
<string name="import_no_downgrade">Datu-basea AntennaPod-en bertsio berriago batekin esportatu zen. Uneko aplikazioak ez daki nola inportatu.</string>
+ <string name="favorites_export_label">Gogokoak esportatu</string>
+ <string name="favorites_export_summary">Gorde diren gogokoak esportatu artxibatzeko</string>
<!--Sleep timer-->
<string name="set_sleeptimer_label">Ezarri tenporizadore bat</string>
<string name="disable_sleeptimer_label">Desgaitu tenporizadorea</string>
diff --git a/core/src/main/res/values-fa/strings.xml b/core/src/main/res/values-fa/strings.xml
index a418d834c..0ac3b684d 100644
--- a/core/src/main/res/values-fa/strings.xml
+++ b/core/src/main/res/values-fa/strings.xml
@@ -85,6 +85,7 @@
<string name="auto_download_apply_to_items_message">تنظیمات جدید <i>بارگیری خودکار</i> به طور خودکار بر قسمت‌های جدید اعمال خواهد شد.\nآیا می‌خواهید بر قسمت‌هایی قبلاً منتشر شده هم اعمال شود؟</string>
<string name="auto_delete_label">حذف خودکار قسمت</string>
<string name="feed_volume_reduction">کم کردن صدا</string>
+ <string name="feed_volume_reduction_summary">برای قسمت‌های این خوراک، صدا کم شود: %1$s</string>
<string name="feed_volume_reduction_off">خاموش</string>
<string name="feed_volume_reduction_light">سبک</string>
<string name="feed_volume_reduction_heavy">سنگین</string>
@@ -204,6 +205,7 @@
<string name="deactivate_auto_download">غیر فعال کردن بارگیری خودکار</string>
<string name="reset_position">تنظیم مجدد موقعیت پخش</string>
<string name="removed_item">مورد حذف شده است</string>
+ <string name="no_items_selected">چیزی انتخاب نشده است</string>
<!--Download messages and labels-->
<string name="download_successful">موفقیت‌آمیز</string>
<string name="download_pending">بارگیری معوق</string>
@@ -324,6 +326,8 @@
<string name="storage_sum">حذف خودکار قسمت، درون‌ریزی، برون‌ریزی</string>
<string name="project_pref">پروژه</string>
<string name="queue_label">صف</string>
+ <string name="synchronization_pref">هم‌گام‌سازی</string>
+ <string name="synchronization_sum">با کمک gpodder.net با دستگاه‌های دیگر هم‌گام کنید</string>
<string name="automation">اتوماسیون</string>
<string name="download_pref_details">جزئیات</string>
<string name="import_export_pref">وارد/صادر کرد</string>
diff --git a/core/src/main/res/values-pl/strings.xml b/core/src/main/res/values-pl/strings.xml
index 1043b58d8..f5fa5e310 100644
--- a/core/src/main/res/values-pl/strings.xml
+++ b/core/src/main/res/values-pl/strings.xml
@@ -323,7 +323,7 @@
<!--Empty list labels-->
<string name="no_items_header_label">Brak odcinków w kolejce</string>
<string name="no_items_label">Dodaj odcinek, pobierając go, lub przytrzymaj dłużej na odcinku i wybierz \"Dodaj do kolejki\".</string>
- <string name="no_shownotes_label">Ten epizod nie ma notatek.</string>
+ <string name="no_shownotes_label">Ten odcinek nie ma notatek.</string>
<string name="no_run_downloads_head_label">Brak aktywnych pobierań</string>
<string name="no_run_downloads_label">Możesz pobrać odcinki z ekranu informacji o podcaście</string>
<string name="no_comp_downloads_head_label">Brak pobranych odcinków</string>
@@ -528,8 +528,10 @@
<!--About screen-->
<string name="about_pref">O...</string>
<string name="antennapod_version">Wersja AntennaPod</string>
+ <string name="contributors">Kontrybutorzy</string>
<string name="developers">Twórcy</string>
<string name="translators">Tłumacze</string>
+ <string name="special_thanks">Specjalne podziękowania</string>
<string name="privacy_policy">Polityka prywatności</string>
<string name="licenses">Licencje</string>
<string name="licenses_summary">AntennaPod używa różnego świetnego oprogramowania/bibliotek</string>
@@ -573,6 +575,8 @@
<string name="import_select_file">Wybierz plik do Importowania</string>
<string name="import_ok">Import zakończony powodzeniem.\n\nNaciśnij OK aby zrestartować AntennaPod</string>
<string name="import_no_downgrade">Baza danych została eksportowana z nowszej wersji AntennaPod. Twoja wersja nie potrafi obsłużyć tego pliku. </string>
+ <string name="favorites_export_label">Eksport ulubionych</string>
+ <string name="favorites_export_summary">Ulubione wyeksportowano do pliku</string>
<!--Sleep timer-->
<string name="set_sleeptimer_label">Ustaw czas do wyłączenia</string>
<string name="disable_sleeptimer_label">Wyłącz wyłącznik czasowy</string>
diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml
index 1d36dc272..59e3af044 100644
--- a/core/src/main/res/values-pt-rBR/strings.xml
+++ b/core/src/main/res/values-pt-rBR/strings.xml
@@ -384,6 +384,7 @@
<string name="pref_mobileUpdate_episode_download">Download de episódios</string>
<string name="pref_mobileUpdate_streaming">Streaming</string>
<string name="user_interface_label">Interface com usuário</string>
+ <string name="user_interface_sum">Aparência, pedidos de assinatura, tela de bloqueio</string>
<string name="pref_set_theme_title">Selecionar tema</string>
<string name="pref_nav_drawer_items_title">Configurar itens da Gaveta de Navegação</string>
<string name="pref_nav_drawer_items_sum">Escolher quais itens irão aparecer na gaveta de navegação.</string>
@@ -400,6 +401,10 @@
<string name="pref_automatic_download_on_battery_sum">Permitir download automático enquanto a bateria não está carregando</string>
<string name="pref_parallel_downloads_title">Downloads paralelos</string>
<string name="pref_episode_cache_title">Cache de episódios</string>
+ <string name="pref_episode_cache_summary">Número total de episódios baixados em cache no dispositivo. O download automático será suspenso se esse número for atingido.</string>
+ <string name="pref_episode_cover_title">Usar capa do episódio</string>
+ <string name="pref_episode_cover_summary">Use a capa específica do episódio sempre que disponível. Se desmarcado, o aplicativo sempre usará a imagem da capa do podcast.</string>
+ <string name="pref_theme_title_use_system">Usar tema do sistema</string>
<string name="pref_theme_title_light">Claro</string>
<string name="pref_theme_title_dark">Escuro</string>
<string name="pref_theme_title_trueblack">Preto (preparado para AMOLED)</string>
@@ -415,12 +420,22 @@
<string name="pref_gpodnet_setlogin_information_sum">Alterar informações de login da sua conta gpodder.net</string>
<string name="pref_gpodnet_sync_changes_title">Sincronizar agora</string>
<string name="pref_gpodnet_sync_changes_sum">Sincronizar as alterações de estado da inscrição e de episódios com o gpodder.net.</string>
+ <string name="pref_gpodnet_full_sync_title">Forçar sincronização completa</string>
<string name="pref_gpodnet_full_sync_sum">Sincronizar os estados das inscrições e episódios com o gpodder.net.</string>
<string name="pref_gpodnet_login_status"><![CDATA[Entrou como <i>%1$s</i> com o dispositivo <i>%2$s</i>]]></string>
<string name="pref_gpodnet_notifications_title">Exibir notificações de erros de sincronismo</string>
<string name="pref_gpodnet_notifications_sum">Essa configuração não se aplica a erros de autenticação.</string>
<string name="pref_playback_speed_title">Velocidades de Reprodução</string>
<string name="pref_playback_speed_sum">Personalize as velocidades variáveis de reprodução de áudio.</string>
+ <string name="pref_feed_playback_speed_sum">A velocidade a ser usada ao iniciar a reprodução de áudio para episódios neste podcast</string>
+ <string name="pref_feed_skip">Salto automático</string>
+ <string name="pref_feed_skip_sum">Pule as introduções e os créditos finais.</string>
+ <string name="pref_feed_skip_ending">Pular últimos</string>
+ <string name="pref_feed_skip_intro">Pular primeiros</string>
+ <string name="pref_feed_skip_ending_toast">Pulou últimos %d segundos</string>
+ <string name="pref_feed_skip_intro_toast">Pulou os primeiros %d segundos</string>
+ <string name="pref_playback_time_respects_speed_title">Ajuste as informações da mídia para a velocidade de reprodução</string>
+ <string name="pref_playback_time_respects_speed_sum">A posição exibida e a duração são adaptadas à velocidade de reprodução</string>
<string name="pref_fast_forward">Tempo de avanço rápido</string>
<string name="pref_fast_forward_sum">Personalize os segundos para avançar quando o botão avanço rápido for clicado</string>
<string name="pref_rewind">Tempo de retroceder</string>
@@ -439,15 +454,29 @@
<string name="pref_lockscreen_background_sum">Configurar o plano de fundo da tela de bloqueio para a imagem do episódio atual. Como um efeito colateral, também ira mostrar imagens de aplicativos de terceiros.</string>
<string name="pref_showDownloadReport_title">Mostrar Relatório de Downloads</string>
<string name="pref_showDownloadReport_sum">Se os downloads falharem, gerar um relatório que mostra os detalhes da falha.</string>
+ <string name="pref_showAutoDownloadReport_title">Mostrar relatório de downloads automáticos</string>
+ <string name="pref_showAutoDownloadReport_sum">Mostra uma notificação para episódios baixados automaticamente.</string>
<string name="pref_expand_notify_unsupport_toast">Versões do Android inferiores a 4.1 não suportam notificações expansíveis</string>
+ <string name="pref_enqueue_location_title">Local da fila</string>
+ <string name="pref_enqueue_location_sum">Adicionar episódios para: %1$s</string>
+ <string name="enqueue_location_back">Final</string>
+ <string name="enqueue_location_front">Início</string>
+ <string name="enqueue_location_after_current">Depois do episódio atual</string>
<string name="pref_smart_mark_as_played_disabled">Desabilitado</string>
<string name="pref_image_cache_size_title">Tamanho da Imagem em Cache</string>
<string name="pref_image_cache_size_sum">Tamanho do cache de disco para imagens.</string>
+ <string name="visit_user_forum">Fórum de usuários</string>
+ <string name="bug_report_title">Reportar um bug</string>
+ <string name="open_bug_tracker">Abrir registro de bugs</string>
+ <string name="export_logs">Exportar logs</string>
+ <string name="copy_to_clipboard">Copiar para clipboard</string>
+ <string name="copied_to_clipboard">Copiado para clipboard</string>
<string name="experimental_pref">Experimental</string>
<string name="pref_media_player_message">Selecione qual reprodutor de mídia usar para reproduzir os arquivos</string>
<string name="pref_current_value">Valor atual: %1$s</string>
<string name="pref_proxy_title">Proxy</string>
<string name="pref_proxy_sum">Configurar um proxy da rede</string>
+ <string name="pref_faq">Perguntas mais frequentes</string>
<string name="pref_no_browser_found">Nenhum navegador web encontrado.</string>
<string name="pref_cast_title">Suporte ao Chromecast</string>
<string name="pref_cast_message_play_flavor">Habilitar o suporte para reprodução remota de mídia em dispositivos Cast (como Chromecast, Caixa de som ou Android TV)</string>
@@ -455,6 +484,8 @@
<string name="pref_enqueue_downloaded_title">Enfileirar os baixados</string>
<string name="pref_enqueue_downloaded_summary">Adicionar episódios baixados à fila</string>
<string name="media_player_builtin">Reprodutor próprio do Android</string>
+ <string name="media_player_switch_to_exoplayer">Alterar para ExoPlayer</string>
+ <string name="media_player_switched_to_exoplayer">Alterado para ExoPlayer</string>
<string name="pref_skip_silence_title">Pular silêncio no áudio</string>
<string name="pref_videoBehavior_title">Após fechar vídeo</string>
<string name="pref_videoBehavior_sum">Comportamento ao parar a reprodução de vídeo</string>
diff --git a/core/src/main/res/values-zh-rTW/strings.xml b/core/src/main/res/values-zh-rTW/strings.xml
index 9d809f88d..0b3f88797 100644
--- a/core/src/main/res/values-zh-rTW/strings.xml
+++ b/core/src/main/res/values-zh-rTW/strings.xml
@@ -40,8 +40,8 @@
<string name="drawer_open">打開選單</string>
<string name="drawer_close">關閉選單</string>
<string name="drawer_preferences">側邊選單設定</string>
- <string name="drawer_feed_order_unplayed_episodes">按數量排序</string>
- <string name="drawer_feed_order_alphabetical">按字母表排序</string>
+ <string name="drawer_feed_order_unplayed_episodes">按計數器排序</string>
+ <string name="drawer_feed_order_alphabetical">按字母排序</string>
<string name="drawer_feed_order_last_update">按發布日期排序</string>
<string name="drawer_feed_order_most_played">按已播放的集數排序</string>
<string name="drawer_feed_counter_new_unplayed">新增及未播放集數</string>
@@ -319,7 +319,7 @@
<string name="synchronization_pref">同步</string>
<string name="synchronization_sum">利用 gpodder.net 與其他裝置同步</string>
<string name="automation">自動化</string>
- <string name="download_pref_details">詳情</string>
+ <string name="download_pref_details">細節</string>
<string name="import_export_pref">匯入/匯出</string>
<string name="import_export_search_keywords">備份, 還原, backup, restore, export, import, 匯出, 匯入</string>
<string name="appearance">外觀</string>
@@ -351,10 +351,10 @@
<string name="playback_pref">播放</string>
<string name="playback_pref_sum">耳機線控、快轉時間、待播清單</string>
<string name="network_pref">網路</string>
- <string name="network_pref_sum">更新週期、下載控制、行動數據</string>
+ <string name="network_pref_sum">更新週期、下載控制、行動網路</string>
<string name="pref_autoUpdateIntervallOrTime_title">更新週期</string>
<string name="pref_autoUpdateIntervallOrTime_sum">設定 Podcast 節目清單的更新週期</string>
- <string name="pref_autoUpdateIntervallOrTime_message">您可以設定「每 2 小時」這類的<i>週期</i>或指定「每天早上 7 點」這種<i>每日定時</i>,也也可以<i>停用</i> 自動更新。\n\n<small>請注意:這裡的時間並非十分精準,可能會有些許延遲。</small></string>
+ <string name="pref_autoUpdateIntervallOrTime_message">您可以設定「每 2 小時」這類的<i>週期</i>或指定「每天早上 7 點」這種<i>每日定時</i>,也可以<i>停用</i> 自動更新。\n\n<small>請注意:這裡的時間並非十分精準,可能會有些許延遲。</small></string>
<string name="pref_autoUpdateIntervallOrTime_Disable">停用</string>
<string name="pref_autoUpdateIntervallOrTime_Interval">設定週期</string>
<string name="pref_autoUpdateIntervallOrTime_TimeOfDay">設定每日定時</string>
@@ -366,20 +366,20 @@
<string name="pref_unpauseOnBluetoothReconnect_title">連上藍牙時繼續播放</string>
<string name="pref_stream_over_download_title">偏好串流</string>
<string name="pref_stream_over_download_sum">在清單中顯示串流播放按鈕取代下載鈕</string>
- <string name="pref_mobileUpdate_title">行動網路更新</string>
+ <string name="pref_mobileUpdate_title">允許以行動網路…</string>
<string name="pref_mobileUpdate_sum">選擇以行動網路連線時可以做的事</string>
<string name="pref_mobileUpdate_refresh">更新 Podcast</string>
- <string name="pref_mobileUpdate_images">封面</string>
+ <string name="pref_mobileUpdate_images">更新封面圖</string>
<string name="pref_mobileUpdate_auto_download">自動下載</string>
<string name="pref_mobileUpdate_episode_download">下載單集</string>
<string name="pref_mobileUpdate_streaming">串流播放</string>
<string name="user_interface_label">使用者介面</string>
- <string name="user_interface_sum">外觀、訂閱順序、鎖定畫面</string>
+ <string name="user_interface_sum">外觀、訂閱排序、鎖定畫面</string>
<string name="pref_set_theme_title">選擇主題</string>
<string name="pref_nav_drawer_items_title">設定側邊選單</string>
<string name="pref_nav_drawer_items_sum">調整側邊選單裡要顯示的項目</string>
- <string name="pref_nav_drawer_feed_order_title">設定訂閱順序</string>
- <string name="pref_nav_drawer_feed_order_sum">更改您的訂閱順序</string>
+ <string name="pref_nav_drawer_feed_order_title">設定訂閱排序方式</string>
+ <string name="pref_nav_drawer_feed_order_sum">更改您訂閱頻道的排序方式</string>
<string name="pref_nav_drawer_feed_counter_title">設定訂閱計數器</string>
<string name="pref_nav_drawer_feed_counter_sum">調整訂閱計數器中要顯示的東西,同時也會在排序方式設定為「計數」時影響排序。</string>
<string name="pref_set_theme_sum">更改 AntennaPod 的外觀</string>
@@ -394,12 +394,12 @@
<string name="pref_episode_cache_summary">在本機中可以暫存的集數,若達上限則將停止自動下載。</string>
<string name="pref_episode_cover_title">使用單集的封面圖</string>
<string name="pref_episode_cover_summary">在單集有專屬封面的情況下使用該封面圖。如果取消,則一律使用 Podcast 的封面圖。</string>
- <string name="pref_theme_title_use_system">使用系統主題</string>
+ <string name="pref_theme_title_use_system">依據系統設定</string>
<string name="pref_theme_title_light">淡色</string>
<string name="pref_theme_title_dark">深色</string>
<string name="pref_theme_title_trueblack">黑色 (適用 AMOLED 螢幕)</string>
<string name="pref_episode_cache_unlimited">無限</string>
- <string name="pref_update_interval_hours_plural">時數</string>
+ <string name="pref_update_interval_hours_plural">小時</string>
<string name="pref_update_interval_hours_singular">小時</string>
<string name="pref_update_interval_hours_manual">手動</string>
<string name="pref_gpodnet_authenticate_title">登入</string>
@@ -490,7 +490,7 @@
<string name="back_button_show_prompt">離開前需要確認</string>
<string name="close_prompt">確定關閉 AntennaPod?</string>
<string name="double_tap_toast">重按返回鍵以離開</string>
- <string name="back_button_go_to_page">前往頁面...</string>
+ <string name="back_button_go_to_page">前往頁面…</string>
<string name="back_button_go_to_page_title">選擇頁面</string>
<string name="pref_delete_removes_from_queue_title">刪除時同步自待播清單中移除</string>
<string name="pref_delete_removes_from_queue_sum">刪除某單集後,也自動將其從待播清單中移除</string>
@@ -693,7 +693,7 @@
<string name="sort_title_a_z">標題 (A \u2192 Z)</string>
<string name="sort_title_z_a">標題 (Z \u2192 A)</string>
<string name="sort_date_new_old">日期 (新 \u2192 舊)</string>
- <string name="sort_date_old_new">標題 (舊 \u2192 新)</string>
+ <string name="sort_date_old_new">日期 (舊 \u2192 新)</string>
<string name="sort_duration_short_long">單集時間 (短 \u2192 長)</string>
<string name="sort_duration_long_short">單集時間 (長 \u2192 短)</string>
<string name="sort_a_z">A \u2192 Z</string>